blob: b0faa9b4f85e61992abaf4061091ecc7551d3bbb [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"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
Corentin Wallezf0e89be2017-11-08 14:00:32 -080069 TextureType type = texture->getType();
70 if (!ValidMipLevel(context, type, level))
Martin Radev137032d2017-07-13 10:11:12 +030071 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
Corentin Wallezf0e89be2017-11-08 14:00:32 -080076 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
Martin Radev137032d2017-07-13 10:11:12 +030077 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800140 TextureType target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800174 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
Geoff Langca271392017-04-05 12:30:00 -0400175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800201 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800218 TextureType texType = TextureTargetToType(target);
219
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 // Validate image size
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800221 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500223 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 }
226
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 // Verify zero border
228 if (border != 0)
229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
Jamie Madill6f38f822014-06-06 17:12:20 -0400234 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
235 std::numeric_limits<GLsizei>::max() - xoffset < width ||
236 std::numeric_limits<GLsizei>::max() - yoffset < height ||
237 std::numeric_limits<GLsizei>::max() - zoffset < depth)
238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500239 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400240 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400241 }
242
Geoff Langaae65a42014-05-26 12:43:44 -0400243 const gl::Caps &caps = context->getCaps();
244
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800245 switch (texType)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800247 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800248 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
249 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500251 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800252 return false;
253 }
254 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800256 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257 ASSERT(level == 0);
258 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
259 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
260 {
261 context->handleError(InvalidValue());
262 return false;
263 }
264 if (isCompressed)
265 {
266 context->handleError(InvalidEnum()
267 << "Rectangle texture cannot have a compressed format.");
268 return false;
269 }
270 break;
271
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800272 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800273 if (!isSubImage && width != height)
274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500275 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800276 return false;
277 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400278
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500281 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 return false;
283 }
284 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800286 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800287 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
288 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
289 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500291 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800292 return false;
293 }
294 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800296 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800297 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
298 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
299 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500301 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800302 return false;
303 }
304 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305
He Yunchaoced53ae2016-11-29 15:00:51 +0800306 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500307 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 }
310
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800311 gl::Texture *texture = context->getTargetTexture(texType);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 if (!texture)
313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 }
317
Geoff Lang69cce582015-09-17 13:20:36 -0400318 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
324 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400325 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400326 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500327 if (isSubImage && actualInternalFormat == GL_NONE)
328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500330 return false;
331 }
332
Geoff Langc4e93662017-05-01 10:45:59 -0400333 const gl::InternalFormat &actualFormatInfo = isSubImage
334 ? *texture->getFormat(target, level).info
335 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 if (isCompressed)
337 {
tmartino7c102692015-10-02 16:43:40 -0400338 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500340 context->handleError(
341 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400342 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 }
344
Geoff Lang966c9402017-04-18 12:38:27 -0400345 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 {
Geoff Lang966c9402017-04-18 12:38:27 -0400347 if (!ValidCompressedSubImageSize(
348 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
349 texture->getWidth(target, level), texture->getHeight(target, level)))
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400352 return false;
353 }
354
355 if (format != actualInternalFormat)
356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500357 context->handleError(InvalidOperation()
358 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400359 return false;
360 }
Geoff Lang86f81162017-10-30 15:10:45 -0400361
362 if (actualInternalFormat == GL_ETC1_RGB8_OES)
363 {
364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
365 return false;
366 }
Geoff Lang966c9402017-04-18 12:38:27 -0400367 }
368 else
369 {
370 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500372 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400373 return false;
374 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 }
376
Geoff Langeb66a6e2016-10-31 13:06:12 -0400377 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500379 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400380 return false;
381 }
382
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800383 if (texType == TextureType::_3D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388 }
389 else
390 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800391 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
392 type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 {
Geoff Lang5d601382014-07-22 15:14:06 -0400394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 }
397
398 // Validate sub image parameters
399 if (isSubImage)
400 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500401 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500403 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 }
406
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500409 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 }
412
413 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
414 std::numeric_limits<GLsizei>::max() - yoffset < height ||
415 std::numeric_limits<GLsizei>::max() - zoffset < depth)
416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420
Geoff Langa9be0dc2014-12-17 12:34:40 -0500421 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
422 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
423 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500425 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 }
Geoff Langfb052642017-10-24 13:42:09 -0400428
429 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400430 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400431 {
432 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
433 return false;
434 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 }
436
Geoff Langdbcced82017-06-06 15:55:54 -0400437 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800438 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
Geoff Langdbcced82017-06-06 15:55:54 -0400439 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400440 {
441 return false;
442 }
443
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400444 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400445 gl::Buffer *pixelUnpackBuffer =
446 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400447 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400448 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 // ...data is not evenly divisible into the number of bytes needed to store in memory a
450 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400451 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400452 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400453 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400454 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400455 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
456
Geoff Langff5b2d52016-09-07 11:32:23 -0400457 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500459 context->handleError(InvalidOperation()
460 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 return false;
462 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400463 }
464
Jamie Madill7a5f7382014-03-05 15:01:24 -0500465 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700466 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500468 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400469 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500470 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400471 }
472
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400473 return true;
474}
475
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500476bool ValidateES3TexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800477 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500478 GLint level,
479 GLenum internalformat,
480 bool isCompressed,
481 bool isSubImage,
482 GLint xoffset,
483 GLint yoffset,
484 GLint zoffset,
485 GLsizei width,
486 GLsizei height,
487 GLsizei depth,
488 GLint border,
489 GLenum format,
490 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400491 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400492 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500493{
494 if (!ValidTexture2DDestinationTarget(context, target))
495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500496 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500497 return false;
498 }
499
500 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
501 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400502 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500503}
504
505bool ValidateES3TexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800506 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500507 GLint level,
508 GLenum internalformat,
509 bool isCompressed,
510 bool isSubImage,
511 GLint xoffset,
512 GLint yoffset,
513 GLint zoffset,
514 GLsizei width,
515 GLsizei height,
516 GLsizei depth,
517 GLint border,
518 GLenum format,
519 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400520 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400521 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522{
523 if (!ValidTexture3DDestinationTarget(context, target))
524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500525 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526 return false;
527 }
528
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 if (IsETC2EACFormat(format) && target != TextureType::_2DArray)
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500530 {
531 // ES 3.1, Section 8.7, page 169.
532 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
533 return false;
534 }
535
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800536 return ValidateES3TexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
537 internalformat, isCompressed, isSubImage, xoffset,
538 yoffset, zoffset, width, height, depth, border, format,
539 type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540}
541
Geoff Lang5d601382014-07-22 15:14:06 -0400542struct EffectiveInternalFormatInfo
543{
Jamie Madill76648fe2016-10-05 17:01:41 -0400544 GLenum effectiveFormat;
545 GLenum destFormat;
546 GLuint minRedBits;
547 GLuint maxRedBits;
548 GLuint minGreenBits;
549 GLuint maxGreenBits;
550 GLuint minBlueBits;
551 GLuint maxBlueBits;
552 GLuint minAlphaBits;
553 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400554};
555
Jamie Madill76648fe2016-10-05 17:01:41 -0400556static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
557 GLenum targetFormat,
558 const EffectiveInternalFormatInfo *list,
559 size_t size,
560 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400561{
Jamie Madill76648fe2016-10-05 17:01:41 -0400562 for (size_t curFormat = 0; curFormat < size; ++curFormat)
563 {
564 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
565 if ((formatInfo.destFormat == targetFormat) &&
566 (formatInfo.minRedBits <= srcFormat.redBits &&
567 formatInfo.maxRedBits >= srcFormat.redBits) &&
568 (formatInfo.minGreenBits <= srcFormat.greenBits &&
569 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
570 (formatInfo.minBlueBits <= srcFormat.blueBits &&
571 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
572 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
573 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
574 {
575 *outEffectiveFormat = formatInfo.effectiveFormat;
576 return true;
577 }
578 }
Geoff Lang5d601382014-07-22 15:14:06 -0400579
Jamie Madill76648fe2016-10-05 17:01:41 -0400580 *outEffectiveFormat = GL_NONE;
581 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400582}
583
Jamie Madill76648fe2016-10-05 17:01:41 -0400584bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
585 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400586{
Jamie Madill76648fe2016-10-05 17:01:41 -0400587 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
588 // Effective internal format coresponding to destination internal format and linear source
589 // buffer component sizes.
590 // | Source channel min/max sizes |
591 // Effective Internal Format | N/A | R | G | B | A |
592 // clang-format off
593 constexpr EffectiveInternalFormatInfo list[] = {
594 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
595 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
596 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
597 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
598 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
599 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
600 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
601 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
602 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
603 };
604 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400605
Jamie Madill76648fe2016-10-05 17:01:41 -0400606 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
607}
Geoff Lang5d601382014-07-22 15:14:06 -0400608
Jamie Madill76648fe2016-10-05 17:01:41 -0400609bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
610 const InternalFormat &destFormat,
611 GLenum *outEffectiveFormat)
612{
613 constexpr GLuint umax = UINT_MAX;
614
615 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
616 // Effective internal format coresponding to destination internal format andlinear source buffer
617 // component sizes.
618 // | Source channel min/max sizes |
619 // Effective Internal Format | Dest Format | R | G | B | A |
620 // clang-format off
621 constexpr EffectiveInternalFormatInfo list[] = {
622 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
623 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
624 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
625 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
626 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
627 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
628 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
629 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
630 };
631 // clang-format on
632
633 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
634 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400635}
636
He Yunchaoced53ae2016-11-29 15:00:51 +0800637static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
638 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400639 GLenum *outEffectiveFormat)
640{
Geoff Langca271392017-04-05 12:30:00 -0400641 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400642 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400643 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400644 }
645 else
646 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400647 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400648 }
Geoff Lang5d601382014-07-22 15:14:06 -0400649}
650
Corentin Wallez76287682016-04-25 09:23:38 -0400651static bool EqualOrFirstZero(GLuint first, GLuint second)
652{
653 return first == 0 || first == second;
654}
655
Geoff Langca271392017-04-05 12:30:00 -0400656static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
657 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400658 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400659{
Jamie Madill21b786b2016-11-01 17:41:31 -0400660 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400661 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400662 return false;
663 }
Geoff Lang5d601382014-07-22 15:14:06 -0400664
Jamie Madill21b786b2016-11-01 17:41:31 -0400665 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
666 // must both be signed, unsigned, or fixed point and both source and destinations
667 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
668 // conversion between fixed and floating point.
669
670 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
671 (framebufferFormatInfo.colorEncoding == GL_SRGB))
672 {
673 return false;
674 }
675
676 if (((textureFormatInfo.componentType == GL_INT) !=
677 (framebufferFormatInfo.componentType == GL_INT)) ||
678 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
679 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
680 {
681 return false;
682 }
683
684 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
685 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
686 textureFormatInfo.componentType == GL_FLOAT) &&
687 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
688 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
689 framebufferFormatInfo.componentType == GL_FLOAT))
690 {
691 return false;
692 }
693
694 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
695 // The effective internal format of the source buffer is determined with the following rules
696 // applied in order:
697 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
698 // format then the effective internal format is the source buffer's sized internal format.
699 // * If the source buffer is a texture that was created with an unsized base internal format,
700 // then the effective internal format is the source image array's effective internal
701 // format, as specified by table 3.12, which is determined from the <format> and <type>
702 // that were used when the source image array was specified by TexImage*.
703 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
704 // where Destination Internal Format matches internalformat and where the [source channel
705 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
706 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
707 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800708 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400709 if (readBufferHandle != 0)
710 {
711 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
712 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400713 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400714 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400715 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400716 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 else
Geoff Lang5d601382014-07-22 15:14:06 -0400718 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 // Renderbuffers cannot be created with an unsized internal format, so this must be an
720 // unsized-format texture. We can use the same table we use when creating textures to
721 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400722 sourceEffectiveFormat =
723 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400724 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400725 }
726 else
727 {
728 // The effective internal format must be derived from the source framebuffer's channel
729 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
730 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400731 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400732 GLenum effectiveFormat;
733 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
734 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400735 {
Geoff Langca271392017-04-05 12:30:00 -0400736 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400737 }
738 else
739 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400740 return false;
741 }
742 }
743 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
744 {
745 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400746 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400747 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
748 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
749 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
750 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
751 {
Geoff Langca271392017-04-05 12:30:00 -0400752 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400753 }
754 else
755 {
756 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400757 }
758 }
759 else
760 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400761 UNREACHABLE();
762 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400763 }
Geoff Lang5d601382014-07-22 15:14:06 -0400764 }
765
Geoff Langca271392017-04-05 12:30:00 -0400766 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400767 {
768 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
769 // sized, component sizes of the source and destination formats must exactly match if the
770 // destination format exists.
771 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
772 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
773 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
774 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
775 {
776 return false;
777 }
778 }
779
780 return true; // A conversion function exists, and no rule in the specification has precluded
781 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400782}
783
Jamie Madill5b772312018-03-08 20:28:32 -0500784bool ValidateES3CopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800785 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786 GLint level,
787 GLenum internalformat,
788 bool isSubImage,
789 GLint xoffset,
790 GLint yoffset,
791 GLint zoffset,
792 GLint x,
793 GLint y,
794 GLsizei width,
795 GLsizei height,
796 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400798 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400799 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 xoffset, yoffset, zoffset, x, y, width, height, border,
801 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400802 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400803 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400805 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806
Jamie Madill51f40ec2016-06-15 14:06:00 -0400807 const auto &state = context->getGLState();
808 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
809 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400810
Jamie Madill427064d2018-04-13 16:20:34 -0400811 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400814 }
815
Jamie Madille98b1b52018-03-08 09:47:23 -0500816 if (readFramebufferID != 0 && !ValidateFramebufferNotMultisampled(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400817 {
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400819 }
820
Jamie Madill0c8abca2016-07-22 20:21:26 -0400821 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822
Yunchao He096a6c82018-02-27 23:48:21 +0800823 // According to ES 3.x spec, if the internalformat of the texture
824 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
825 if (textureFormat.info->internalFormat == GL_RGB9_E5)
826 {
827 context->handleError(InvalidOperation());
828 return false;
829 }
830
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 if (isSubImage)
832 {
Geoff Langca271392017-04-05 12:30:00 -0400833 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500834 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500836 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 }
839 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400840 else
841 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400842 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400843 const InternalFormat &framebufferFormat = *source->getFormat().info;
844 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400845 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500847 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400849 }
850 }
851
Geoff Lang784a8fd2013-09-24 12:33:16 -0400852 // If width or height is zero, it is a no-op. Return false without setting an error.
853 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854}
855
Jamie Madill5b772312018-03-08 20:28:32 -0500856bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800857 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500858 GLint level,
859 GLenum internalformat,
860 bool isSubImage,
861 GLint xoffset,
862 GLint yoffset,
863 GLint zoffset,
864 GLint x,
865 GLint y,
866 GLsizei width,
867 GLsizei height,
868 GLint border)
869{
870 if (!ValidTexture2DDestinationTarget(context, target))
871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500872 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500873 return false;
874 }
875
876 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
877 xoffset, yoffset, zoffset, x, y, width, height,
878 border);
879}
880
Jamie Madill5b772312018-03-08 20:28:32 -0500881bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800882 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 GLint level,
884 GLenum internalformat,
885 bool isSubImage,
886 GLint xoffset,
887 GLint yoffset,
888 GLint zoffset,
889 GLint x,
890 GLint y,
891 GLsizei width,
892 GLsizei height,
893 GLint border)
894{
895 if (!ValidTexture3DDestinationTarget(context, target))
896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500897 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898 return false;
899 }
900
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
902 internalformat, isSubImage, xoffset, yoffset,
903 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500904}
905
906bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800907 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500908 GLsizei levels,
909 GLenum internalformat,
910 GLsizei width,
911 GLsizei height,
912 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913{
914 if (width < 1 || height < 1 || depth < 1 || levels < 1)
915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 }
919
Geoff Langb92c1332015-09-04 12:54:55 -0400920 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800921 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400922 {
923 maxDim = std::max(maxDim, depth);
924 }
925
926 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500928 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 }
931
Geoff Langaae65a42014-05-26 12:43:44 -0400932 const gl::Caps &caps = context->getCaps();
933
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 switch (target)
935 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800936 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 {
Geoff Langaae65a42014-05-26 12:43:44 -0400938 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
939 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 }
944 }
945 break;
946
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800947 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400948 {
949 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
950 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
951 {
952 context->handleError(InvalidValue());
953 return false;
954 }
955 }
956 break;
957
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800958 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 if (width != height)
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965
Geoff Langaae65a42014-05-26 12:43:44 -0400966 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400969 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 }
971 }
972 break;
973
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800974 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 {
Geoff Langaae65a42014-05-26 12:43:44 -0400976 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
977 static_cast<GLuint>(height) > caps.max3DTextureSize ||
978 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500980 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400981 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 }
983 }
984 break;
985
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800986 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400987 {
Geoff Langaae65a42014-05-26 12:43:44 -0400988 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
989 static_cast<GLuint>(height) > caps.max2DTextureSize ||
990 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500992 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400993 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400994 }
995 }
996 break;
997
He Yunchaoced53ae2016-11-29 15:00:51 +0800998 default:
999 UNREACHABLE();
1000 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001001 }
1002
Geoff Lang691e58c2014-12-19 17:03:25 -05001003 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 if (!texture || texture->id() == 0)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Geoff Lang69cce582015-09-17 13:20:36 -04001010 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 }
1015
Geoff Langca271392017-04-05 12:30:00 -04001016 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001017 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022
Geoff Langca271392017-04-05 12:30:00 -04001023 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001025 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001026 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 }
1028
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001029 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001030 {
1031 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1032 return false;
1033 }
1034
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 return true;
1036}
1037
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001038bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001039 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001040 GLsizei levels,
1041 GLenum internalformat,
1042 GLsizei width,
1043 GLsizei height,
1044 GLsizei depth)
1045{
1046 if (!ValidTexture2DTarget(context, target))
1047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001049 return false;
1050 }
1051
1052 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1053 height, depth);
1054}
1055
1056bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001057 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001058 GLsizei levels,
1059 GLenum internalformat,
1060 GLsizei width,
1061 GLsizei height,
1062 GLsizei depth)
1063{
1064 if (!ValidTexture3DTarget(context, target))
1065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001066 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001067 return false;
1068 }
1069
1070 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1071 height, depth);
1072}
1073
Corentin Wallezad3ae902018-03-09 13:40:42 -05001074bool ValidateBeginQuery(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001075{
Martin Radev1be913c2016-07-11 17:59:16 +03001076 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001077 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001079 return false;
1080 }
1081
1082 return ValidateBeginQueryBase(context, target, id);
1083}
1084
Corentin Wallezad3ae902018-03-09 13:40:42 -05001085bool ValidateEndQuery(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086{
Martin Radev1be913c2016-07-11 17:59:16 +03001087 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001088 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001090 return false;
1091 }
1092
1093 return ValidateEndQueryBase(context, target);
1094}
1095
Corentin Wallezad3ae902018-03-09 13:40:42 -05001096bool ValidateGetQueryiv(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097{
Martin Radev1be913c2016-07-11 17:59:16 +03001098 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001099 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001101 return false;
1102 }
1103
Geoff Lang2186c382016-10-14 10:54:54 -04001104 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001105}
1106
1107bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1108{
Martin Radev1be913c2016-07-11 17:59:16 +03001109 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001110 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001112 return false;
1113 }
1114
Geoff Lang2186c382016-10-14 10:54:54 -04001115 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001116}
1117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118bool ValidateFramebufferTextureLayer(Context *context,
1119 GLenum target,
1120 GLenum attachment,
1121 GLuint texture,
1122 GLint level,
1123 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001124{
Martin Radev1be913c2016-07-11 17:59:16 +03001125 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001126 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001128 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001129 }
1130
Jamie Madill55ec3b12014-07-03 10:38:57 -04001131 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1132 {
1133 return false;
1134 }
1135
1136 const gl::Caps &caps = context->getCaps();
1137 if (texture != 0)
1138 {
Geoff Lang23e02842017-10-17 13:24:09 -04001139 if (layer < 0)
1140 {
1141 context->handleError(InvalidValue());
1142 return false;
1143 }
1144
Jamie Madill55ec3b12014-07-03 10:38:57 -04001145 gl::Texture *tex = context->getTexture(texture);
1146 ASSERT(tex);
1147
Corentin Wallez99d492c2018-02-27 15:17:10 -05001148 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001149 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001150 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001151 {
1152 if (level > gl::log2(caps.max2DTextureSize))
1153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001156 }
1157
1158 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001160 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001161 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001162 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001163 }
1164 break;
1165
Corentin Wallez99d492c2018-02-27 15:17:10 -05001166 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001167 {
1168 if (level > gl::log2(caps.max3DTextureSize))
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001172 }
1173
1174 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001176 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001178 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001179 }
1180 break;
1181
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001183 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001185 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001186
Corentin Wallez99d492c2018-02-27 15:17:10 -05001187 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001188 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001190 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001191 return false;
1192 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001193 }
1194
1195 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001196}
1197
He Yunchaoced53ae2016-11-29 15:00:51 +08001198bool ValidateInvalidateFramebuffer(Context *context,
1199 GLenum target,
1200 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001201 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202{
Martin Radev1be913c2016-07-11 17:59:16 +03001203 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001206 return false;
1207 }
1208
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001209 bool defaultFramebuffer = false;
1210
1211 switch (target)
1212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 case GL_DRAW_FRAMEBUFFER:
1214 case GL_FRAMEBUFFER:
1215 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1216 break;
1217 case GL_READ_FRAMEBUFFER:
1218 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1219 break;
1220 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1226 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227}
1228
Jamie Madill3ef140a2017-08-26 23:11:21 -04001229bool ValidateInvalidateSubFramebuffer(Context *context,
1230 GLenum target,
1231 GLsizei numAttachments,
1232 const GLenum *attachments,
1233 GLint x,
1234 GLint y,
1235 GLsizei width,
1236 GLsizei height)
1237{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001238 if (width < 0 || height < 0)
1239 {
1240 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1241 return false;
1242 }
1243
Jamie Madill3ef140a2017-08-26 23:11:21 -04001244 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1245}
1246
Jamie Madill5b772312018-03-08 20:28:32 -05001247bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001248{
Martin Radev1be913c2016-07-11 17:59:16 +03001249 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001253 }
1254
Jamie Madill427064d2018-04-13 16:20:34 -04001255 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001256 {
Geoff Langb1196682014-07-23 13:47:29 -04001257 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001258 }
1259
1260 return true;
1261}
1262
Olli Etuaho71dfb362016-03-10 14:04:27 +02001263bool ValidateDrawRangeElements(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001264 PrimitiveMode mode,
Olli Etuaho71dfb362016-03-10 14:04:27 +02001265 GLuint start,
1266 GLuint end,
1267 GLsizei count,
1268 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001269 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001270{
Martin Radev1be913c2016-07-11 17:59:16 +03001271 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001272 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001274 return false;
1275 }
1276
1277 if (end < start)
1278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001280 return false;
1281 }
1282
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001283 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001284 {
1285 return false;
1286 }
1287
Jamie Madill9fdaa492018-02-16 10:52:11 -05001288 // Skip range checks for no-op calls.
1289 if (count <= 0)
1290 {
1291 return true;
1292 }
1293
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001294 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04001295 const DrawCallParams &params = context->getParams<DrawCallParams>();
1296 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001297
Jamie Madill6f5444d2018-03-14 10:08:11 -04001298 const IndexRange &indexRange = params.getIndexRange();
1299
1300 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001301 {
1302 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001304 return false;
1305 }
1306 return true;
1307}
1308
He Yunchaoced53ae2016-11-29 15:00:51 +08001309bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001310{
Martin Radev1be913c2016-07-11 17:59:16 +03001311 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001312 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001315 }
1316
Jamie Madill78f41802014-08-25 15:47:55 -04001317 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001318}
1319
Jamie Madillb885e572015-02-03 16:16:04 -05001320bool ValidateReadBuffer(Context *context, GLenum src)
1321{
Martin Radev1be913c2016-07-11 17:59:16 +03001322 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001323 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001325 return false;
1326 }
1327
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001328 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001329
1330 if (readFBO == nullptr)
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001333 return false;
1334 }
1335
1336 if (src == GL_NONE)
1337 {
1338 return true;
1339 }
1340
Olli Etuaho84c9f592016-03-09 14:37:25 +02001341 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001344 return false;
1345 }
1346
1347 if (readFBO->id() == 0)
1348 {
1349 if (src != GL_BACK)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(
1352 InvalidOperation()
1353 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001354 return false;
1355 }
1356 }
1357 else
1358 {
1359 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1360
1361 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001364 return false;
1365 }
1366 }
1367
1368 return true;
1369}
1370
Jamie Madill86af3d22015-07-21 15:14:07 -04001371bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001372 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001373 GLint level,
1374 GLenum internalformat,
1375 GLsizei width,
1376 GLsizei height,
1377 GLsizei depth,
1378 GLint border,
1379 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001380 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001381{
Martin Radev1be913c2016-07-11 17:59:16 +03001382 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001384 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001385 return false;
1386 }
1387
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001388 if (!ValidTextureTarget(context, target))
1389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001391 return false;
1392 }
1393
Jamie Madille2e406c2016-06-02 13:04:10 -04001394 // Validate image size
1395 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001398 return false;
1399 }
1400
Geoff Langca271392017-04-05 12:30:00 -04001401 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001402 if (!formatInfo.compressed)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001405 return false;
1406 }
1407
Jeff Gilbert48590352017-11-07 16:03:38 -08001408 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001409 if (blockSizeOrErr.isError())
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001412 return false;
1413 }
1414 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001417 return false;
1418 }
1419
1420 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001421 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001424 return false;
1425 }
1426
1427 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001428 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001429 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1430 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001431 {
1432 return false;
1433 }
1434
1435 return true;
1436}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001437
Corentin Wallezb2931602017-04-11 15:58:57 -04001438bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001439 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001440 GLint level,
1441 GLenum internalformat,
1442 GLsizei width,
1443 GLsizei height,
1444 GLsizei depth,
1445 GLint border,
1446 GLsizei imageSize,
1447 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001448 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001449{
1450 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1451 {
1452 return false;
1453 }
1454
1455 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1456 depth, border, imageSize, data);
1457}
1458
Austin Kinrossbc781f32015-10-26 09:27:38 -07001459bool ValidateBindVertexArray(Context *context, GLuint array)
1460{
Martin Radev1be913c2016-07-11 17:59:16 +03001461 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001462 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001464 return false;
1465 }
1466
1467 return ValidateBindVertexArrayBase(context, array);
1468}
1469
Jamie Madilld7576732017-08-26 18:49:50 -04001470bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001471{
Martin Radev1be913c2016-07-11 17:59:16 +03001472 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001473 {
Jamie Madilld7576732017-08-26 18:49:50 -04001474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001475 return false;
1476 }
1477
1478 return true;
1479}
Geoff Langc5629752015-12-07 16:29:04 -05001480
Jiajia Qin6eafb042016-12-27 17:04:07 +08001481static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001482 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001483 GLuint index,
1484 GLuint buffer,
1485 GLintptr offset,
1486 GLsizeiptr size)
1487{
1488 if (context->getClientMajorVersion() < 3)
1489 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001491 return false;
1492 }
1493
1494 if (buffer != 0 && offset < 0)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001497 return false;
1498 }
1499
1500 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1501 !context->isBufferGenerated(buffer))
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 return false;
1505 }
1506
1507 const Caps &caps = context->getCaps();
1508 switch (target)
1509 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001510 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001511 {
1512 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidValue() << "index is greater than or equal to the "
1515 "number of TRANSFORM_FEEDBACK_BUFFER "
1516 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001517 return false;
1518 }
1519 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001522 return false;
1523 }
1524
1525 TransformFeedback *curTransformFeedback =
1526 context->getGLState().getCurrentTransformFeedback();
1527 if (curTransformFeedback && curTransformFeedback->isActive())
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation()
1530 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1531 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 return false;
1533 }
1534 break;
1535 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001536 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001537 {
1538 if (index >= caps.maxUniformBufferBindings)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidValue() << "index is greater than or equal to the "
1541 "number of UNIFORM_BUFFER indexed "
1542 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001543 return false;
1544 }
1545
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001546 ASSERT(caps.uniformBufferOffsetAlignment);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001547 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1548 {
1549 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001550 InvalidValue()
1551 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001552 return false;
1553 }
1554 break;
1555 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001556 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001557 {
1558 if (context->getClientVersion() < ES_3_1)
1559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidEnum()
1561 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001562 return false;
1563 }
1564 if (index >= caps.maxAtomicCounterBufferBindings)
1565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001566 context->handleError(InvalidValue() << "index is greater than or equal to the "
1567 "number of ATOMIC_COUNTER_BUFFER "
1568 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001569 return false;
1570 }
1571 if (buffer != 0 && (offset % 4) != 0)
1572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001573 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001574 return false;
1575 }
1576 break;
1577 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001578 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001579 {
1580 if (context->getClientVersion() < ES_3_1)
1581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidEnum()
1583 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001584 return false;
1585 }
1586 if (index >= caps.maxShaderStorageBufferBindings)
1587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001588 context->handleError(InvalidValue() << "index is greater than or equal to the "
1589 "number of SHADER_STORAGE_BUFFER "
1590 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001591 return false;
1592 }
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001593 ASSERT(caps.shaderStorageBufferOffsetAlignment);
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001594 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001596 context->handleError(InvalidValue() << "offset must be multiple of value of "
1597 "SHADER_STORAGE_BUFFER_OFFSET_"
1598 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001599 return false;
1600 }
1601 break;
1602 }
1603 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001605 return false;
1606 }
1607
1608 return true;
1609}
1610
Corentin Wallez336129f2017-10-17 15:55:40 -04001611bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001612{
1613 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1614}
1615
1616bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001617 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001618 GLuint index,
1619 GLuint buffer,
1620 GLintptr offset,
1621 GLsizeiptr size)
1622{
1623 if (buffer != 0 && size <= 0)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidValue()
1626 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001627 return false;
1628 }
1629 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1630}
1631
Geoff Langc5629752015-12-07 16:29:04 -05001632bool ValidateProgramBinary(Context *context,
1633 GLuint program,
1634 GLenum binaryFormat,
1635 const void *binary,
1636 GLint length)
1637{
Martin Radev1be913c2016-07-11 17:59:16 +03001638 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001639 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001640 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001641 return false;
1642 }
1643
1644 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1645}
1646
1647bool ValidateGetProgramBinary(Context *context,
1648 GLuint program,
1649 GLsizei bufSize,
1650 GLsizei *length,
1651 GLenum *binaryFormat,
1652 void *binary)
1653{
Martin Radev1be913c2016-07-11 17:59:16 +03001654 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001655 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001657 return false;
1658 }
1659
1660 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1661}
1662
Olli Etuahof0fee072016-03-30 15:11:58 +03001663bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001664{
Martin Radev1be913c2016-07-11 17:59:16 +03001665 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001666 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001668 return false;
1669 }
1670
1671 if (GetValidProgram(context, program) == nullptr)
1672 {
1673 return false;
1674 }
1675
1676 switch (pname)
1677 {
1678 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001679 if (value != GL_FALSE && value != GL_TRUE)
1680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001681 context->handleError(InvalidValue()
1682 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001683 return false;
1684 }
Geoff Langc5629752015-12-07 16:29:04 -05001685 break;
1686
Yunchao He61afff12017-03-14 15:34:03 +08001687 case GL_PROGRAM_SEPARABLE:
1688 if (context->getClientVersion() < ES_3_1)
1689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001690 context->handleError(InvalidEnum()
1691 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001692 return false;
1693 }
1694
1695 if (value != GL_FALSE && value != GL_TRUE)
1696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001697 context->handleError(InvalidValue()
1698 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001699 return false;
1700 }
1701 break;
1702
Geoff Langc5629752015-12-07 16:29:04 -05001703 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001704 context->handleError(InvalidEnum()
1705 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001706 return false;
1707 }
1708
1709 return true;
1710}
Jamie Madillc29968b2016-01-20 11:17:23 -05001711
1712bool ValidateBlitFramebuffer(Context *context,
1713 GLint srcX0,
1714 GLint srcY0,
1715 GLint srcX1,
1716 GLint srcY1,
1717 GLint dstX0,
1718 GLint dstY0,
1719 GLint dstX1,
1720 GLint dstY1,
1721 GLbitfield mask,
1722 GLenum filter)
1723{
Martin Radev1be913c2016-07-11 17:59:16 +03001724 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001727 return false;
1728 }
1729
1730 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1731 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001732}
Jamie Madillc29968b2016-01-20 11:17:23 -05001733
Jamie Madill5b772312018-03-08 20:28:32 -05001734bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001735{
1736 switch (buffer)
1737 {
1738 case GL_COLOR:
1739 if (drawbuffer < 0 ||
1740 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001742 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 return false;
1744 }
Geoff Lang76e65652017-03-27 14:58:02 -04001745 if (context->getExtensions().webglCompatibility)
1746 {
1747 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001748 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001749 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1750 {
1751 return false;
1752 }
1753 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001754 break;
1755
1756 case GL_STENCIL:
1757 if (drawbuffer != 0)
1758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001759 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001760 return false;
1761 }
1762 break;
1763
1764 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001766 return false;
1767 }
1768
1769 return ValidateClearBuffer(context);
1770}
1771
Jamie Madill5b772312018-03-08 20:28:32 -05001772bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001773{
1774 switch (buffer)
1775 {
1776 case GL_COLOR:
1777 if (drawbuffer < 0 ||
1778 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
Geoff Lang76e65652017-03-27 14:58:02 -04001783 if (context->getExtensions().webglCompatibility)
1784 {
1785 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001786 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001787 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1788 {
1789 return false;
1790 }
1791 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 break;
1793
1794 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001795 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001796 return false;
1797 }
1798
1799 return ValidateClearBuffer(context);
1800}
1801
Jamie Madill5b772312018-03-08 20:28:32 -05001802bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001803{
1804 switch (buffer)
1805 {
1806 case GL_COLOR:
1807 if (drawbuffer < 0 ||
1808 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001810 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001811 return false;
1812 }
Geoff Lang76e65652017-03-27 14:58:02 -04001813 if (context->getExtensions().webglCompatibility)
1814 {
1815 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1816 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001817 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001818 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1819 {
1820 return false;
1821 }
1822 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001823 break;
1824
1825 case GL_DEPTH:
1826 if (drawbuffer != 0)
1827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001828 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001829 return false;
1830 }
1831 break;
1832
1833 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001834 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001835 return false;
1836 }
1837
1838 return ValidateClearBuffer(context);
1839}
1840
Jamie Madill5b772312018-03-08 20:28:32 -05001841bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001842 GLenum buffer,
1843 GLint drawbuffer,
1844 GLfloat depth,
1845 GLint stencil)
1846{
1847 switch (buffer)
1848 {
1849 case GL_DEPTH_STENCIL:
1850 if (drawbuffer != 0)
1851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001852 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001853 return false;
1854 }
1855 break;
1856
1857 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001858 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001859 return false;
1860 }
1861
1862 return ValidateClearBuffer(context);
1863}
1864
Jamie Madill5b772312018-03-08 20:28:32 -05001865bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001866{
Martin Radev1be913c2016-07-11 17:59:16 +03001867 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001868 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001869 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 return false;
1871 }
1872
1873 return ValidateDrawBuffersBase(context, n, bufs);
1874}
1875
1876bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001877 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 GLint level,
1879 GLint xoffset,
1880 GLint yoffset,
1881 GLint zoffset,
1882 GLint x,
1883 GLint y,
1884 GLsizei width,
1885 GLsizei height)
1886{
Martin Radev1be913c2016-07-11 17:59:16 +03001887 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001890 return false;
1891 }
1892
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001893 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1894 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001895}
1896
Jamie Madill73a84962016-02-12 09:27:23 -05001897bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001898 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001899 GLint level,
1900 GLint internalformat,
1901 GLsizei width,
1902 GLsizei height,
1903 GLsizei depth,
1904 GLint border,
1905 GLenum format,
1906 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001907 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001908{
Martin Radev1be913c2016-07-11 17:59:16 +03001909 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001910 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001911 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001912 return false;
1913 }
1914
1915 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001916 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001917 pixels);
1918}
1919
Geoff Langc52f6f12016-10-14 10:18:00 -04001920bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001921 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001922 GLint level,
1923 GLint internalformat,
1924 GLsizei width,
1925 GLsizei height,
1926 GLsizei depth,
1927 GLint border,
1928 GLenum format,
1929 GLenum type,
1930 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001931 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001932{
1933 if (context->getClientMajorVersion() < 3)
1934 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001935 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001936 return false;
1937 }
1938
1939 if (!ValidateRobustEntryPoint(context, bufSize))
1940 {
1941 return false;
1942 }
1943
1944 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1945 0, 0, width, height, depth, border, format, type,
1946 bufSize, pixels);
1947}
1948
Jamie Madill73a84962016-02-12 09:27:23 -05001949bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001950 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001951 GLint level,
1952 GLint xoffset,
1953 GLint yoffset,
1954 GLint zoffset,
1955 GLsizei width,
1956 GLsizei height,
1957 GLsizei depth,
1958 GLenum format,
1959 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001960 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001961{
Martin Radev1be913c2016-07-11 17:59:16 +03001962 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001963 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001965 return false;
1966 }
1967
1968 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1969 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001970 -1, pixels);
1971}
1972
1973bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001974 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001975 GLint level,
1976 GLint xoffset,
1977 GLint yoffset,
1978 GLint zoffset,
1979 GLsizei width,
1980 GLsizei height,
1981 GLsizei depth,
1982 GLenum format,
1983 GLenum type,
1984 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001985 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001986{
1987 if (context->getClientMajorVersion() < 3)
1988 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001990 return false;
1991 }
1992
1993 if (!ValidateRobustEntryPoint(context, bufSize))
1994 {
1995 return false;
1996 }
1997
1998 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1999 yoffset, zoffset, width, height, depth, 0, format, type,
2000 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002001}
2002
2003bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002004 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002005 GLint level,
2006 GLint xoffset,
2007 GLint yoffset,
2008 GLint zoffset,
2009 GLsizei width,
2010 GLsizei height,
2011 GLsizei depth,
2012 GLenum format,
2013 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002014 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002015{
Martin Radev1be913c2016-07-11 17:59:16 +03002016 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002017 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002019 return false;
2020 }
2021
Geoff Langca271392017-04-05 12:30:00 -04002022 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002023 if (!formatInfo.compressed)
2024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002025 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002026 return false;
2027 }
2028
Jeff Gilbert48590352017-11-07 16:03:38 -08002029 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002030 if (blockSizeOrErr.isError())
2031 {
2032 context->handleError(blockSizeOrErr.getError());
2033 return false;
2034 }
2035 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002037 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002038 return false;
2039 }
2040
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002041 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2042 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2043 -1, data))
2044 {
2045 return false;
2046 }
2047
Jamie Madill73a84962016-02-12 09:27:23 -05002048 if (!data)
2049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002050 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002051 return false;
2052 }
2053
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002054 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002055}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002056
Corentin Wallezb2931602017-04-11 15:58:57 -04002057bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002058 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002059 GLint level,
2060 GLint xoffset,
2061 GLint yoffset,
2062 GLint zoffset,
2063 GLsizei width,
2064 GLsizei height,
2065 GLsizei depth,
2066 GLenum format,
2067 GLsizei imageSize,
2068 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002069 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002070{
2071 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2072 {
2073 return false;
2074 }
2075
2076 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2077 height, depth, format, imageSize, data);
2078}
Jamie Madill73a84962016-02-12 09:27:23 -05002079
Olli Etuaho41997e72016-03-10 13:38:39 +02002080bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2081{
2082 return ValidateGenOrDeleteES3(context, n);
2083}
2084
2085bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2086{
2087 return ValidateGenOrDeleteES3(context, n);
2088}
2089
2090bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2091{
2092 return ValidateGenOrDeleteCountES3(context, count);
2093}
2094
2095bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2096{
2097 return ValidateGenOrDeleteCountES3(context, count);
2098}
2099
2100bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2101{
2102 return ValidateGenOrDeleteES3(context, n);
2103}
2104
2105bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2106{
2107 if (!ValidateGenOrDeleteES3(context, n))
2108 {
2109 return false;
2110 }
2111 for (GLint i = 0; i < n; ++i)
2112 {
2113 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2114 if (transformFeedback != nullptr && transformFeedback->isActive())
2115 {
2116 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002117 context->handleError(InvalidOperation()
2118 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002119 return false;
2120 }
2121 }
2122 return true;
2123}
2124
2125bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2126{
2127 return ValidateGenOrDeleteES3(context, n);
2128}
2129
2130bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2131{
2132 return ValidateGenOrDeleteES3(context, n);
2133}
2134
Jamie Madill493f9572018-05-24 19:52:15 -04002135bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMode)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002136{
Martin Radev1be913c2016-07-11 17:59:16 +03002137 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002138 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002140 return false;
2141 }
2142 switch (primitiveMode)
2143 {
Jamie Madill493f9572018-05-24 19:52:15 -04002144 case PrimitiveMode::Triangles:
2145 case PrimitiveMode::Lines:
2146 case PrimitiveMode::Points:
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002147 break;
2148
2149 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002150 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002151 return false;
2152 }
2153
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002154 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002155 ASSERT(transformFeedback != nullptr);
2156
2157 if (transformFeedback->isActive())
2158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002159 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002160 return false;
2161 }
Geoff Lang79f71042017-08-14 16:43:43 -04002162
2163 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2164 {
2165 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2166 if (buffer.get() && buffer->isMapped())
2167 {
2168 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2169 return false;
2170 }
2171 }
2172
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002173 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002174
2175 if (!program)
2176 {
2177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2178 return false;
2179 }
2180
2181 if (program->getTransformFeedbackVaryingCount() == 0)
2182 {
2183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2184 return false;
2185 }
2186
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002187 return true;
2188}
2189
Corentin Wallez336129f2017-10-17 15:55:40 -04002190bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002191{
Geoff Lang496c02d2016-10-20 11:38:11 -07002192 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2193}
2194
2195bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002196 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002197 GLenum pname,
2198 GLsizei bufSize,
2199 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002200 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002201{
2202 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002203 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002204 return false;
2205 }
2206
Brandon Jonesd1049182018-03-28 10:02:20 -07002207 GLsizei numParams = 0;
2208
2209 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002210 {
2211 return false;
2212 }
2213
Brandon Jonesd1049182018-03-28 10:02:20 -07002214 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002215 {
2216 return false;
2217 }
2218
Brandon Jonesd1049182018-03-28 10:02:20 -07002219 SetRobustLengthParam(length, numParams);
2220
Geoff Lang496c02d2016-10-20 11:38:11 -07002221 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002222}
2223
Corentin Wallez336129f2017-10-17 15:55:40 -04002224bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002225{
Martin Radev1be913c2016-07-11 17:59:16 +03002226 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002227 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002229 return false;
2230 }
2231
2232 return ValidateUnmapBufferBase(context, target);
2233}
2234
2235bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002236 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002237 GLintptr offset,
2238 GLsizeiptr length,
2239 GLbitfield access)
2240{
Martin Radev1be913c2016-07-11 17:59:16 +03002241 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002242 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002244 return false;
2245 }
2246
2247 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2248}
2249
2250bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002251 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002252 GLintptr offset,
2253 GLsizeiptr length)
2254{
Martin Radev1be913c2016-07-11 17:59:16 +03002255 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002256 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002258 return false;
2259 }
2260
2261 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2262}
2263
Jamie Madill5b772312018-03-08 20:28:32 -05002264bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002265{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002266 if (length)
2267 {
2268 *length = 0;
2269 }
2270
Martin Radev66fb8202016-07-28 11:45:20 +03002271 GLenum nativeType;
2272 unsigned int numParams;
2273 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002275 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002276 return false;
2277 }
2278
2279 const Caps &caps = context->getCaps();
2280 switch (pname)
2281 {
2282 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2283 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2284 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2285 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002287 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002288 return false;
2289 }
2290 break;
2291
2292 case GL_UNIFORM_BUFFER_START:
2293 case GL_UNIFORM_BUFFER_SIZE:
2294 case GL_UNIFORM_BUFFER_BINDING:
2295 if (index >= caps.maxUniformBufferBindings)
2296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002298 return false;
2299 }
2300 break;
Shao80957d92017-02-20 21:25:59 +08002301
Martin Radev66fb8202016-07-28 11:45:20 +03002302 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2303 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2304 if (index >= 3u)
2305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002306 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002307 return false;
2308 }
2309 break;
Shao80957d92017-02-20 21:25:59 +08002310
Jiajia Qin6eafb042016-12-27 17:04:07 +08002311 case GL_ATOMIC_COUNTER_BUFFER_START:
2312 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2313 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2314 if (context->getClientVersion() < ES_3_1)
2315 {
2316 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002317 InvalidEnum()
2318 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002319 return false;
2320 }
2321 if (index >= caps.maxAtomicCounterBufferBindings)
2322 {
2323 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002324 InvalidValue()
2325 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002326 return false;
2327 }
2328 break;
Shao80957d92017-02-20 21:25:59 +08002329
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002330 case GL_SHADER_STORAGE_BUFFER_START:
2331 case GL_SHADER_STORAGE_BUFFER_SIZE:
2332 case GL_SHADER_STORAGE_BUFFER_BINDING:
2333 if (context->getClientVersion() < ES_3_1)
2334 {
2335 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002336 InvalidEnum()
2337 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002338 return false;
2339 }
2340 if (index >= caps.maxShaderStorageBufferBindings)
2341 {
2342 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002343 InvalidValue()
2344 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002345 return false;
2346 }
2347 break;
2348
Shao80957d92017-02-20 21:25:59 +08002349 case GL_VERTEX_BINDING_BUFFER:
2350 case GL_VERTEX_BINDING_DIVISOR:
2351 case GL_VERTEX_BINDING_OFFSET:
2352 case GL_VERTEX_BINDING_STRIDE:
2353 if (context->getClientVersion() < ES_3_1)
2354 {
2355 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002356 InvalidEnum()
2357 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002358 return false;
2359 }
2360 if (index >= caps.maxVertexAttribBindings)
2361 {
2362 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 InvalidValue()
2364 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002365 return false;
2366 }
2367 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002368 case GL_SAMPLE_MASK_VALUE:
2369 if (context->getClientVersion() < ES_3_1)
2370 {
2371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2372 return false;
2373 }
2374 if (index >= caps.maxSampleMaskWords)
2375 {
2376 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2377 return false;
2378 }
2379 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002380 case GL_IMAGE_BINDING_NAME:
2381 case GL_IMAGE_BINDING_LEVEL:
2382 case GL_IMAGE_BINDING_LAYERED:
2383 case GL_IMAGE_BINDING_LAYER:
2384 case GL_IMAGE_BINDING_ACCESS:
2385 case GL_IMAGE_BINDING_FORMAT:
2386 if (context->getClientVersion() < ES_3_1)
2387 {
2388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2389 return false;
2390 }
2391 if (index >= caps.maxImageUnits)
2392 {
2393 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2394 return false;
2395 }
2396 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002397 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002399 return false;
2400 }
2401
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002402 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002403 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002404 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002405 }
2406
2407 return true;
2408}
2409
Jamie Madill5b772312018-03-08 20:28:32 -05002410bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002411{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002412 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002413 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002415 return false;
2416 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002417 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002418}
2419
Jamie Madill5b772312018-03-08 20:28:32 -05002420bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002421 GLenum target,
2422 GLuint index,
2423 GLsizei bufSize,
2424 GLsizei *length,
2425 GLint *data)
2426{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002427 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002428 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002430 return false;
2431 }
2432
2433 if (!ValidateRobustEntryPoint(context, bufSize))
2434 {
2435 return false;
2436 }
2437
Brandon Jonesd1049182018-03-28 10:02:20 -07002438 GLsizei numParams = 0;
2439
2440 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002441 {
2442 return false;
2443 }
2444
Brandon Jonesd1049182018-03-28 10:02:20 -07002445 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002446 {
2447 return false;
2448 }
2449
Brandon Jonesd1049182018-03-28 10:02:20 -07002450 SetRobustLengthParam(length, numParams);
2451
Geoff Langcf255ea2016-10-20 11:39:09 -07002452 return true;
2453}
2454
Jamie Madill5b772312018-03-08 20:28:32 -05002455bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002456{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002457 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002460 return false;
2461 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002462 return ValidateIndexedStateQuery(context, target, index, nullptr);
2463}
2464
Jamie Madill5b772312018-03-08 20:28:32 -05002465bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002466 GLenum target,
2467 GLuint index,
2468 GLsizei bufSize,
2469 GLsizei *length,
2470 GLint64 *data)
2471{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002472 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002473 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002475 return false;
2476 }
2477
2478 if (!ValidateRobustEntryPoint(context, bufSize))
2479 {
2480 return false;
2481 }
2482
Brandon Jonesd1049182018-03-28 10:02:20 -07002483 GLsizei numParams = 0;
2484
2485 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002486 {
2487 return false;
2488 }
2489
Brandon Jonesd1049182018-03-28 10:02:20 -07002490 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002491 {
2492 return false;
2493 }
2494
Brandon Jonesd1049182018-03-28 10:02:20 -07002495 SetRobustLengthParam(length, numParams);
2496
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002497 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002498}
2499
Jamie Madill5b772312018-03-08 20:28:32 -05002500bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002501 BufferBinding readTarget,
2502 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002503 GLintptr readOffset,
2504 GLintptr writeOffset,
2505 GLsizeiptr size)
2506{
2507 if (context->getClientMajorVersion() < 3)
2508 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002509 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002510 return false;
2511 }
2512
Corentin Walleze4477002017-12-01 14:39:58 -05002513 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002515 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002516 return false;
2517 }
2518
2519 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2520 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2521
2522 if (!readBuffer || !writeBuffer)
2523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002524 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002525 return false;
2526 }
2527
2528 // Verify that readBuffer and writeBuffer are not currently mapped
2529 if (readBuffer->isMapped() || writeBuffer->isMapped())
2530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002531 context->handleError(InvalidOperation()
2532 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002533 return false;
2534 }
2535
James Darpiniane8a93c62018-01-04 18:02:24 -08002536 if (context->getExtensions().webglCompatibility &&
2537 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2538 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2539 {
2540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2541 return false;
2542 }
2543
Jamie Madilld2f0c742016-11-02 10:34:41 -04002544 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2545 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2546 CheckedNumeric<GLintptr> checkedSize(size);
2547
2548 auto checkedReadSum = checkedReadOffset + checkedSize;
2549 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2550
2551 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2552 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2553 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002555 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002556 return false;
2557 }
2558
Jamie Madilld2f0c742016-11-02 10:34:41 -04002559 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002561 context->handleError(InvalidValue()
2562 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002563 return false;
2564 }
2565
Jamie Madilld2f0c742016-11-02 10:34:41 -04002566 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2567 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002569 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002570 return false;
2571 }
2572
2573 if (readBuffer == writeBuffer)
2574 {
2575 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2576 if (!checkedOffsetDiff.IsValid())
2577 {
2578 // This shold not be possible.
2579 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002580 context->handleError(InvalidValue()
2581 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002582 return false;
2583 }
2584
2585 if (checkedOffsetDiff.ValueOrDie() < size)
2586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002587 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002588 return false;
2589 }
2590 }
2591
Jamie Madillb0817d12016-11-01 15:48:31 -04002592 return true;
2593}
2594
Geoff Langc339c4e2016-11-29 10:37:36 -05002595bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2596{
2597 if (context->getClientMajorVersion() < 3)
2598 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002600 return false;
2601 }
2602
2603 switch (name)
2604 {
2605 case GL_EXTENSIONS:
2606 if (index >= context->getExtensionStringCount())
2607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002608 context->handleError(InvalidValue()
2609 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002610 return false;
2611 }
2612 break;
2613
2614 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2615 if (!context->getExtensions().requestExtension)
2616 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002617 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002618 return false;
2619 }
2620 if (index >= context->getRequestableExtensionStringCount())
2621 {
2622 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002623 InvalidValue()
2624 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002625 return false;
2626 }
2627 break;
2628
2629 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002631 return false;
2632 }
2633
2634 return true;
2635}
2636
Jamie Madill5b772312018-03-08 20:28:32 -05002637bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002638 GLenum target,
2639 GLsizei samples,
2640 GLenum internalformat,
2641 GLsizei width,
2642 GLsizei height)
2643{
2644 if (context->getClientMajorVersion() < 3)
2645 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002647 return false;
2648 }
2649
2650 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2651 height))
2652 {
2653 return false;
2654 }
2655
2656 // 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 +08002657 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2658 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002659 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002660 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002661 {
Yunchao Hec0810202018-01-22 09:48:48 +08002662 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2663 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2664 {
2665 context->handleError(InvalidOperation());
2666 return false;
2667 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002668 }
2669
2670 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2671 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2672 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2673 {
2674 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002675 InvalidOperation()
2676 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002677 return false;
2678 }
2679
2680 return true;
2681}
2682
Jamie Madill5b772312018-03-08 20:28:32 -05002683bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002684 GLuint index,
2685 GLint size,
2686 GLenum type,
2687 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002688 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002689{
2690 if (context->getClientMajorVersion() < 3)
2691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002693 return false;
2694 }
2695
Shao80957d92017-02-20 21:25:59 +08002696 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002697 {
Geoff Langaa086d62017-03-23 16:47:21 -04002698 return false;
2699 }
2700
Geoff Langaa086d62017-03-23 16:47:21 -04002701 if (stride < 0)
2702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002703 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002704 return false;
2705 }
2706
Shao80957d92017-02-20 21:25:59 +08002707 const Caps &caps = context->getCaps();
2708 if (context->getClientVersion() >= ES_3_1)
2709 {
2710 if (stride > caps.maxVertexAttribStride)
2711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002712 context->handleError(InvalidValue()
2713 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002714 return false;
2715 }
2716
2717 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2718 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2719 // validation should be inherited.
2720 if (index >= caps.maxVertexAttribBindings)
2721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002722 context->handleError(InvalidValue()
2723 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002724 return false;
2725 }
2726 }
2727
Geoff Langaa086d62017-03-23 16:47:21 -04002728 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2729 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2730 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2731 // and the pointer argument is not NULL.
2732 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002733 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002735 context
2736 ->handleError(InvalidOperation()
2737 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002738 return false;
2739 }
2740
Geoff Lang2d62ab72017-03-23 16:54:40 -04002741 if (context->getExtensions().webglCompatibility)
2742 {
2743 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2744 {
2745 return false;
2746 }
2747 }
2748
Geoff Langaa086d62017-03-23 16:47:21 -04002749 return true;
2750}
2751
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002752bool ValidateGetSynciv(Context *context,
2753 GLsync sync,
2754 GLenum pname,
2755 GLsizei bufSize,
2756 GLsizei *length,
2757 GLint *values)
2758{
2759 if (context->getClientMajorVersion() < 3)
2760 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002762 return false;
2763 }
2764
2765 if (bufSize < 0)
2766 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002767 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002768 return false;
2769 }
2770
Jamie Madill70b5bb02017-08-28 13:32:37 -04002771 Sync *syncObject = context->getSync(sync);
2772 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002774 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002775 return false;
2776 }
2777
2778 switch (pname)
2779 {
2780 case GL_OBJECT_TYPE:
2781 case GL_SYNC_CONDITION:
2782 case GL_SYNC_FLAGS:
2783 case GL_SYNC_STATUS:
2784 break;
2785
2786 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002788 return false;
2789 }
2790
2791 return true;
2792}
2793
Jamie Madill5b772312018-03-08 20:28:32 -05002794bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002795 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002796 GLsizei count,
2797 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002798 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002799 GLsizei instanceCount)
2800{
2801 if (context->getClientMajorVersion() < 3)
2802 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002804 return false;
2805 }
2806
2807 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2808}
2809
Martin Radev137032d2017-07-13 10:11:12 +03002810bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2811 GLenum target,
2812 GLenum attachment,
2813 GLuint texture,
2814 GLint level,
2815 GLint baseViewIndex,
2816 GLsizei numViews)
2817{
2818
2819 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2820 numViews))
2821 {
2822 return false;
2823 }
2824
Martin Radev137032d2017-07-13 10:11:12 +03002825 if (texture != 0)
2826 {
Martin Radev14b21262017-08-25 13:54:37 +03002827 if (baseViewIndex < 0)
2828 {
2829 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2830 return false;
2831 }
2832
Martin Radev137032d2017-07-13 10:11:12 +03002833 Texture *tex = context->getTexture(texture);
2834 ASSERT(tex);
2835
Corentin Wallez99d492c2018-02-27 15:17:10 -05002836 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002837 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002838 case TextureType::_2DArray:
Martin Radev137032d2017-07-13 10:11:12 +03002839 {
2840 const Caps &caps = context->getCaps();
2841 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2842 {
2843 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2844 "greater than "
2845 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2846 return false;
2847 }
2848 }
2849 break;
2850 default:
2851 context->handleError(InvalidOperation()
2852 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2853 return false;
2854 }
2855
2856 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2857 {
2858 return false;
2859 }
2860 }
2861
2862 return true;
2863}
2864
2865bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2866 GLenum target,
2867 GLenum attachment,
2868 GLuint texture,
2869 GLint level,
2870 GLsizei numViews,
2871 const GLint *viewportOffsets)
2872{
2873 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2874 numViews))
2875 {
2876 return false;
2877 }
2878
Martin Radev137032d2017-07-13 10:11:12 +03002879 if (texture != 0)
2880 {
Martin Radev14b21262017-08-25 13:54:37 +03002881 const GLsizei numViewportOffsetValues = numViews * 2;
2882 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2883 {
2884 if (viewportOffsets[i] < 0)
2885 {
2886 context->handleError(InvalidValue()
2887 << "viewportOffsets cannot contain negative values.");
2888 return false;
2889 }
2890 }
2891
Martin Radev137032d2017-07-13 10:11:12 +03002892 Texture *tex = context->getTexture(texture);
2893 ASSERT(tex);
2894
Corentin Wallez99d492c2018-02-27 15:17:10 -05002895 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002896 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002897 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002898 break;
2899 default:
2900 context->handleError(InvalidOperation()
2901 << "Texture's target must be GL_TEXTURE_2D.");
2902 return false;
2903 }
2904
2905 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2906 {
2907 return false;
2908 }
2909 }
2910
2911 return true;
2912}
2913
Jamie Madillff325f12017-08-26 15:06:05 -04002914bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2915{
2916 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2917}
2918
2919bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2920{
2921 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2922}
2923
2924bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2925{
2926 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2927}
2928
2929bool ValidateUniform4ui(Context *context,
2930 GLint location,
2931 GLuint v0,
2932 GLuint v1,
2933 GLuint v2,
2934 GLuint v3)
2935{
2936 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2937}
2938
2939bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2940{
2941 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2942}
2943
2944bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2945{
2946 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2947}
2948
2949bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2950{
2951 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2952}
2953
2954bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2955{
2956 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2957}
2958
Jamie Madillf0e04492017-08-26 15:28:42 -04002959bool ValidateIsQuery(Context *context, GLuint id)
2960{
2961 if (context->getClientMajorVersion() < 3)
2962 {
2963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2964 return false;
2965 }
2966
2967 return true;
2968}
2969
Jamie Madillc8c95812017-08-26 18:40:09 -04002970bool ValidateUniformMatrix2x3fv(Context *context,
2971 GLint location,
2972 GLsizei count,
2973 GLboolean transpose,
2974 const GLfloat *value)
2975{
2976 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2977}
2978
2979bool ValidateUniformMatrix3x2fv(Context *context,
2980 GLint location,
2981 GLsizei count,
2982 GLboolean transpose,
2983 const GLfloat *value)
2984{
2985 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2986}
2987
2988bool ValidateUniformMatrix2x4fv(Context *context,
2989 GLint location,
2990 GLsizei count,
2991 GLboolean transpose,
2992 const GLfloat *value)
2993{
2994 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2995}
2996
2997bool ValidateUniformMatrix4x2fv(Context *context,
2998 GLint location,
2999 GLsizei count,
3000 GLboolean transpose,
3001 const GLfloat *value)
3002{
3003 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3004}
3005
3006bool ValidateUniformMatrix3x4fv(Context *context,
3007 GLint location,
3008 GLsizei count,
3009 GLboolean transpose,
3010 const GLfloat *value)
3011{
3012 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3013}
3014
3015bool ValidateUniformMatrix4x3fv(Context *context,
3016 GLint location,
3017 GLsizei count,
3018 GLboolean transpose,
3019 const GLfloat *value)
3020{
3021 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3022}
3023
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003024bool ValidateEndTransformFeedback(Context *context)
3025{
3026 if (context->getClientMajorVersion() < 3)
3027 {
3028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3029 return false;
3030 }
3031
3032 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3033 ASSERT(transformFeedback != nullptr);
3034
3035 if (!transformFeedback->isActive())
3036 {
3037 context->handleError(InvalidOperation());
3038 return false;
3039 }
3040
3041 return true;
3042}
3043
3044bool ValidateTransformFeedbackVaryings(Context *context,
3045 GLuint program,
3046 GLsizei count,
3047 const GLchar *const *varyings,
3048 GLenum bufferMode)
3049{
3050 if (context->getClientMajorVersion() < 3)
3051 {
3052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3053 return false;
3054 }
3055
3056 if (count < 0)
3057 {
3058 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3059 return false;
3060 }
3061
3062 switch (bufferMode)
3063 {
3064 case GL_INTERLEAVED_ATTRIBS:
3065 break;
3066 case GL_SEPARATE_ATTRIBS:
3067 {
3068 const Caps &caps = context->getCaps();
3069 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3070 {
3071 context->handleError(InvalidValue());
3072 return false;
3073 }
3074 break;
3075 }
3076 default:
3077 context->handleError(InvalidEnum());
3078 return false;
3079 }
3080
3081 Program *programObject = GetValidProgram(context, program);
3082 if (!programObject)
3083 {
3084 return false;
3085 }
3086
3087 return true;
3088}
3089
3090bool ValidateGetTransformFeedbackVarying(Context *context,
3091 GLuint program,
3092 GLuint index,
3093 GLsizei bufSize,
3094 GLsizei *length,
3095 GLsizei *size,
3096 GLenum *type,
3097 GLchar *name)
3098{
3099 if (context->getClientMajorVersion() < 3)
3100 {
3101 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3102 return false;
3103 }
3104
3105 if (bufSize < 0)
3106 {
3107 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3108 return false;
3109 }
3110
3111 Program *programObject = GetValidProgram(context, program);
3112 if (!programObject)
3113 {
3114 return false;
3115 }
3116
3117 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3118 {
3119 context->handleError(InvalidValue());
3120 return false;
3121 }
3122
3123 return true;
3124}
3125
3126bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3127{
3128 if (context->getClientMajorVersion() < 3)
3129 {
3130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3131 return false;
3132 }
3133
3134 switch (target)
3135 {
3136 case GL_TRANSFORM_FEEDBACK:
3137 {
3138 // Cannot bind a transform feedback object if the current one is started and not
3139 // paused (3.0.2 pg 85 section 2.14.1)
3140 TransformFeedback *curTransformFeedback =
3141 context->getGLState().getCurrentTransformFeedback();
3142 if (curTransformFeedback && curTransformFeedback->isActive() &&
3143 !curTransformFeedback->isPaused())
3144 {
3145 context->handleError(InvalidOperation());
3146 return false;
3147 }
3148
3149 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3150 // 2.14.1)
3151 if (!context->isTransformFeedbackGenerated(id))
3152 {
3153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3154 return false;
3155 }
3156 }
3157 break;
3158
3159 default:
3160 context->handleError(InvalidEnum());
3161 return false;
3162 }
3163
3164 return true;
3165}
3166
3167bool ValidateIsTransformFeedback(Context *context, GLuint id)
3168{
3169 if (context->getClientMajorVersion() < 3)
3170 {
3171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3172 return false;
3173 }
3174
3175 return true;
3176}
3177
3178bool ValidatePauseTransformFeedback(Context *context)
3179{
3180 if (context->getClientMajorVersion() < 3)
3181 {
3182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3183 return false;
3184 }
3185
3186 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3187 ASSERT(transformFeedback != nullptr);
3188
3189 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3190 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3191 {
3192 context->handleError(InvalidOperation());
3193 return false;
3194 }
3195
3196 return true;
3197}
3198
3199bool ValidateResumeTransformFeedback(Context *context)
3200{
3201 if (context->getClientMajorVersion() < 3)
3202 {
3203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3204 return false;
3205 }
3206
3207 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3208 ASSERT(transformFeedback != nullptr);
3209
3210 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3211 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3212 {
3213 context->handleError(InvalidOperation());
3214 return false;
3215 }
3216
3217 return true;
3218}
3219
Jamie Madill12e957f2017-08-26 21:42:26 -04003220bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3221{
3222 if (context->getClientMajorVersion() < 3)
3223 {
3224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3225 return false;
3226 }
3227
3228 return ValidateVertexAttribIndex(context, index);
3229}
3230
3231bool ValidateVertexAttribI4ui(Context *context,
3232 GLuint index,
3233 GLuint x,
3234 GLuint y,
3235 GLuint z,
3236 GLuint w)
3237{
3238 if (context->getClientMajorVersion() < 3)
3239 {
3240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3241 return false;
3242 }
3243
3244 return ValidateVertexAttribIndex(context, index);
3245}
3246
3247bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3248{
3249 if (context->getClientMajorVersion() < 3)
3250 {
3251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3252 return false;
3253 }
3254
3255 return ValidateVertexAttribIndex(context, index);
3256}
3257
3258bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3259{
3260 if (context->getClientMajorVersion() < 3)
3261 {
3262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3263 return false;
3264 }
3265
3266 return ValidateVertexAttribIndex(context, index);
3267}
3268
3269bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3270{
3271 if (context->getClientMajorVersion() < 3)
3272 {
3273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3274 return false;
3275 }
3276
3277 Program *programObject = GetValidProgram(context, program);
3278 if (!programObject)
3279 {
3280 return false;
3281 }
3282
3283 if (!programObject->isLinked())
3284 {
3285 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3286 return false;
3287 }
3288
3289 return true;
3290}
3291
3292bool ValidateGetUniformIndices(Context *context,
3293 GLuint program,
3294 GLsizei uniformCount,
3295 const GLchar *const *uniformNames,
3296 GLuint *uniformIndices)
3297{
3298 if (context->getClientMajorVersion() < 3)
3299 {
3300 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3301 return false;
3302 }
3303
3304 if (uniformCount < 0)
3305 {
3306 context->handleError(InvalidValue());
3307 return false;
3308 }
3309
3310 Program *programObject = GetValidProgram(context, program);
3311 if (!programObject)
3312 {
3313 return false;
3314 }
3315
3316 return true;
3317}
3318
3319bool ValidateGetActiveUniformsiv(Context *context,
3320 GLuint program,
3321 GLsizei uniformCount,
3322 const GLuint *uniformIndices,
3323 GLenum pname,
3324 GLint *params)
3325{
3326 if (context->getClientMajorVersion() < 3)
3327 {
3328 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3329 return false;
3330 }
3331
3332 if (uniformCount < 0)
3333 {
3334 context->handleError(InvalidValue());
3335 return false;
3336 }
3337
3338 Program *programObject = GetValidProgram(context, program);
3339 if (!programObject)
3340 {
3341 return false;
3342 }
3343
3344 switch (pname)
3345 {
3346 case GL_UNIFORM_TYPE:
3347 case GL_UNIFORM_SIZE:
3348 case GL_UNIFORM_NAME_LENGTH:
3349 case GL_UNIFORM_BLOCK_INDEX:
3350 case GL_UNIFORM_OFFSET:
3351 case GL_UNIFORM_ARRAY_STRIDE:
3352 case GL_UNIFORM_MATRIX_STRIDE:
3353 case GL_UNIFORM_IS_ROW_MAJOR:
3354 break;
3355
3356 default:
3357 context->handleError(InvalidEnum());
3358 return false;
3359 }
3360
3361 if (uniformCount > programObject->getActiveUniformCount())
3362 {
3363 context->handleError(InvalidValue());
3364 return false;
3365 }
3366
3367 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3368 {
3369 const GLuint index = uniformIndices[uniformId];
3370
3371 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3372 {
3373 context->handleError(InvalidValue());
3374 return false;
3375 }
3376 }
3377
3378 return true;
3379}
3380
3381bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3382{
3383 if (context->getClientMajorVersion() < 3)
3384 {
3385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3386 return false;
3387 }
3388
3389 Program *programObject = GetValidProgram(context, program);
3390 if (!programObject)
3391 {
3392 return false;
3393 }
3394
3395 return true;
3396}
3397
3398bool ValidateGetActiveUniformBlockiv(Context *context,
3399 GLuint program,
3400 GLuint uniformBlockIndex,
3401 GLenum pname,
3402 GLint *params)
3403{
3404 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3405}
3406
3407bool ValidateGetActiveUniformBlockName(Context *context,
3408 GLuint program,
3409 GLuint uniformBlockIndex,
3410 GLsizei bufSize,
3411 GLsizei *length,
3412 GLchar *uniformBlockName)
3413{
3414 if (context->getClientMajorVersion() < 3)
3415 {
3416 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3417 return false;
3418 }
3419
3420 Program *programObject = GetValidProgram(context, program);
3421 if (!programObject)
3422 {
3423 return false;
3424 }
3425
3426 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3427 {
3428 context->handleError(InvalidValue());
3429 return false;
3430 }
3431
3432 return true;
3433}
3434
3435bool ValidateUniformBlockBinding(Context *context,
3436 GLuint program,
3437 GLuint uniformBlockIndex,
3438 GLuint uniformBlockBinding)
3439{
3440 if (context->getClientMajorVersion() < 3)
3441 {
3442 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3443 return false;
3444 }
3445
3446 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3447 {
3448 context->handleError(InvalidValue());
3449 return false;
3450 }
3451
3452 Program *programObject = GetValidProgram(context, program);
3453 if (!programObject)
3454 {
3455 return false;
3456 }
3457
3458 // if never linked, there won't be any uniform blocks
3459 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3460 {
3461 context->handleError(InvalidValue());
3462 return false;
3463 }
3464
3465 return true;
3466}
3467
3468bool ValidateDrawArraysInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003469 PrimitiveMode mode,
Jamie Madill12e957f2017-08-26 21:42:26 -04003470 GLint first,
3471 GLsizei count,
3472 GLsizei primcount)
3473{
3474 if (context->getClientMajorVersion() < 3)
3475 {
3476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3477 return false;
3478 }
3479
3480 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3481}
3482
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003483bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3484{
3485 if (context->getClientMajorVersion() < 3)
3486 {
3487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3488 return false;
3489 }
3490
3491 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3492 {
3493 context->handleError(InvalidEnum());
3494 return false;
3495 }
3496
3497 if (flags != 0)
3498 {
3499 context->handleError(InvalidValue());
3500 return false;
3501 }
3502
3503 return true;
3504}
3505
3506bool ValidateIsSync(Context *context, GLsync sync)
3507{
3508 if (context->getClientMajorVersion() < 3)
3509 {
3510 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3511 return false;
3512 }
3513
3514 return true;
3515}
3516
3517bool ValidateDeleteSync(Context *context, GLsync sync)
3518{
3519 if (context->getClientMajorVersion() < 3)
3520 {
3521 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3522 return false;
3523 }
3524
Jamie Madill70b5bb02017-08-28 13:32:37 -04003525 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003526 {
3527 context->handleError(InvalidValue());
3528 return false;
3529 }
3530
3531 return true;
3532}
3533
3534bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3535{
3536 if (context->getClientMajorVersion() < 3)
3537 {
3538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3539 return false;
3540 }
3541
3542 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3543 {
3544 context->handleError(InvalidValue());
3545 return false;
3546 }
3547
Jamie Madill70b5bb02017-08-28 13:32:37 -04003548 Sync *clientWaitSync = context->getSync(sync);
3549 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003550 {
3551 context->handleError(InvalidValue());
3552 return false;
3553 }
3554
3555 return true;
3556}
3557
3558bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3559{
3560 if (context->getClientMajorVersion() < 3)
3561 {
3562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3563 return false;
3564 }
3565
3566 if (flags != 0)
3567 {
3568 context->handleError(InvalidValue());
3569 return false;
3570 }
3571
3572 if (timeout != GL_TIMEOUT_IGNORED)
3573 {
3574 context->handleError(InvalidValue());
3575 return false;
3576 }
3577
Jamie Madill70b5bb02017-08-28 13:32:37 -04003578 Sync *waitSync = context->getSync(sync);
3579 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003580 {
3581 context->handleError(InvalidValue());
3582 return false;
3583 }
3584
3585 return true;
3586}
3587
3588bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3589{
3590 if (context->getClientMajorVersion() < 3)
3591 {
3592 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3593 return false;
3594 }
3595
3596 GLenum nativeType = GL_NONE;
3597 unsigned int numParams = 0;
3598 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3599 {
3600 return false;
3601 }
3602
3603 return true;
3604}
3605
Jamie Madill3ef140a2017-08-26 23:11:21 -04003606bool ValidateIsSampler(Context *context, GLuint sampler)
3607{
3608 if (context->getClientMajorVersion() < 3)
3609 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003611 return false;
3612 }
3613
3614 return true;
3615}
3616
3617bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3618{
3619 if (context->getClientMajorVersion() < 3)
3620 {
3621 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3622 return false;
3623 }
3624
3625 if (sampler != 0 && !context->isSampler(sampler))
3626 {
3627 context->handleError(InvalidOperation());
3628 return false;
3629 }
3630
3631 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3632 {
3633 context->handleError(InvalidValue());
3634 return false;
3635 }
3636
3637 return true;
3638}
3639
3640bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3641{
3642 if (context->getClientMajorVersion() < 3)
3643 {
3644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3645 return false;
3646 }
3647
3648 return ValidateVertexAttribIndex(context, index);
3649}
3650
3651bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003652 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003653 GLsizei levels,
3654 GLenum internalformat,
3655 GLsizei width,
3656 GLsizei height)
3657{
3658 if (context->getClientMajorVersion() < 3)
3659 {
3660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3661 return false;
3662 }
3663
3664 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3665 1))
3666 {
3667 return false;
3668 }
3669
3670 return true;
3671}
3672
3673bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003674 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003675 GLsizei levels,
3676 GLenum internalformat,
3677 GLsizei width,
3678 GLsizei height,
3679 GLsizei depth)
3680{
3681 if (context->getClientMajorVersion() < 3)
3682 {
3683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3684 return false;
3685 }
3686
3687 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3688 depth))
3689 {
3690 return false;
3691 }
3692
3693 return true;
3694}
3695
Jamie Madill5b772312018-03-08 20:28:32 -05003696bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003697 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003698 GLenum pname,
3699 GLint64 *params)
3700{
3701 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3702}
3703
3704bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3705{
3706 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3707}
3708
3709bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3710{
3711 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3712}
3713
3714bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3715{
3716 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3717}
3718
3719bool ValidateSamplerParameterfv(Context *context,
3720 GLuint sampler,
3721 GLenum pname,
3722 const GLfloat *params)
3723{
3724 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3725}
3726
3727bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3728{
3729 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3730}
3731
3732bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3733{
3734 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3735}
3736
3737bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3738{
3739 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3740}
3741
3742bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3743{
3744 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3745}
3746
3747bool ValidateGetInternalformativ(Context *context,
3748 GLenum target,
3749 GLenum internalformat,
3750 GLenum pname,
3751 GLsizei bufSize,
3752 GLint *params)
3753{
3754 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3755 nullptr);
3756}
3757
Jamie Madillc29968b2016-01-20 11:17:23 -05003758} // namespace gl