blob: 12f290cf2630521c3368cdd8b251eb940d0346d0 [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 {
Olli Etuahofd162102018-08-27 16:14:57 +03001154 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1155 FramebufferTextureInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001157 }
1158
1159 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1160 {
Olli Etuahofd162102018-08-27 16:14:57 +03001161 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
Geoff Langb1196682014-07-23 13:47:29 -04001162 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001163 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001164 }
1165 break;
1166
Corentin Wallez99d492c2018-02-27 15:17:10 -05001167 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001168 {
1169 if (level > gl::log2(caps.max3DTextureSize))
1170 {
Olli Etuahofd162102018-08-27 16:14:57 +03001171 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1172 FramebufferTextureInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001174 }
1175
1176 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1177 {
Olli Etuahofd162102018-08-27 16:14:57 +03001178 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
1179 return false;
1180 }
1181 }
1182 break;
1183
1184 case TextureType::_2DMultisampleArray:
1185 {
1186 if (level != 0)
1187 {
1188 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1189 FramebufferTextureInvalidMipLevel);
1190 return false;
1191 }
1192
1193 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1194 {
1195 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
Geoff Langb1196682014-07-23 13:47:29 -04001196 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001197 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001198 }
1199 break;
1200
He Yunchaoced53ae2016-11-29 15:00:51 +08001201 default:
Olli Etuahofd162102018-08-27 16:14:57 +03001202 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1203 FramebufferTextureLayerIncorrectTextureType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001205 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001206
Corentin Wallez99d492c2018-02-27 15:17:10 -05001207 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001208 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001210 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001211 return false;
1212 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001213 }
1214
1215 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001216}
1217
He Yunchaoced53ae2016-11-29 15:00:51 +08001218bool ValidateInvalidateFramebuffer(Context *context,
1219 GLenum target,
1220 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001221 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001222{
Martin Radev1be913c2016-07-11 17:59:16 +03001223 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001224 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001225 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001226 return false;
1227 }
1228
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 bool defaultFramebuffer = false;
1230
1231 switch (target)
1232 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001233 case GL_DRAW_FRAMEBUFFER:
1234 case GL_FRAMEBUFFER:
1235 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1236 break;
1237 case GL_READ_FRAMEBUFFER:
1238 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1239 break;
1240 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001241 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001242 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 }
1244
He Yunchaoced53ae2016-11-29 15:00:51 +08001245 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1246 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247}
1248
Jamie Madill3ef140a2017-08-26 23:11:21 -04001249bool ValidateInvalidateSubFramebuffer(Context *context,
1250 GLenum target,
1251 GLsizei numAttachments,
1252 const GLenum *attachments,
1253 GLint x,
1254 GLint y,
1255 GLsizei width,
1256 GLsizei height)
1257{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001258 if (width < 0 || height < 0)
1259 {
1260 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1261 return false;
1262 }
1263
Jamie Madill3ef140a2017-08-26 23:11:21 -04001264 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1265}
1266
Jamie Madill5b772312018-03-08 20:28:32 -05001267bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001268{
Martin Radev1be913c2016-07-11 17:59:16 +03001269 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001270 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001271 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001272 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001273 }
1274
Jamie Madill427064d2018-04-13 16:20:34 -04001275 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001276 {
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001278 }
1279
1280 return true;
1281}
1282
Olli Etuaho71dfb362016-03-10 14:04:27 +02001283bool ValidateDrawRangeElements(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001284 PrimitiveMode mode,
Olli Etuaho71dfb362016-03-10 14:04:27 +02001285 GLuint start,
1286 GLuint end,
1287 GLsizei count,
1288 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001289 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001290{
Martin Radev1be913c2016-07-11 17:59:16 +03001291 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001292 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001294 return false;
1295 }
1296
1297 if (end < start)
1298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001299 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001300 return false;
1301 }
1302
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001303 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001304 {
1305 return false;
1306 }
1307
Jamie Madill9fdaa492018-02-16 10:52:11 -05001308 // Skip range checks for no-op calls.
1309 if (count <= 0)
1310 {
1311 return true;
1312 }
1313
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001314 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04001315 const DrawCallParams &params = context->getParams<DrawCallParams>();
1316 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001317
Jamie Madill6f5444d2018-03-14 10:08:11 -04001318 const IndexRange &indexRange = params.getIndexRange();
1319
1320 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001321 {
1322 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001323 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001324 return false;
1325 }
1326 return true;
1327}
1328
He Yunchaoced53ae2016-11-29 15:00:51 +08001329bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001330{
Martin Radev1be913c2016-07-11 17:59:16 +03001331 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001332 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001334 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001335 }
1336
Jamie Madill78f41802014-08-25 15:47:55 -04001337 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001338}
1339
Jamie Madillb885e572015-02-03 16:16:04 -05001340bool ValidateReadBuffer(Context *context, GLenum src)
1341{
Martin Radev1be913c2016-07-11 17:59:16 +03001342 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001343 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001344 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001345 return false;
1346 }
1347
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001348 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001349
1350 if (readFBO == nullptr)
1351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001352 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001353 return false;
1354 }
1355
1356 if (src == GL_NONE)
1357 {
1358 return true;
1359 }
1360
Olli Etuaho84c9f592016-03-09 14:37:25 +02001361 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001364 return false;
1365 }
1366
1367 if (readFBO->id() == 0)
1368 {
1369 if (src != GL_BACK)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(
1372 InvalidOperation()
1373 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001374 return false;
1375 }
1376 }
1377 else
1378 {
1379 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1380
1381 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001384 return false;
1385 }
1386 }
1387
1388 return true;
1389}
1390
Jamie Madill86af3d22015-07-21 15:14:07 -04001391bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001392 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001393 GLint level,
1394 GLenum internalformat,
1395 GLsizei width,
1396 GLsizei height,
1397 GLsizei depth,
1398 GLint border,
1399 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001400 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001401{
Martin Radev1be913c2016-07-11 17:59:16 +03001402 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001403 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001405 return false;
1406 }
1407
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001408 if (!ValidTextureTarget(context, target))
1409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001410 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001411 return false;
1412 }
1413
Jamie Madille2e406c2016-06-02 13:04:10 -04001414 // Validate image size
1415 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001418 return false;
1419 }
1420
Geoff Langca271392017-04-05 12:30:00 -04001421 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001422 if (!formatInfo.compressed)
1423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001424 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001425 return false;
1426 }
1427
Jamie Madillca2ff382018-07-11 09:01:17 -04001428 GLuint blockSize = 0;
1429 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001432 return false;
1433 }
Jamie Madillca2ff382018-07-11 09:01:17 -04001434
1435 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill86af3d22015-07-21 15:14:07 -04001436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001438 return false;
1439 }
1440
1441 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001442 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001445 return false;
1446 }
1447
1448 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001449 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001450 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1451 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001452 {
1453 return false;
1454 }
1455
1456 return true;
1457}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001458
Corentin Wallezb2931602017-04-11 15:58:57 -04001459bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001460 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001461 GLint level,
1462 GLenum internalformat,
1463 GLsizei width,
1464 GLsizei height,
1465 GLsizei depth,
1466 GLint border,
1467 GLsizei imageSize,
1468 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001469 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001470{
1471 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1472 {
1473 return false;
1474 }
1475
1476 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1477 depth, border, imageSize, data);
1478}
1479
Austin Kinrossbc781f32015-10-26 09:27:38 -07001480bool ValidateBindVertexArray(Context *context, GLuint array)
1481{
Martin Radev1be913c2016-07-11 17:59:16 +03001482 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001483 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001484 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001485 return false;
1486 }
1487
1488 return ValidateBindVertexArrayBase(context, array);
1489}
1490
Jamie Madilld7576732017-08-26 18:49:50 -04001491bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001492{
Martin Radev1be913c2016-07-11 17:59:16 +03001493 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001494 {
Jamie Madilld7576732017-08-26 18:49:50 -04001495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001496 return false;
1497 }
1498
1499 return true;
1500}
Geoff Langc5629752015-12-07 16:29:04 -05001501
Jiajia Qin6eafb042016-12-27 17:04:07 +08001502static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001503 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 GLuint index,
1505 GLuint buffer,
1506 GLintptr offset,
1507 GLsizeiptr size)
1508{
1509 if (context->getClientMajorVersion() < 3)
1510 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001512 return false;
1513 }
1514
1515 if (buffer != 0 && offset < 0)
1516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001518 return false;
1519 }
1520
1521 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1522 !context->isBufferGenerated(buffer))
1523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001524 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001525 return false;
1526 }
1527
1528 const Caps &caps = context->getCaps();
1529 switch (target)
1530 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001531 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 {
1533 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(InvalidValue() << "index is greater than or equal to the "
1536 "number of TRANSFORM_FEEDBACK_BUFFER "
1537 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001538 return false;
1539 }
1540 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001542 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001543 return false;
1544 }
1545
1546 TransformFeedback *curTransformFeedback =
1547 context->getGLState().getCurrentTransformFeedback();
1548 if (curTransformFeedback && curTransformFeedback->isActive())
1549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001550 context->handleError(InvalidOperation()
1551 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1552 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001553 return false;
1554 }
1555 break;
1556 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001557 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001558 {
1559 if (index >= caps.maxUniformBufferBindings)
1560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidValue() << "index is greater than or equal to the "
1562 "number of UNIFORM_BUFFER indexed "
1563 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001564 return false;
1565 }
1566
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001567 ASSERT(caps.uniformBufferOffsetAlignment);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001568 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1569 {
1570 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001571 InvalidValue()
1572 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001573 return false;
1574 }
1575 break;
1576 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001577 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001578 {
1579 if (context->getClientVersion() < ES_3_1)
1580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001581 context->handleError(InvalidEnum()
1582 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001583 return false;
1584 }
1585 if (index >= caps.maxAtomicCounterBufferBindings)
1586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidValue() << "index is greater than or equal to the "
1588 "number of ATOMIC_COUNTER_BUFFER "
1589 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001590 return false;
1591 }
1592 if (buffer != 0 && (offset % 4) != 0)
1593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001595 return false;
1596 }
1597 break;
1598 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001599 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001600 {
1601 if (context->getClientVersion() < ES_3_1)
1602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001603 context->handleError(InvalidEnum()
1604 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001605 return false;
1606 }
1607 if (index >= caps.maxShaderStorageBufferBindings)
1608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidValue() << "index is greater than or equal to the "
1610 "number of SHADER_STORAGE_BUFFER "
1611 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001612 return false;
1613 }
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001614 ASSERT(caps.shaderStorageBufferOffsetAlignment);
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001615 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidValue() << "offset must be multiple of value of "
1618 "SHADER_STORAGE_BUFFER_OFFSET_"
1619 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001620 return false;
1621 }
1622 break;
1623 }
1624 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001626 return false;
1627 }
1628
1629 return true;
1630}
1631
Corentin Wallez336129f2017-10-17 15:55:40 -04001632bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001633{
1634 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1635}
1636
1637bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001638 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001639 GLuint index,
1640 GLuint buffer,
1641 GLintptr offset,
1642 GLsizeiptr size)
1643{
1644 if (buffer != 0 && size <= 0)
1645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidValue()
1647 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001648 return false;
1649 }
1650 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1651}
1652
Geoff Langc5629752015-12-07 16:29:04 -05001653bool ValidateProgramBinary(Context *context,
1654 GLuint program,
1655 GLenum binaryFormat,
1656 const void *binary,
1657 GLint length)
1658{
Martin Radev1be913c2016-07-11 17:59:16 +03001659 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001660 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001662 return false;
1663 }
1664
1665 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1666}
1667
1668bool ValidateGetProgramBinary(Context *context,
1669 GLuint program,
1670 GLsizei bufSize,
1671 GLsizei *length,
1672 GLenum *binaryFormat,
1673 void *binary)
1674{
Martin Radev1be913c2016-07-11 17:59:16 +03001675 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001676 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001678 return false;
1679 }
1680
1681 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1682}
1683
Olli Etuahof0fee072016-03-30 15:11:58 +03001684bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001685{
Martin Radev1be913c2016-07-11 17:59:16 +03001686 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001687 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001689 return false;
1690 }
1691
1692 if (GetValidProgram(context, program) == nullptr)
1693 {
1694 return false;
1695 }
1696
1697 switch (pname)
1698 {
1699 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001700 if (value != GL_FALSE && value != GL_TRUE)
1701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(InvalidValue()
1703 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001704 return false;
1705 }
Geoff Langc5629752015-12-07 16:29:04 -05001706 break;
1707
Yunchao He61afff12017-03-14 15:34:03 +08001708 case GL_PROGRAM_SEPARABLE:
1709 if (context->getClientVersion() < ES_3_1)
1710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001711 context->handleError(InvalidEnum()
1712 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001713 return false;
1714 }
1715
1716 if (value != GL_FALSE && value != GL_TRUE)
1717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001718 context->handleError(InvalidValue()
1719 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001720 return false;
1721 }
1722 break;
1723
Geoff Langc5629752015-12-07 16:29:04 -05001724 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidEnum()
1726 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001727 return false;
1728 }
1729
1730 return true;
1731}
Jamie Madillc29968b2016-01-20 11:17:23 -05001732
1733bool ValidateBlitFramebuffer(Context *context,
1734 GLint srcX0,
1735 GLint srcY0,
1736 GLint srcX1,
1737 GLint srcY1,
1738 GLint dstX0,
1739 GLint dstY0,
1740 GLint dstX1,
1741 GLint dstY1,
1742 GLbitfield mask,
1743 GLenum filter)
1744{
Martin Radev1be913c2016-07-11 17:59:16 +03001745 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001746 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750
1751 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1752 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753}
Jamie Madillc29968b2016-01-20 11:17:23 -05001754
Jamie Madill5b772312018-03-08 20:28:32 -05001755bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001756{
1757 switch (buffer)
1758 {
1759 case GL_COLOR:
1760 if (drawbuffer < 0 ||
1761 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001763 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001764 return false;
1765 }
Geoff Lang76e65652017-03-27 14:58:02 -04001766 if (context->getExtensions().webglCompatibility)
1767 {
1768 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001769 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001770 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1771 {
1772 return false;
1773 }
1774 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001775 break;
1776
1777 case GL_STENCIL:
1778 if (drawbuffer != 0)
1779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783 break;
1784
1785 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001786 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001787 return false;
1788 }
1789
1790 return ValidateClearBuffer(context);
1791}
1792
Jamie Madill5b772312018-03-08 20:28:32 -05001793bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001794{
1795 switch (buffer)
1796 {
1797 case GL_COLOR:
1798 if (drawbuffer < 0 ||
1799 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001801 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001802 return false;
1803 }
Geoff Lang76e65652017-03-27 14:58:02 -04001804 if (context->getExtensions().webglCompatibility)
1805 {
1806 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001807 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001808 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1809 {
1810 return false;
1811 }
1812 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 break;
1814
1815 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001816 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819
1820 return ValidateClearBuffer(context);
1821}
1822
Jamie Madill5b772312018-03-08 20:28:32 -05001823bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001824{
1825 switch (buffer)
1826 {
1827 case GL_COLOR:
1828 if (drawbuffer < 0 ||
1829 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001831 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001832 return false;
1833 }
Geoff Lang76e65652017-03-27 14:58:02 -04001834 if (context->getExtensions().webglCompatibility)
1835 {
1836 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1837 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001838 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001839 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1840 {
1841 return false;
1842 }
1843 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001844 break;
1845
1846 case GL_DEPTH:
1847 if (drawbuffer != 0)
1848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001849 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852 break;
1853
1854 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001855 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 return false;
1857 }
1858
1859 return ValidateClearBuffer(context);
1860}
1861
Jamie Madill5b772312018-03-08 20:28:32 -05001862bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 GLenum buffer,
1864 GLint drawbuffer,
1865 GLfloat depth,
1866 GLint stencil)
1867{
1868 switch (buffer)
1869 {
1870 case GL_DEPTH_STENCIL:
1871 if (drawbuffer != 0)
1872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001873 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001874 return false;
1875 }
1876 break;
1877
1878 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001879 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
1883 return ValidateClearBuffer(context);
1884}
1885
Jamie Madill5b772312018-03-08 20:28:32 -05001886bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001887{
Martin Radev1be913c2016-07-11 17:59:16 +03001888 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001889 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001891 return false;
1892 }
1893
1894 return ValidateDrawBuffersBase(context, n, bufs);
1895}
1896
1897bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001898 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001899 GLint level,
1900 GLint xoffset,
1901 GLint yoffset,
1902 GLint zoffset,
1903 GLint x,
1904 GLint y,
1905 GLsizei width,
1906 GLsizei height)
1907{
Martin Radev1be913c2016-07-11 17:59:16 +03001908 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001909 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001910 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001911 return false;
1912 }
1913
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001914 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1915 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001916}
1917
Jamie Madill73a84962016-02-12 09:27:23 -05001918bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001919 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001920 GLint level,
1921 GLint internalformat,
1922 GLsizei width,
1923 GLsizei height,
1924 GLsizei depth,
1925 GLint border,
1926 GLenum format,
1927 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001928 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001929{
Martin Radev1be913c2016-07-11 17:59:16 +03001930 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001931 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001933 return false;
1934 }
1935
1936 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001937 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001938 pixels);
1939}
1940
Geoff Langc52f6f12016-10-14 10:18:00 -04001941bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001942 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001943 GLint level,
1944 GLint internalformat,
1945 GLsizei width,
1946 GLsizei height,
1947 GLsizei depth,
1948 GLint border,
1949 GLenum format,
1950 GLenum type,
1951 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001952 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001953{
1954 if (context->getClientMajorVersion() < 3)
1955 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001956 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001957 return false;
1958 }
1959
1960 if (!ValidateRobustEntryPoint(context, bufSize))
1961 {
1962 return false;
1963 }
1964
1965 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1966 0, 0, width, height, depth, border, format, type,
1967 bufSize, pixels);
1968}
1969
Jamie Madill73a84962016-02-12 09:27:23 -05001970bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001971 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001972 GLint level,
1973 GLint xoffset,
1974 GLint yoffset,
1975 GLint zoffset,
1976 GLsizei width,
1977 GLsizei height,
1978 GLsizei depth,
1979 GLenum format,
1980 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001981 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001982{
Martin Radev1be913c2016-07-11 17:59:16 +03001983 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001984 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001986 return false;
1987 }
1988
1989 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1990 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001991 -1, pixels);
1992}
1993
1994bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001995 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001996 GLint level,
1997 GLint xoffset,
1998 GLint yoffset,
1999 GLint zoffset,
2000 GLsizei width,
2001 GLsizei height,
2002 GLsizei depth,
2003 GLenum format,
2004 GLenum type,
2005 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002006 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002007{
2008 if (context->getClientMajorVersion() < 3)
2009 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002010 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04002011 return false;
2012 }
2013
2014 if (!ValidateRobustEntryPoint(context, bufSize))
2015 {
2016 return false;
2017 }
2018
2019 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2020 yoffset, zoffset, width, height, depth, 0, format, type,
2021 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002022}
2023
2024bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002025 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002026 GLint level,
2027 GLint xoffset,
2028 GLint yoffset,
2029 GLint zoffset,
2030 GLsizei width,
2031 GLsizei height,
2032 GLsizei depth,
2033 GLenum format,
2034 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002035 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002036{
Martin Radev1be913c2016-07-11 17:59:16 +03002037 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002038 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002039 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002040 return false;
2041 }
2042
Geoff Langca271392017-04-05 12:30:00 -04002043 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002044 if (!formatInfo.compressed)
2045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002046 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002047 return false;
2048 }
2049
Jamie Madillca2ff382018-07-11 09:01:17 -04002050 GLuint blockSize = 0;
2051 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002052 {
Jamie Madillca2ff382018-07-11 09:01:17 -04002053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madille2e406c2016-06-02 13:04:10 -04002054 return false;
2055 }
Jamie Madillca2ff382018-07-11 09:01:17 -04002056
2057 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill73a84962016-02-12 09:27:23 -05002058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002059 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002060 return false;
2061 }
2062
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002063 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2064 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2065 -1, data))
2066 {
2067 return false;
2068 }
2069
Jamie Madill73a84962016-02-12 09:27:23 -05002070 if (!data)
2071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002072 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002073 return false;
2074 }
2075
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002076 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002077}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002078
Corentin Wallezb2931602017-04-11 15:58:57 -04002079bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002080 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002081 GLint level,
2082 GLint xoffset,
2083 GLint yoffset,
2084 GLint zoffset,
2085 GLsizei width,
2086 GLsizei height,
2087 GLsizei depth,
2088 GLenum format,
2089 GLsizei imageSize,
2090 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002091 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002092{
2093 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2094 {
2095 return false;
2096 }
2097
2098 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2099 height, depth, format, imageSize, data);
2100}
Jamie Madill73a84962016-02-12 09:27:23 -05002101
Olli Etuaho41997e72016-03-10 13:38:39 +02002102bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2103{
2104 return ValidateGenOrDeleteES3(context, n);
2105}
2106
2107bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2108{
2109 return ValidateGenOrDeleteES3(context, n);
2110}
2111
2112bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2113{
2114 return ValidateGenOrDeleteCountES3(context, count);
2115}
2116
2117bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2118{
2119 return ValidateGenOrDeleteCountES3(context, count);
2120}
2121
2122bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2123{
2124 return ValidateGenOrDeleteES3(context, n);
2125}
2126
2127bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2128{
2129 if (!ValidateGenOrDeleteES3(context, n))
2130 {
2131 return false;
2132 }
2133 for (GLint i = 0; i < n; ++i)
2134 {
2135 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2136 if (transformFeedback != nullptr && transformFeedback->isActive())
2137 {
2138 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002139 context->handleError(InvalidOperation()
2140 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002141 return false;
2142 }
2143 }
2144 return true;
2145}
2146
2147bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2148{
2149 return ValidateGenOrDeleteES3(context, n);
2150}
2151
2152bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2153{
2154 return ValidateGenOrDeleteES3(context, n);
2155}
2156
Jamie Madill493f9572018-05-24 19:52:15 -04002157bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMode)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002158{
Martin Radev1be913c2016-07-11 17:59:16 +03002159 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002160 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002162 return false;
2163 }
2164 switch (primitiveMode)
2165 {
Jamie Madill493f9572018-05-24 19:52:15 -04002166 case PrimitiveMode::Triangles:
2167 case PrimitiveMode::Lines:
2168 case PrimitiveMode::Points:
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002169 break;
2170
2171 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002172 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002173 return false;
2174 }
2175
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002176 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002177 ASSERT(transformFeedback != nullptr);
2178
2179 if (transformFeedback->isActive())
2180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002181 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002182 return false;
2183 }
Geoff Lang79f71042017-08-14 16:43:43 -04002184
2185 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2186 {
2187 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2188 if (buffer.get() && buffer->isMapped())
2189 {
2190 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2191 return false;
2192 }
2193 }
2194
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002195 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002196
2197 if (!program)
2198 {
2199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2200 return false;
2201 }
2202
2203 if (program->getTransformFeedbackVaryingCount() == 0)
2204 {
2205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2206 return false;
2207 }
2208
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002209 return true;
2210}
2211
Corentin Wallez336129f2017-10-17 15:55:40 -04002212bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002213{
Geoff Lang496c02d2016-10-20 11:38:11 -07002214 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2215}
2216
2217bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002218 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002219 GLenum pname,
2220 GLsizei bufSize,
2221 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002222 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002223{
2224 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002225 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002226 return false;
2227 }
2228
Brandon Jonesd1049182018-03-28 10:02:20 -07002229 GLsizei numParams = 0;
2230
2231 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002232 {
2233 return false;
2234 }
2235
Brandon Jonesd1049182018-03-28 10:02:20 -07002236 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002237 {
2238 return false;
2239 }
2240
Brandon Jonesd1049182018-03-28 10:02:20 -07002241 SetRobustLengthParam(length, numParams);
2242
Geoff Lang496c02d2016-10-20 11:38:11 -07002243 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002244}
2245
Corentin Wallez336129f2017-10-17 15:55:40 -04002246bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002247{
Martin Radev1be913c2016-07-11 17:59:16 +03002248 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002249 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002251 return false;
2252 }
2253
2254 return ValidateUnmapBufferBase(context, target);
2255}
2256
2257bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002258 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002259 GLintptr offset,
2260 GLsizeiptr length,
2261 GLbitfield access)
2262{
Martin Radev1be913c2016-07-11 17:59:16 +03002263 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002264 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002266 return false;
2267 }
2268
2269 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2270}
2271
2272bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002273 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002274 GLintptr offset,
2275 GLsizeiptr length)
2276{
Martin Radev1be913c2016-07-11 17:59:16 +03002277 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002278 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002279 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002280 return false;
2281 }
2282
2283 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2284}
2285
Jamie Madill5b772312018-03-08 20:28:32 -05002286bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002287{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002288 if (length)
2289 {
2290 *length = 0;
2291 }
2292
Martin Radev66fb8202016-07-28 11:45:20 +03002293 GLenum nativeType;
2294 unsigned int numParams;
2295 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002298 return false;
2299 }
2300
2301 const Caps &caps = context->getCaps();
2302 switch (pname)
2303 {
2304 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2305 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2306 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2307 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002309 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002310 return false;
2311 }
2312 break;
2313
2314 case GL_UNIFORM_BUFFER_START:
2315 case GL_UNIFORM_BUFFER_SIZE:
2316 case GL_UNIFORM_BUFFER_BINDING:
2317 if (index >= caps.maxUniformBufferBindings)
2318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002319 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002320 return false;
2321 }
2322 break;
Shao80957d92017-02-20 21:25:59 +08002323
Martin Radev66fb8202016-07-28 11:45:20 +03002324 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2325 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2326 if (index >= 3u)
2327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002328 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002329 return false;
2330 }
2331 break;
Shao80957d92017-02-20 21:25:59 +08002332
Jiajia Qin6eafb042016-12-27 17:04:07 +08002333 case GL_ATOMIC_COUNTER_BUFFER_START:
2334 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2335 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2336 if (context->getClientVersion() < ES_3_1)
2337 {
2338 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002339 InvalidEnum()
2340 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002341 return false;
2342 }
2343 if (index >= caps.maxAtomicCounterBufferBindings)
2344 {
2345 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002346 InvalidValue()
2347 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002348 return false;
2349 }
2350 break;
Shao80957d92017-02-20 21:25:59 +08002351
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002352 case GL_SHADER_STORAGE_BUFFER_START:
2353 case GL_SHADER_STORAGE_BUFFER_SIZE:
2354 case GL_SHADER_STORAGE_BUFFER_BINDING:
2355 if (context->getClientVersion() < ES_3_1)
2356 {
2357 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002358 InvalidEnum()
2359 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002360 return false;
2361 }
2362 if (index >= caps.maxShaderStorageBufferBindings)
2363 {
2364 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 InvalidValue()
2366 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002367 return false;
2368 }
2369 break;
2370
Shao80957d92017-02-20 21:25:59 +08002371 case GL_VERTEX_BINDING_BUFFER:
2372 case GL_VERTEX_BINDING_DIVISOR:
2373 case GL_VERTEX_BINDING_OFFSET:
2374 case GL_VERTEX_BINDING_STRIDE:
2375 if (context->getClientVersion() < ES_3_1)
2376 {
2377 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002378 InvalidEnum()
2379 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002380 return false;
2381 }
2382 if (index >= caps.maxVertexAttribBindings)
2383 {
2384 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002385 InvalidValue()
2386 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002387 return false;
2388 }
2389 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002390 case GL_SAMPLE_MASK_VALUE:
2391 if (context->getClientVersion() < ES_3_1)
2392 {
2393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2394 return false;
2395 }
2396 if (index >= caps.maxSampleMaskWords)
2397 {
2398 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2399 return false;
2400 }
2401 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002402 case GL_IMAGE_BINDING_NAME:
2403 case GL_IMAGE_BINDING_LEVEL:
2404 case GL_IMAGE_BINDING_LAYERED:
2405 case GL_IMAGE_BINDING_LAYER:
2406 case GL_IMAGE_BINDING_ACCESS:
2407 case GL_IMAGE_BINDING_FORMAT:
2408 if (context->getClientVersion() < ES_3_1)
2409 {
2410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2411 return false;
2412 }
2413 if (index >= caps.maxImageUnits)
2414 {
2415 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2416 return false;
2417 }
2418 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002419 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002420 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002421 return false;
2422 }
2423
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002424 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002425 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002426 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002427 }
2428
2429 return true;
2430}
2431
Jamie Madill5b772312018-03-08 20:28:32 -05002432bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002433{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002434 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002437 return false;
2438 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002439 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002440}
2441
Jamie Madill5b772312018-03-08 20:28:32 -05002442bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002443 GLenum target,
2444 GLuint index,
2445 GLsizei bufSize,
2446 GLsizei *length,
2447 GLint *data)
2448{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002449 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002450 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002452 return false;
2453 }
2454
2455 if (!ValidateRobustEntryPoint(context, bufSize))
2456 {
2457 return false;
2458 }
2459
Brandon Jonesd1049182018-03-28 10:02:20 -07002460 GLsizei numParams = 0;
2461
2462 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002463 {
2464 return false;
2465 }
2466
Brandon Jonesd1049182018-03-28 10:02:20 -07002467 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002468 {
2469 return false;
2470 }
2471
Brandon Jonesd1049182018-03-28 10:02:20 -07002472 SetRobustLengthParam(length, numParams);
2473
Geoff Langcf255ea2016-10-20 11:39:09 -07002474 return true;
2475}
2476
Jamie Madill5b772312018-03-08 20:28:32 -05002477bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002478{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002479 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002480 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002481 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002482 return false;
2483 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002484 return ValidateIndexedStateQuery(context, target, index, nullptr);
2485}
2486
Jamie Madill5b772312018-03-08 20:28:32 -05002487bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002488 GLenum target,
2489 GLuint index,
2490 GLsizei bufSize,
2491 GLsizei *length,
2492 GLint64 *data)
2493{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002494 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002495 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002497 return false;
2498 }
2499
2500 if (!ValidateRobustEntryPoint(context, bufSize))
2501 {
2502 return false;
2503 }
2504
Brandon Jonesd1049182018-03-28 10:02:20 -07002505 GLsizei numParams = 0;
2506
2507 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002508 {
2509 return false;
2510 }
2511
Brandon Jonesd1049182018-03-28 10:02:20 -07002512 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002513 {
2514 return false;
2515 }
2516
Brandon Jonesd1049182018-03-28 10:02:20 -07002517 SetRobustLengthParam(length, numParams);
2518
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002519 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002520}
2521
Jamie Madill5b772312018-03-08 20:28:32 -05002522bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002523 BufferBinding readTarget,
2524 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002525 GLintptr readOffset,
2526 GLintptr writeOffset,
2527 GLsizeiptr size)
2528{
2529 if (context->getClientMajorVersion() < 3)
2530 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002532 return false;
2533 }
2534
Corentin Walleze4477002017-12-01 14:39:58 -05002535 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002537 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002538 return false;
2539 }
2540
2541 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2542 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2543
2544 if (!readBuffer || !writeBuffer)
2545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002546 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002547 return false;
2548 }
2549
2550 // Verify that readBuffer and writeBuffer are not currently mapped
2551 if (readBuffer->isMapped() || writeBuffer->isMapped())
2552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002553 context->handleError(InvalidOperation()
2554 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002555 return false;
2556 }
2557
James Darpiniane8a93c62018-01-04 18:02:24 -08002558 if (context->getExtensions().webglCompatibility &&
2559 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2560 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2561 {
2562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2563 return false;
2564 }
2565
Jamie Madilld2f0c742016-11-02 10:34:41 -04002566 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2567 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2568 CheckedNumeric<GLintptr> checkedSize(size);
2569
2570 auto checkedReadSum = checkedReadOffset + checkedSize;
2571 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2572
2573 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2574 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2575 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002577 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002578 return false;
2579 }
2580
Jamie Madilld2f0c742016-11-02 10:34:41 -04002581 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002583 context->handleError(InvalidValue()
2584 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002585 return false;
2586 }
2587
Jamie Madilld2f0c742016-11-02 10:34:41 -04002588 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2589 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002591 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002592 return false;
2593 }
2594
2595 if (readBuffer == writeBuffer)
2596 {
2597 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2598 if (!checkedOffsetDiff.IsValid())
2599 {
2600 // This shold not be possible.
2601 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002602 context->handleError(InvalidValue()
2603 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002604 return false;
2605 }
2606
2607 if (checkedOffsetDiff.ValueOrDie() < size)
2608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002609 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002610 return false;
2611 }
2612 }
2613
Jamie Madillb0817d12016-11-01 15:48:31 -04002614 return true;
2615}
2616
Geoff Langc339c4e2016-11-29 10:37:36 -05002617bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2618{
2619 if (context->getClientMajorVersion() < 3)
2620 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002621 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002622 return false;
2623 }
2624
2625 switch (name)
2626 {
2627 case GL_EXTENSIONS:
2628 if (index >= context->getExtensionStringCount())
2629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 context->handleError(InvalidValue()
2631 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002632 return false;
2633 }
2634 break;
2635
2636 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2637 if (!context->getExtensions().requestExtension)
2638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002640 return false;
2641 }
2642 if (index >= context->getRequestableExtensionStringCount())
2643 {
2644 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002645 InvalidValue()
2646 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002647 return false;
2648 }
2649 break;
2650
2651 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002653 return false;
2654 }
2655
2656 return true;
2657}
2658
Jamie Madill5b772312018-03-08 20:28:32 -05002659bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002660 GLenum target,
2661 GLsizei samples,
2662 GLenum internalformat,
2663 GLsizei width,
2664 GLsizei height)
2665{
2666 if (context->getClientMajorVersion() < 3)
2667 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002669 return false;
2670 }
2671
2672 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2673 height))
2674 {
2675 return false;
2676 }
2677
2678 // 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 +08002679 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2680 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002681 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002682 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002683 {
Yunchao Hec0810202018-01-22 09:48:48 +08002684 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2685 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2686 {
2687 context->handleError(InvalidOperation());
2688 return false;
2689 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002690 }
2691
2692 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2693 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2694 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2695 {
2696 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002697 InvalidOperation()
2698 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002699 return false;
2700 }
2701
2702 return true;
2703}
2704
Jamie Madill5b772312018-03-08 20:28:32 -05002705bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002706 GLuint index,
2707 GLint size,
2708 GLenum type,
2709 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002710 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002711{
2712 if (context->getClientMajorVersion() < 3)
2713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002715 return false;
2716 }
2717
Shao80957d92017-02-20 21:25:59 +08002718 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002719 {
Geoff Langaa086d62017-03-23 16:47:21 -04002720 return false;
2721 }
2722
Geoff Langaa086d62017-03-23 16:47:21 -04002723 if (stride < 0)
2724 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002725 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002726 return false;
2727 }
2728
Shao80957d92017-02-20 21:25:59 +08002729 const Caps &caps = context->getCaps();
2730 if (context->getClientVersion() >= ES_3_1)
2731 {
2732 if (stride > caps.maxVertexAttribStride)
2733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002734 context->handleError(InvalidValue()
2735 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002736 return false;
2737 }
2738
2739 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2740 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2741 // validation should be inherited.
2742 if (index >= caps.maxVertexAttribBindings)
2743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002744 context->handleError(InvalidValue()
2745 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002746 return false;
2747 }
2748 }
2749
Geoff Langaa086d62017-03-23 16:47:21 -04002750 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2751 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2752 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2753 // and the pointer argument is not NULL.
2754 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002755 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002757 context
2758 ->handleError(InvalidOperation()
2759 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002760 return false;
2761 }
2762
Geoff Lang2d62ab72017-03-23 16:54:40 -04002763 if (context->getExtensions().webglCompatibility)
2764 {
2765 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2766 {
2767 return false;
2768 }
2769 }
2770
Geoff Langaa086d62017-03-23 16:47:21 -04002771 return true;
2772}
2773
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002774bool ValidateGetSynciv(Context *context,
2775 GLsync sync,
2776 GLenum pname,
2777 GLsizei bufSize,
2778 GLsizei *length,
2779 GLint *values)
2780{
2781 if (context->getClientMajorVersion() < 3)
2782 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002784 return false;
2785 }
2786
2787 if (bufSize < 0)
2788 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002789 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002790 return false;
2791 }
2792
Jamie Madill70b5bb02017-08-28 13:32:37 -04002793 Sync *syncObject = context->getSync(sync);
2794 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002796 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002797 return false;
2798 }
2799
2800 switch (pname)
2801 {
2802 case GL_OBJECT_TYPE:
2803 case GL_SYNC_CONDITION:
2804 case GL_SYNC_FLAGS:
2805 case GL_SYNC_STATUS:
2806 break;
2807
2808 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002809 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002810 return false;
2811 }
2812
2813 return true;
2814}
2815
Jamie Madill5b772312018-03-08 20:28:32 -05002816bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002817 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002818 GLsizei count,
2819 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002820 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002821 GLsizei instanceCount)
2822{
2823 if (context->getClientMajorVersion() < 3)
2824 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002825 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002826 return false;
2827 }
2828
2829 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2830}
2831
Martin Radev137032d2017-07-13 10:11:12 +03002832bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2833 GLenum target,
2834 GLenum attachment,
2835 GLuint texture,
2836 GLint level,
2837 GLint baseViewIndex,
2838 GLsizei numViews)
2839{
Martin Radev137032d2017-07-13 10:11:12 +03002840 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2841 numViews))
2842 {
2843 return false;
2844 }
2845
Martin Radev137032d2017-07-13 10:11:12 +03002846 if (texture != 0)
2847 {
Martin Radev14b21262017-08-25 13:54:37 +03002848 if (baseViewIndex < 0)
2849 {
2850 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2851 return false;
2852 }
2853
Martin Radev137032d2017-07-13 10:11:12 +03002854 Texture *tex = context->getTexture(texture);
2855 ASSERT(tex);
2856
Corentin Wallez99d492c2018-02-27 15:17:10 -05002857 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002858 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002859 case TextureType::_2DArray:
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002860 case TextureType::_2DMultisampleArray:
Martin Radev137032d2017-07-13 10:11:12 +03002861 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002862 if (tex->getType() == TextureType::_2DMultisampleArray)
2863 {
2864 if (!context->getExtensions().multiviewMultisample)
2865 {
2866 context->handleError(InvalidOperation()
2867 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2868 return false;
2869 }
2870 }
2871
Martin Radev137032d2017-07-13 10:11:12 +03002872 const Caps &caps = context->getCaps();
2873 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2874 {
2875 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2876 "greater than "
2877 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2878 return false;
2879 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002880
2881 break;
Martin Radev137032d2017-07-13 10:11:12 +03002882 }
Martin Radev137032d2017-07-13 10:11:12 +03002883 default:
2884 context->handleError(InvalidOperation()
2885 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2886 return false;
2887 }
2888
2889 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2890 {
2891 return false;
2892 }
2893 }
2894
2895 return true;
2896}
2897
2898bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2899 GLenum target,
2900 GLenum attachment,
2901 GLuint texture,
2902 GLint level,
2903 GLsizei numViews,
2904 const GLint *viewportOffsets)
2905{
2906 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2907 numViews))
2908 {
2909 return false;
2910 }
2911
Martin Radev137032d2017-07-13 10:11:12 +03002912 if (texture != 0)
2913 {
Martin Radev14b21262017-08-25 13:54:37 +03002914 const GLsizei numViewportOffsetValues = numViews * 2;
2915 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2916 {
2917 if (viewportOffsets[i] < 0)
2918 {
2919 context->handleError(InvalidValue()
2920 << "viewportOffsets cannot contain negative values.");
2921 return false;
2922 }
2923 }
2924
Martin Radev137032d2017-07-13 10:11:12 +03002925 Texture *tex = context->getTexture(texture);
2926 ASSERT(tex);
2927
Corentin Wallez99d492c2018-02-27 15:17:10 -05002928 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002929 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002930 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002931 break;
2932 default:
2933 context->handleError(InvalidOperation()
2934 << "Texture's target must be GL_TEXTURE_2D.");
2935 return false;
2936 }
2937
2938 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2939 {
2940 return false;
2941 }
2942 }
2943
2944 return true;
2945}
2946
Jamie Madillff325f12017-08-26 15:06:05 -04002947bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2948{
2949 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2950}
2951
2952bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2953{
2954 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2955}
2956
2957bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2958{
2959 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2960}
2961
2962bool ValidateUniform4ui(Context *context,
2963 GLint location,
2964 GLuint v0,
2965 GLuint v1,
2966 GLuint v2,
2967 GLuint v3)
2968{
2969 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2970}
2971
2972bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2973{
2974 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2975}
2976
2977bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2978{
2979 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2980}
2981
2982bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2983{
2984 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2985}
2986
2987bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2988{
2989 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2990}
2991
Jamie Madillf0e04492017-08-26 15:28:42 -04002992bool ValidateIsQuery(Context *context, GLuint id)
2993{
2994 if (context->getClientMajorVersion() < 3)
2995 {
2996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2997 return false;
2998 }
2999
3000 return true;
3001}
3002
Jamie Madillc8c95812017-08-26 18:40:09 -04003003bool ValidateUniformMatrix2x3fv(Context *context,
3004 GLint location,
3005 GLsizei count,
3006 GLboolean transpose,
3007 const GLfloat *value)
3008{
3009 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
3010}
3011
3012bool ValidateUniformMatrix3x2fv(Context *context,
3013 GLint location,
3014 GLsizei count,
3015 GLboolean transpose,
3016 const GLfloat *value)
3017{
3018 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
3019}
3020
3021bool ValidateUniformMatrix2x4fv(Context *context,
3022 GLint location,
3023 GLsizei count,
3024 GLboolean transpose,
3025 const GLfloat *value)
3026{
3027 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
3028}
3029
3030bool ValidateUniformMatrix4x2fv(Context *context,
3031 GLint location,
3032 GLsizei count,
3033 GLboolean transpose,
3034 const GLfloat *value)
3035{
3036 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3037}
3038
3039bool ValidateUniformMatrix3x4fv(Context *context,
3040 GLint location,
3041 GLsizei count,
3042 GLboolean transpose,
3043 const GLfloat *value)
3044{
3045 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3046}
3047
3048bool ValidateUniformMatrix4x3fv(Context *context,
3049 GLint location,
3050 GLsizei count,
3051 GLboolean transpose,
3052 const GLfloat *value)
3053{
3054 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3055}
3056
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003057bool ValidateEndTransformFeedback(Context *context)
3058{
3059 if (context->getClientMajorVersion() < 3)
3060 {
3061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3062 return false;
3063 }
3064
3065 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3066 ASSERT(transformFeedback != nullptr);
3067
3068 if (!transformFeedback->isActive())
3069 {
3070 context->handleError(InvalidOperation());
3071 return false;
3072 }
3073
3074 return true;
3075}
3076
3077bool ValidateTransformFeedbackVaryings(Context *context,
3078 GLuint program,
3079 GLsizei count,
3080 const GLchar *const *varyings,
3081 GLenum bufferMode)
3082{
3083 if (context->getClientMajorVersion() < 3)
3084 {
3085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3086 return false;
3087 }
3088
3089 if (count < 0)
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3092 return false;
3093 }
3094
3095 switch (bufferMode)
3096 {
3097 case GL_INTERLEAVED_ATTRIBS:
3098 break;
3099 case GL_SEPARATE_ATTRIBS:
3100 {
3101 const Caps &caps = context->getCaps();
3102 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3103 {
3104 context->handleError(InvalidValue());
3105 return false;
3106 }
3107 break;
3108 }
3109 default:
3110 context->handleError(InvalidEnum());
3111 return false;
3112 }
3113
3114 Program *programObject = GetValidProgram(context, program);
3115 if (!programObject)
3116 {
3117 return false;
3118 }
3119
3120 return true;
3121}
3122
3123bool ValidateGetTransformFeedbackVarying(Context *context,
3124 GLuint program,
3125 GLuint index,
3126 GLsizei bufSize,
3127 GLsizei *length,
3128 GLsizei *size,
3129 GLenum *type,
3130 GLchar *name)
3131{
3132 if (context->getClientMajorVersion() < 3)
3133 {
3134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3135 return false;
3136 }
3137
3138 if (bufSize < 0)
3139 {
3140 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3141 return false;
3142 }
3143
3144 Program *programObject = GetValidProgram(context, program);
3145 if (!programObject)
3146 {
3147 return false;
3148 }
3149
3150 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3151 {
3152 context->handleError(InvalidValue());
3153 return false;
3154 }
3155
3156 return true;
3157}
3158
3159bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3160{
3161 if (context->getClientMajorVersion() < 3)
3162 {
3163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3164 return false;
3165 }
3166
3167 switch (target)
3168 {
3169 case GL_TRANSFORM_FEEDBACK:
3170 {
3171 // Cannot bind a transform feedback object if the current one is started and not
3172 // paused (3.0.2 pg 85 section 2.14.1)
3173 TransformFeedback *curTransformFeedback =
3174 context->getGLState().getCurrentTransformFeedback();
3175 if (curTransformFeedback && curTransformFeedback->isActive() &&
3176 !curTransformFeedback->isPaused())
3177 {
3178 context->handleError(InvalidOperation());
3179 return false;
3180 }
3181
3182 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3183 // 2.14.1)
3184 if (!context->isTransformFeedbackGenerated(id))
3185 {
3186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3187 return false;
3188 }
3189 }
3190 break;
3191
3192 default:
3193 context->handleError(InvalidEnum());
3194 return false;
3195 }
3196
3197 return true;
3198}
3199
3200bool ValidateIsTransformFeedback(Context *context, GLuint id)
3201{
3202 if (context->getClientMajorVersion() < 3)
3203 {
3204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3205 return false;
3206 }
3207
3208 return true;
3209}
3210
3211bool ValidatePauseTransformFeedback(Context *context)
3212{
3213 if (context->getClientMajorVersion() < 3)
3214 {
3215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3216 return false;
3217 }
3218
3219 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3220 ASSERT(transformFeedback != nullptr);
3221
3222 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3223 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3224 {
3225 context->handleError(InvalidOperation());
3226 return false;
3227 }
3228
3229 return true;
3230}
3231
3232bool ValidateResumeTransformFeedback(Context *context)
3233{
3234 if (context->getClientMajorVersion() < 3)
3235 {
3236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3237 return false;
3238 }
3239
3240 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3241 ASSERT(transformFeedback != nullptr);
3242
3243 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3244 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3245 {
3246 context->handleError(InvalidOperation());
3247 return false;
3248 }
3249
3250 return true;
3251}
3252
Jamie Madill12e957f2017-08-26 21:42:26 -04003253bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3254{
3255 if (context->getClientMajorVersion() < 3)
3256 {
3257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3258 return false;
3259 }
3260
3261 return ValidateVertexAttribIndex(context, index);
3262}
3263
3264bool ValidateVertexAttribI4ui(Context *context,
3265 GLuint index,
3266 GLuint x,
3267 GLuint y,
3268 GLuint z,
3269 GLuint w)
3270{
3271 if (context->getClientMajorVersion() < 3)
3272 {
3273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3274 return false;
3275 }
3276
3277 return ValidateVertexAttribIndex(context, index);
3278}
3279
3280bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3281{
3282 if (context->getClientMajorVersion() < 3)
3283 {
3284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3285 return false;
3286 }
3287
3288 return ValidateVertexAttribIndex(context, index);
3289}
3290
3291bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3292{
3293 if (context->getClientMajorVersion() < 3)
3294 {
3295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3296 return false;
3297 }
3298
3299 return ValidateVertexAttribIndex(context, index);
3300}
3301
3302bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3303{
3304 if (context->getClientMajorVersion() < 3)
3305 {
3306 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3307 return false;
3308 }
3309
3310 Program *programObject = GetValidProgram(context, program);
3311 if (!programObject)
3312 {
3313 return false;
3314 }
3315
3316 if (!programObject->isLinked())
3317 {
3318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3319 return false;
3320 }
3321
3322 return true;
3323}
3324
3325bool ValidateGetUniformIndices(Context *context,
3326 GLuint program,
3327 GLsizei uniformCount,
3328 const GLchar *const *uniformNames,
3329 GLuint *uniformIndices)
3330{
3331 if (context->getClientMajorVersion() < 3)
3332 {
3333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3334 return false;
3335 }
3336
3337 if (uniformCount < 0)
3338 {
3339 context->handleError(InvalidValue());
3340 return false;
3341 }
3342
3343 Program *programObject = GetValidProgram(context, program);
3344 if (!programObject)
3345 {
3346 return false;
3347 }
3348
3349 return true;
3350}
3351
3352bool ValidateGetActiveUniformsiv(Context *context,
3353 GLuint program,
3354 GLsizei uniformCount,
3355 const GLuint *uniformIndices,
3356 GLenum pname,
3357 GLint *params)
3358{
3359 if (context->getClientMajorVersion() < 3)
3360 {
3361 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3362 return false;
3363 }
3364
3365 if (uniformCount < 0)
3366 {
3367 context->handleError(InvalidValue());
3368 return false;
3369 }
3370
3371 Program *programObject = GetValidProgram(context, program);
3372 if (!programObject)
3373 {
3374 return false;
3375 }
3376
3377 switch (pname)
3378 {
3379 case GL_UNIFORM_TYPE:
3380 case GL_UNIFORM_SIZE:
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07003381 break;
Jamie Madill12e957f2017-08-26 21:42:26 -04003382 case GL_UNIFORM_NAME_LENGTH:
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07003383 if (context->getExtensions().webglCompatibility)
3384 {
3385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3386 return false;
3387 }
3388 break;
Jamie Madill12e957f2017-08-26 21:42:26 -04003389 case GL_UNIFORM_BLOCK_INDEX:
3390 case GL_UNIFORM_OFFSET:
3391 case GL_UNIFORM_ARRAY_STRIDE:
3392 case GL_UNIFORM_MATRIX_STRIDE:
3393 case GL_UNIFORM_IS_ROW_MAJOR:
3394 break;
3395
3396 default:
3397 context->handleError(InvalidEnum());
3398 return false;
3399 }
3400
3401 if (uniformCount > programObject->getActiveUniformCount())
3402 {
3403 context->handleError(InvalidValue());
3404 return false;
3405 }
3406
3407 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3408 {
3409 const GLuint index = uniformIndices[uniformId];
3410
3411 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3412 {
3413 context->handleError(InvalidValue());
3414 return false;
3415 }
3416 }
3417
3418 return true;
3419}
3420
3421bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3422{
3423 if (context->getClientMajorVersion() < 3)
3424 {
3425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3426 return false;
3427 }
3428
3429 Program *programObject = GetValidProgram(context, program);
3430 if (!programObject)
3431 {
3432 return false;
3433 }
3434
3435 return true;
3436}
3437
3438bool ValidateGetActiveUniformBlockiv(Context *context,
3439 GLuint program,
3440 GLuint uniformBlockIndex,
3441 GLenum pname,
3442 GLint *params)
3443{
3444 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3445}
3446
3447bool ValidateGetActiveUniformBlockName(Context *context,
3448 GLuint program,
3449 GLuint uniformBlockIndex,
3450 GLsizei bufSize,
3451 GLsizei *length,
3452 GLchar *uniformBlockName)
3453{
3454 if (context->getClientMajorVersion() < 3)
3455 {
3456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3457 return false;
3458 }
3459
3460 Program *programObject = GetValidProgram(context, program);
3461 if (!programObject)
3462 {
3463 return false;
3464 }
3465
3466 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3467 {
3468 context->handleError(InvalidValue());
3469 return false;
3470 }
3471
3472 return true;
3473}
3474
3475bool ValidateUniformBlockBinding(Context *context,
3476 GLuint program,
3477 GLuint uniformBlockIndex,
3478 GLuint uniformBlockBinding)
3479{
3480 if (context->getClientMajorVersion() < 3)
3481 {
3482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3483 return false;
3484 }
3485
3486 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3487 {
3488 context->handleError(InvalidValue());
3489 return false;
3490 }
3491
3492 Program *programObject = GetValidProgram(context, program);
3493 if (!programObject)
3494 {
3495 return false;
3496 }
3497
3498 // if never linked, there won't be any uniform blocks
3499 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3500 {
3501 context->handleError(InvalidValue());
3502 return false;
3503 }
3504
3505 return true;
3506}
3507
3508bool ValidateDrawArraysInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003509 PrimitiveMode mode,
Jamie Madill12e957f2017-08-26 21:42:26 -04003510 GLint first,
3511 GLsizei count,
3512 GLsizei primcount)
3513{
3514 if (context->getClientMajorVersion() < 3)
3515 {
3516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3517 return false;
3518 }
3519
3520 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3521}
3522
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003523bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3524{
3525 if (context->getClientMajorVersion() < 3)
3526 {
3527 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3528 return false;
3529 }
3530
3531 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3532 {
3533 context->handleError(InvalidEnum());
3534 return false;
3535 }
3536
3537 if (flags != 0)
3538 {
3539 context->handleError(InvalidValue());
3540 return false;
3541 }
3542
3543 return true;
3544}
3545
3546bool ValidateIsSync(Context *context, GLsync sync)
3547{
3548 if (context->getClientMajorVersion() < 3)
3549 {
3550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3551 return false;
3552 }
3553
3554 return true;
3555}
3556
3557bool ValidateDeleteSync(Context *context, GLsync sync)
3558{
3559 if (context->getClientMajorVersion() < 3)
3560 {
3561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3562 return false;
3563 }
3564
Jamie Madill70b5bb02017-08-28 13:32:37 -04003565 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003566 {
3567 context->handleError(InvalidValue());
3568 return false;
3569 }
3570
3571 return true;
3572}
3573
3574bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3575{
3576 if (context->getClientMajorVersion() < 3)
3577 {
3578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3579 return false;
3580 }
3581
3582 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3583 {
3584 context->handleError(InvalidValue());
3585 return false;
3586 }
3587
Jamie Madill70b5bb02017-08-28 13:32:37 -04003588 Sync *clientWaitSync = context->getSync(sync);
3589 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003590 {
3591 context->handleError(InvalidValue());
3592 return false;
3593 }
3594
3595 return true;
3596}
3597
3598bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3599{
3600 if (context->getClientMajorVersion() < 3)
3601 {
3602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3603 return false;
3604 }
3605
3606 if (flags != 0)
3607 {
3608 context->handleError(InvalidValue());
3609 return false;
3610 }
3611
3612 if (timeout != GL_TIMEOUT_IGNORED)
3613 {
3614 context->handleError(InvalidValue());
3615 return false;
3616 }
3617
Jamie Madill70b5bb02017-08-28 13:32:37 -04003618 Sync *waitSync = context->getSync(sync);
3619 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003620 {
3621 context->handleError(InvalidValue());
3622 return false;
3623 }
3624
3625 return true;
3626}
3627
3628bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3629{
3630 if (context->getClientMajorVersion() < 3)
3631 {
3632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3633 return false;
3634 }
3635
3636 GLenum nativeType = GL_NONE;
3637 unsigned int numParams = 0;
3638 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3639 {
3640 return false;
3641 }
3642
3643 return true;
3644}
3645
Jamie Madill3ef140a2017-08-26 23:11:21 -04003646bool ValidateIsSampler(Context *context, GLuint sampler)
3647{
3648 if (context->getClientMajorVersion() < 3)
3649 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003651 return false;
3652 }
3653
3654 return true;
3655}
3656
3657bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3658{
3659 if (context->getClientMajorVersion() < 3)
3660 {
3661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3662 return false;
3663 }
3664
3665 if (sampler != 0 && !context->isSampler(sampler))
3666 {
3667 context->handleError(InvalidOperation());
3668 return false;
3669 }
3670
3671 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3672 {
3673 context->handleError(InvalidValue());
3674 return false;
3675 }
3676
3677 return true;
3678}
3679
3680bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3681{
3682 if (context->getClientMajorVersion() < 3)
3683 {
3684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3685 return false;
3686 }
3687
3688 return ValidateVertexAttribIndex(context, index);
3689}
3690
3691bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003692 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003693 GLsizei levels,
3694 GLenum internalformat,
3695 GLsizei width,
3696 GLsizei height)
3697{
3698 if (context->getClientMajorVersion() < 3)
3699 {
3700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3701 return false;
3702 }
3703
3704 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3705 1))
3706 {
3707 return false;
3708 }
3709
3710 return true;
3711}
3712
3713bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003714 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003715 GLsizei levels,
3716 GLenum internalformat,
3717 GLsizei width,
3718 GLsizei height,
3719 GLsizei depth)
3720{
3721 if (context->getClientMajorVersion() < 3)
3722 {
3723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3724 return false;
3725 }
3726
3727 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3728 depth))
3729 {
3730 return false;
3731 }
3732
3733 return true;
3734}
3735
Jamie Madill5b772312018-03-08 20:28:32 -05003736bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003737 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003738 GLenum pname,
3739 GLint64 *params)
3740{
3741 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3742}
3743
3744bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3745{
3746 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3747}
3748
3749bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3750{
3751 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3752}
3753
3754bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3755{
3756 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3757}
3758
3759bool ValidateSamplerParameterfv(Context *context,
3760 GLuint sampler,
3761 GLenum pname,
3762 const GLfloat *params)
3763{
3764 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3765}
3766
3767bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3768{
3769 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3770}
3771
3772bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3773{
3774 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3775}
3776
3777bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3778{
3779 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3780}
3781
3782bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3783{
3784 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3785}
3786
3787bool ValidateGetInternalformativ(Context *context,
3788 GLenum target,
3789 GLenum internalformat,
3790 GLenum pname,
3791 GLsizei bufSize,
3792 GLint *params)
3793{
3794 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3795 nullptr);
3796}
3797
Jamie Madillc29968b2016-01-20 11:17:23 -05003798} // namespace gl