blob: 0a0fd1dd5feb4ca76c1c23df39b8a8a7b3872012 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
Corentin Wallezf0e89be2017-11-08 14:00:32 -080069 TextureType type = texture->getType();
70 if (!ValidMipLevel(context, type, level))
Martin Radev137032d2017-07-13 10:11:12 +030071 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
Corentin Wallezf0e89be2017-11-08 14:00:32 -080076 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
Martin Radev137032d2017-07-13 10:11:12 +030077 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800140 TextureType target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800174 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
Geoff Langca271392017-04-05 12:30:00 -0400175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800201 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800218 TextureType texType = TextureTargetToType(target);
219
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 // Validate image size
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800221 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500223 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 }
226
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 // Verify zero border
228 if (border != 0)
229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
Jamie Madill6f38f822014-06-06 17:12:20 -0400234 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
235 std::numeric_limits<GLsizei>::max() - xoffset < width ||
236 std::numeric_limits<GLsizei>::max() - yoffset < height ||
237 std::numeric_limits<GLsizei>::max() - zoffset < depth)
238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500239 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400240 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400241 }
242
Geoff Langaae65a42014-05-26 12:43:44 -0400243 const gl::Caps &caps = context->getCaps();
244
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800245 switch (texType)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800247 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800248 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
249 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500251 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800252 return false;
253 }
254 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800256 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257 ASSERT(level == 0);
258 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
259 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
260 {
261 context->handleError(InvalidValue());
262 return false;
263 }
264 if (isCompressed)
265 {
266 context->handleError(InvalidEnum()
267 << "Rectangle texture cannot have a compressed format.");
268 return false;
269 }
270 break;
271
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800272 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800273 if (!isSubImage && width != height)
274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500275 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800276 return false;
277 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400278
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500281 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 return false;
283 }
284 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800286 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800287 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
288 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
289 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500291 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800292 return false;
293 }
294 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800296 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800297 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
298 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
299 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500301 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800302 return false;
303 }
304 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305
He Yunchaoced53ae2016-11-29 15:00:51 +0800306 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500307 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 }
310
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800311 gl::Texture *texture = context->getTargetTexture(texType);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 if (!texture)
313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 }
317
Geoff Lang69cce582015-09-17 13:20:36 -0400318 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
324 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400325 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400326 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500327 if (isSubImage && actualInternalFormat == GL_NONE)
328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500330 return false;
331 }
332
Geoff Langc4e93662017-05-01 10:45:59 -0400333 const gl::InternalFormat &actualFormatInfo = isSubImage
334 ? *texture->getFormat(target, level).info
335 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 if (isCompressed)
337 {
tmartino7c102692015-10-02 16:43:40 -0400338 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500340 context->handleError(
341 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400342 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 }
344
Geoff Lang966c9402017-04-18 12:38:27 -0400345 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 {
Geoff Lang966c9402017-04-18 12:38:27 -0400347 if (!ValidCompressedSubImageSize(
348 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
349 texture->getWidth(target, level), texture->getHeight(target, level)))
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400352 return false;
353 }
354
355 if (format != actualInternalFormat)
356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500357 context->handleError(InvalidOperation()
358 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400359 return false;
360 }
Geoff Lang86f81162017-10-30 15:10:45 -0400361
362 if (actualInternalFormat == GL_ETC1_RGB8_OES)
363 {
364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
365 return false;
366 }
Geoff Lang966c9402017-04-18 12:38:27 -0400367 }
368 else
369 {
370 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500372 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400373 return false;
374 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 }
376
Geoff Langeb66a6e2016-10-31 13:06:12 -0400377 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500379 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400380 return false;
381 }
382
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800383 if (texType == TextureType::_3D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388 }
389 else
390 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800391 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
392 type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 {
Geoff Lang5d601382014-07-22 15:14:06 -0400394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 }
397
398 // Validate sub image parameters
399 if (isSubImage)
400 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500401 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500403 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 }
406
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500409 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 }
412
413 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
414 std::numeric_limits<GLsizei>::max() - yoffset < height ||
415 std::numeric_limits<GLsizei>::max() - zoffset < depth)
416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420
Geoff Langa9be0dc2014-12-17 12:34:40 -0500421 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
422 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
423 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500425 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 }
Geoff Langfb052642017-10-24 13:42:09 -0400428
429 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400430 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400431 {
432 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
433 return false;
434 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 }
436
Geoff Langdbcced82017-06-06 15:55:54 -0400437 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800438 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
Geoff Langdbcced82017-06-06 15:55:54 -0400439 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400440 {
441 return false;
442 }
443
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400444 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400445 gl::Buffer *pixelUnpackBuffer =
446 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400447 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400448 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 // ...data is not evenly divisible into the number of bytes needed to store in memory a
450 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400451 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400452 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400453 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400454 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400455 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
456
Geoff Langff5b2d52016-09-07 11:32:23 -0400457 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500459 context->handleError(InvalidOperation()
460 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 return false;
462 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400463 }
464
Jamie Madill7a5f7382014-03-05 15:01:24 -0500465 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700466 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500468 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400469 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500470 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400471 }
472
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400473 return true;
474}
475
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500476bool ValidateES3TexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800477 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500478 GLint level,
479 GLenum internalformat,
480 bool isCompressed,
481 bool isSubImage,
482 GLint xoffset,
483 GLint yoffset,
484 GLint zoffset,
485 GLsizei width,
486 GLsizei height,
487 GLsizei depth,
488 GLint border,
489 GLenum format,
490 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400491 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400492 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500493{
494 if (!ValidTexture2DDestinationTarget(context, target))
495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500496 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500497 return false;
498 }
499
500 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
501 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400502 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500503}
504
505bool ValidateES3TexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800506 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500507 GLint level,
508 GLenum internalformat,
509 bool isCompressed,
510 bool isSubImage,
511 GLint xoffset,
512 GLint yoffset,
513 GLint zoffset,
514 GLsizei width,
515 GLsizei height,
516 GLsizei depth,
517 GLint border,
518 GLenum format,
519 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400520 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400521 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522{
523 if (!ValidTexture3DDestinationTarget(context, target))
524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500525 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526 return false;
527 }
528
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 if (IsETC2EACFormat(format) && target != TextureType::_2DArray)
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500530 {
531 // ES 3.1, Section 8.7, page 169.
532 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
533 return false;
534 }
535
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800536 return ValidateES3TexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
537 internalformat, isCompressed, isSubImage, xoffset,
538 yoffset, zoffset, width, height, depth, border, format,
539 type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540}
541
Geoff Lang5d601382014-07-22 15:14:06 -0400542struct EffectiveInternalFormatInfo
543{
Jamie Madill76648fe2016-10-05 17:01:41 -0400544 GLenum effectiveFormat;
545 GLenum destFormat;
546 GLuint minRedBits;
547 GLuint maxRedBits;
548 GLuint minGreenBits;
549 GLuint maxGreenBits;
550 GLuint minBlueBits;
551 GLuint maxBlueBits;
552 GLuint minAlphaBits;
553 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400554};
555
Jamie Madill76648fe2016-10-05 17:01:41 -0400556static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
557 GLenum targetFormat,
558 const EffectiveInternalFormatInfo *list,
559 size_t size,
560 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400561{
Jamie Madill76648fe2016-10-05 17:01:41 -0400562 for (size_t curFormat = 0; curFormat < size; ++curFormat)
563 {
564 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
565 if ((formatInfo.destFormat == targetFormat) &&
566 (formatInfo.minRedBits <= srcFormat.redBits &&
567 formatInfo.maxRedBits >= srcFormat.redBits) &&
568 (formatInfo.minGreenBits <= srcFormat.greenBits &&
569 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
570 (formatInfo.minBlueBits <= srcFormat.blueBits &&
571 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
572 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
573 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
574 {
575 *outEffectiveFormat = formatInfo.effectiveFormat;
576 return true;
577 }
578 }
Geoff Lang5d601382014-07-22 15:14:06 -0400579
Jamie Madill76648fe2016-10-05 17:01:41 -0400580 *outEffectiveFormat = GL_NONE;
581 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400582}
583
Jamie Madill76648fe2016-10-05 17:01:41 -0400584bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
585 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400586{
Jamie Madill76648fe2016-10-05 17:01:41 -0400587 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
588 // Effective internal format coresponding to destination internal format and linear source
589 // buffer component sizes.
590 // | Source channel min/max sizes |
591 // Effective Internal Format | N/A | R | G | B | A |
592 // clang-format off
593 constexpr EffectiveInternalFormatInfo list[] = {
594 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
595 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
596 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
597 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
598 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
599 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
600 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
601 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
602 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
603 };
604 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400605
Jamie Madill76648fe2016-10-05 17:01:41 -0400606 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
607}
Geoff Lang5d601382014-07-22 15:14:06 -0400608
Jamie Madill76648fe2016-10-05 17:01:41 -0400609bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
610 const InternalFormat &destFormat,
611 GLenum *outEffectiveFormat)
612{
613 constexpr GLuint umax = UINT_MAX;
614
615 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
616 // Effective internal format coresponding to destination internal format andlinear source buffer
617 // component sizes.
618 // | Source channel min/max sizes |
619 // Effective Internal Format | Dest Format | R | G | B | A |
620 // clang-format off
621 constexpr EffectiveInternalFormatInfo list[] = {
622 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
623 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
624 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
625 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
626 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
627 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
628 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
629 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
630 };
631 // clang-format on
632
633 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
634 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400635}
636
He Yunchaoced53ae2016-11-29 15:00:51 +0800637static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
638 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400639 GLenum *outEffectiveFormat)
640{
Geoff Langca271392017-04-05 12:30:00 -0400641 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400642 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400643 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400644 }
645 else
646 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400647 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400648 }
Geoff Lang5d601382014-07-22 15:14:06 -0400649}
650
Corentin Wallez76287682016-04-25 09:23:38 -0400651static bool EqualOrFirstZero(GLuint first, GLuint second)
652{
653 return first == 0 || first == second;
654}
655
Geoff Langca271392017-04-05 12:30:00 -0400656static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
657 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400658 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400659{
Jamie Madill21b786b2016-11-01 17:41:31 -0400660 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400661 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400662 return false;
663 }
Geoff Lang5d601382014-07-22 15:14:06 -0400664
Jamie Madill21b786b2016-11-01 17:41:31 -0400665 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
666 // must both be signed, unsigned, or fixed point and both source and destinations
667 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
668 // conversion between fixed and floating point.
669
670 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
671 (framebufferFormatInfo.colorEncoding == GL_SRGB))
672 {
673 return false;
674 }
675
676 if (((textureFormatInfo.componentType == GL_INT) !=
677 (framebufferFormatInfo.componentType == GL_INT)) ||
678 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
679 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
680 {
681 return false;
682 }
683
684 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
685 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
686 textureFormatInfo.componentType == GL_FLOAT) &&
687 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
688 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
689 framebufferFormatInfo.componentType == GL_FLOAT))
690 {
691 return false;
692 }
693
694 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
695 // The effective internal format of the source buffer is determined with the following rules
696 // applied in order:
697 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
698 // format then the effective internal format is the source buffer's sized internal format.
699 // * If the source buffer is a texture that was created with an unsized base internal format,
700 // then the effective internal format is the source image array's effective internal
701 // format, as specified by table 3.12, which is determined from the <format> and <type>
702 // that were used when the source image array was specified by TexImage*.
703 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
704 // where Destination Internal Format matches internalformat and where the [source channel
705 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
706 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
707 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800708 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400709 if (readBufferHandle != 0)
710 {
711 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
712 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400713 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400714 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400715 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400716 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 else
Geoff Lang5d601382014-07-22 15:14:06 -0400718 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 // Renderbuffers cannot be created with an unsized internal format, so this must be an
720 // unsized-format texture. We can use the same table we use when creating textures to
721 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400722 sourceEffectiveFormat =
723 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400724 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400725 }
726 else
727 {
728 // The effective internal format must be derived from the source framebuffer's channel
729 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
730 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400731 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400732 GLenum effectiveFormat;
733 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
734 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400735 {
Geoff Langca271392017-04-05 12:30:00 -0400736 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400737 }
738 else
739 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400740 return false;
741 }
742 }
743 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
744 {
745 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400746 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400747 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
748 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
749 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
750 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
751 {
Geoff Langca271392017-04-05 12:30:00 -0400752 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400753 }
754 else
755 {
756 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400757 }
758 }
759 else
760 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400761 UNREACHABLE();
762 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400763 }
Geoff Lang5d601382014-07-22 15:14:06 -0400764 }
765
Geoff Langca271392017-04-05 12:30:00 -0400766 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400767 {
768 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
769 // sized, component sizes of the source and destination formats must exactly match if the
770 // destination format exists.
771 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
772 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
773 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
774 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
775 {
776 return false;
777 }
778 }
779
780 return true; // A conversion function exists, and no rule in the specification has precluded
781 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400782}
783
Jamie Madill5b772312018-03-08 20:28:32 -0500784bool ValidateES3CopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800785 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786 GLint level,
787 GLenum internalformat,
788 bool isSubImage,
789 GLint xoffset,
790 GLint yoffset,
791 GLint zoffset,
792 GLint x,
793 GLint y,
794 GLsizei width,
795 GLsizei height,
796 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400798 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400799 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 xoffset, yoffset, zoffset, x, y, width, height, border,
801 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400802 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400803 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400805 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806
Jamie Madill51f40ec2016-06-15 14:06:00 -0400807 const auto &state = context->getGLState();
808 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
809 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400810
Jamie Madill427064d2018-04-13 16:20:34 -0400811 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400814 }
815
Jamie Madille98b1b52018-03-08 09:47:23 -0500816 if (readFramebufferID != 0 && !ValidateFramebufferNotMultisampled(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400817 {
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400819 }
820
Jamie Madill0c8abca2016-07-22 20:21:26 -0400821 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822
Yunchao He096a6c82018-02-27 23:48:21 +0800823 // According to ES 3.x spec, if the internalformat of the texture
824 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
825 if (textureFormat.info->internalFormat == GL_RGB9_E5)
826 {
827 context->handleError(InvalidOperation());
828 return false;
829 }
830
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 if (isSubImage)
832 {
Geoff Langca271392017-04-05 12:30:00 -0400833 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500834 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500836 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 }
839 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400840 else
841 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400842 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400843 const InternalFormat &framebufferFormat = *source->getFormat().info;
844 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400845 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500847 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400849 }
850 }
851
Geoff Lang784a8fd2013-09-24 12:33:16 -0400852 // If width or height is zero, it is a no-op. Return false without setting an error.
853 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854}
855
Jamie Madill5b772312018-03-08 20:28:32 -0500856bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800857 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500858 GLint level,
859 GLenum internalformat,
860 bool isSubImage,
861 GLint xoffset,
862 GLint yoffset,
863 GLint zoffset,
864 GLint x,
865 GLint y,
866 GLsizei width,
867 GLsizei height,
868 GLint border)
869{
870 if (!ValidTexture2DDestinationTarget(context, target))
871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500872 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500873 return false;
874 }
875
876 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
877 xoffset, yoffset, zoffset, x, y, width, height,
878 border);
879}
880
Jamie Madill5b772312018-03-08 20:28:32 -0500881bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800882 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 GLint level,
884 GLenum internalformat,
885 bool isSubImage,
886 GLint xoffset,
887 GLint yoffset,
888 GLint zoffset,
889 GLint x,
890 GLint y,
891 GLsizei width,
892 GLsizei height,
893 GLint border)
894{
895 if (!ValidTexture3DDestinationTarget(context, target))
896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500897 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898 return false;
899 }
900
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
902 internalformat, isSubImage, xoffset, yoffset,
903 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500904}
905
906bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800907 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500908 GLsizei levels,
909 GLenum internalformat,
910 GLsizei width,
911 GLsizei height,
912 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913{
914 if (width < 1 || height < 1 || depth < 1 || levels < 1)
915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 }
919
Geoff Langb92c1332015-09-04 12:54:55 -0400920 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800921 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400922 {
923 maxDim = std::max(maxDim, depth);
924 }
925
926 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500928 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 }
931
Geoff Langaae65a42014-05-26 12:43:44 -0400932 const gl::Caps &caps = context->getCaps();
933
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 switch (target)
935 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800936 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 {
Geoff Langaae65a42014-05-26 12:43:44 -0400938 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
939 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 }
944 }
945 break;
946
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800947 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400948 {
949 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
950 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
951 {
952 context->handleError(InvalidValue());
953 return false;
954 }
955 }
956 break;
957
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800958 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 if (width != height)
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965
Geoff Langaae65a42014-05-26 12:43:44 -0400966 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400969 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 }
971 }
972 break;
973
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800974 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 {
Geoff Langaae65a42014-05-26 12:43:44 -0400976 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
977 static_cast<GLuint>(height) > caps.max3DTextureSize ||
978 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500980 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400981 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 }
983 }
984 break;
985
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800986 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400987 {
Geoff Langaae65a42014-05-26 12:43:44 -0400988 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
989 static_cast<GLuint>(height) > caps.max2DTextureSize ||
990 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500992 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400993 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400994 }
995 }
996 break;
997
He Yunchaoced53ae2016-11-29 15:00:51 +0800998 default:
999 UNREACHABLE();
1000 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001001 }
1002
Geoff Lang691e58c2014-12-19 17:03:25 -05001003 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 if (!texture || texture->id() == 0)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Geoff Lang69cce582015-09-17 13:20:36 -04001010 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 }
1015
Geoff Langca271392017-04-05 12:30:00 -04001016 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001017 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022
Geoff Langca271392017-04-05 12:30:00 -04001023 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001025 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001026 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 }
1028
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001029 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001030 {
1031 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1032 return false;
1033 }
1034
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 return true;
1036}
1037
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001038bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001039 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001040 GLsizei levels,
1041 GLenum internalformat,
1042 GLsizei width,
1043 GLsizei height,
1044 GLsizei depth)
1045{
1046 if (!ValidTexture2DTarget(context, target))
1047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001049 return false;
1050 }
1051
1052 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1053 height, depth);
1054}
1055
1056bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001057 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001058 GLsizei levels,
1059 GLenum internalformat,
1060 GLsizei width,
1061 GLsizei height,
1062 GLsizei depth)
1063{
1064 if (!ValidTexture3DTarget(context, target))
1065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001066 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001067 return false;
1068 }
1069
1070 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1071 height, depth);
1072}
1073
Corentin Wallezad3ae902018-03-09 13:40:42 -05001074bool ValidateBeginQuery(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001075{
Martin Radev1be913c2016-07-11 17:59:16 +03001076 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001077 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001079 return false;
1080 }
1081
1082 return ValidateBeginQueryBase(context, target, id);
1083}
1084
Corentin Wallezad3ae902018-03-09 13:40:42 -05001085bool ValidateEndQuery(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086{
Martin Radev1be913c2016-07-11 17:59:16 +03001087 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001088 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001090 return false;
1091 }
1092
1093 return ValidateEndQueryBase(context, target);
1094}
1095
Corentin Wallezad3ae902018-03-09 13:40:42 -05001096bool ValidateGetQueryiv(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097{
Martin Radev1be913c2016-07-11 17:59:16 +03001098 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001099 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001101 return false;
1102 }
1103
Geoff Lang2186c382016-10-14 10:54:54 -04001104 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001105}
1106
1107bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1108{
Martin Radev1be913c2016-07-11 17:59:16 +03001109 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001110 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001112 return false;
1113 }
1114
Geoff Lang2186c382016-10-14 10:54:54 -04001115 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001116}
1117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118bool ValidateFramebufferTextureLayer(Context *context,
1119 GLenum target,
1120 GLenum attachment,
1121 GLuint texture,
1122 GLint level,
1123 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001124{
Martin Radev1be913c2016-07-11 17:59:16 +03001125 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001126 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001128 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001129 }
1130
Jamie Madill55ec3b12014-07-03 10:38:57 -04001131 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1132 {
1133 return false;
1134 }
1135
1136 const gl::Caps &caps = context->getCaps();
1137 if (texture != 0)
1138 {
Geoff Lang23e02842017-10-17 13:24:09 -04001139 if (layer < 0)
1140 {
1141 context->handleError(InvalidValue());
1142 return false;
1143 }
1144
Jamie Madill55ec3b12014-07-03 10:38:57 -04001145 gl::Texture *tex = context->getTexture(texture);
1146 ASSERT(tex);
1147
Corentin Wallez99d492c2018-02-27 15:17:10 -05001148 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001149 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001150 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001151 {
1152 if (level > gl::log2(caps.max2DTextureSize))
1153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001156 }
1157
1158 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001160 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001161 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001162 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001163 }
1164 break;
1165
Corentin Wallez99d492c2018-02-27 15:17:10 -05001166 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001167 {
1168 if (level > gl::log2(caps.max3DTextureSize))
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001172 }
1173
1174 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001176 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001178 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001179 }
1180 break;
1181
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001183 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001185 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001186
Corentin Wallez99d492c2018-02-27 15:17:10 -05001187 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001188 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001190 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001191 return false;
1192 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001193 }
1194
1195 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001196}
1197
He Yunchaoced53ae2016-11-29 15:00:51 +08001198bool ValidateInvalidateFramebuffer(Context *context,
1199 GLenum target,
1200 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001201 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202{
Martin Radev1be913c2016-07-11 17:59:16 +03001203 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001206 return false;
1207 }
1208
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001209 bool defaultFramebuffer = false;
1210
1211 switch (target)
1212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 case GL_DRAW_FRAMEBUFFER:
1214 case GL_FRAMEBUFFER:
1215 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1216 break;
1217 case GL_READ_FRAMEBUFFER:
1218 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1219 break;
1220 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1226 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227}
1228
Jamie Madill3ef140a2017-08-26 23:11:21 -04001229bool ValidateInvalidateSubFramebuffer(Context *context,
1230 GLenum target,
1231 GLsizei numAttachments,
1232 const GLenum *attachments,
1233 GLint x,
1234 GLint y,
1235 GLsizei width,
1236 GLsizei height)
1237{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001238 if (width < 0 || height < 0)
1239 {
1240 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1241 return false;
1242 }
1243
Jamie Madill3ef140a2017-08-26 23:11:21 -04001244 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1245}
1246
Jamie Madill5b772312018-03-08 20:28:32 -05001247bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001248{
Martin Radev1be913c2016-07-11 17:59:16 +03001249 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001253 }
1254
Jamie Madill427064d2018-04-13 16:20:34 -04001255 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001256 {
Geoff Langb1196682014-07-23 13:47:29 -04001257 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001258 }
1259
1260 return true;
1261}
1262
Olli Etuaho71dfb362016-03-10 14:04:27 +02001263bool ValidateDrawRangeElements(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001264 PrimitiveMode mode,
Olli Etuaho71dfb362016-03-10 14:04:27 +02001265 GLuint start,
1266 GLuint end,
1267 GLsizei count,
1268 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001269 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001270{
Martin Radev1be913c2016-07-11 17:59:16 +03001271 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001272 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001274 return false;
1275 }
1276
1277 if (end < start)
1278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001280 return false;
1281 }
1282
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001283 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001284 {
1285 return false;
1286 }
1287
Jamie Madill9fdaa492018-02-16 10:52:11 -05001288 // Skip range checks for no-op calls.
1289 if (count <= 0)
1290 {
1291 return true;
1292 }
1293
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001294 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04001295 const DrawCallParams &params = context->getParams<DrawCallParams>();
1296 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001297
Jamie Madill6f5444d2018-03-14 10:08:11 -04001298 const IndexRange &indexRange = params.getIndexRange();
1299
1300 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001301 {
1302 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001304 return false;
1305 }
1306 return true;
1307}
1308
He Yunchaoced53ae2016-11-29 15:00:51 +08001309bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001310{
Martin Radev1be913c2016-07-11 17:59:16 +03001311 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001312 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001315 }
1316
Jamie Madill78f41802014-08-25 15:47:55 -04001317 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001318}
1319
Jamie Madillb885e572015-02-03 16:16:04 -05001320bool ValidateReadBuffer(Context *context, GLenum src)
1321{
Martin Radev1be913c2016-07-11 17:59:16 +03001322 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001323 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001325 return false;
1326 }
1327
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001328 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001329
1330 if (readFBO == nullptr)
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001333 return false;
1334 }
1335
1336 if (src == GL_NONE)
1337 {
1338 return true;
1339 }
1340
Olli Etuaho84c9f592016-03-09 14:37:25 +02001341 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001344 return false;
1345 }
1346
1347 if (readFBO->id() == 0)
1348 {
1349 if (src != GL_BACK)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(
1352 InvalidOperation()
1353 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001354 return false;
1355 }
1356 }
1357 else
1358 {
1359 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1360
1361 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001364 return false;
1365 }
1366 }
1367
1368 return true;
1369}
1370
Jamie Madill86af3d22015-07-21 15:14:07 -04001371bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001372 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001373 GLint level,
1374 GLenum internalformat,
1375 GLsizei width,
1376 GLsizei height,
1377 GLsizei depth,
1378 GLint border,
1379 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001380 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001381{
Martin Radev1be913c2016-07-11 17:59:16 +03001382 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001384 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001385 return false;
1386 }
1387
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001388 if (!ValidTextureTarget(context, target))
1389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001391 return false;
1392 }
1393
Jamie Madille2e406c2016-06-02 13:04:10 -04001394 // Validate image size
1395 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001398 return false;
1399 }
1400
Geoff Langca271392017-04-05 12:30:00 -04001401 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001402 if (!formatInfo.compressed)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001405 return false;
1406 }
1407
Jamie Madillca2ff382018-07-11 09:01:17 -04001408 GLuint blockSize = 0;
1409 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001412 return false;
1413 }
Jamie Madillca2ff382018-07-11 09:01:17 -04001414
1415 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill86af3d22015-07-21 15:14:07 -04001416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001418 return false;
1419 }
1420
1421 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001422 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001424 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001425 return false;
1426 }
1427
1428 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001429 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001430 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1431 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001432 {
1433 return false;
1434 }
1435
1436 return true;
1437}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001438
Corentin Wallezb2931602017-04-11 15:58:57 -04001439bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001440 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001441 GLint level,
1442 GLenum internalformat,
1443 GLsizei width,
1444 GLsizei height,
1445 GLsizei depth,
1446 GLint border,
1447 GLsizei imageSize,
1448 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001449 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001450{
1451 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1452 {
1453 return false;
1454 }
1455
1456 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1457 depth, border, imageSize, data);
1458}
1459
Austin Kinrossbc781f32015-10-26 09:27:38 -07001460bool ValidateBindVertexArray(Context *context, GLuint array)
1461{
Martin Radev1be913c2016-07-11 17:59:16 +03001462 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001463 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001465 return false;
1466 }
1467
1468 return ValidateBindVertexArrayBase(context, array);
1469}
1470
Jamie Madilld7576732017-08-26 18:49:50 -04001471bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001472{
Martin Radev1be913c2016-07-11 17:59:16 +03001473 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001474 {
Jamie Madilld7576732017-08-26 18:49:50 -04001475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001476 return false;
1477 }
1478
1479 return true;
1480}
Geoff Langc5629752015-12-07 16:29:04 -05001481
Jiajia Qin6eafb042016-12-27 17:04:07 +08001482static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001483 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001484 GLuint index,
1485 GLuint buffer,
1486 GLintptr offset,
1487 GLsizeiptr size)
1488{
1489 if (context->getClientMajorVersion() < 3)
1490 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001492 return false;
1493 }
1494
1495 if (buffer != 0 && offset < 0)
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001498 return false;
1499 }
1500
1501 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1502 !context->isBufferGenerated(buffer))
1503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001504 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001505 return false;
1506 }
1507
1508 const Caps &caps = context->getCaps();
1509 switch (target)
1510 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001511 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001512 {
1513 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 context->handleError(InvalidValue() << "index is greater than or equal to the "
1516 "number of TRANSFORM_FEEDBACK_BUFFER "
1517 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001518 return false;
1519 }
1520 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001522 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001523 return false;
1524 }
1525
1526 TransformFeedback *curTransformFeedback =
1527 context->getGLState().getCurrentTransformFeedback();
1528 if (curTransformFeedback && curTransformFeedback->isActive())
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidOperation()
1531 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1532 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001533 return false;
1534 }
1535 break;
1536 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001537 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001538 {
1539 if (index >= caps.maxUniformBufferBindings)
1540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidValue() << "index is greater than or equal to the "
1542 "number of UNIFORM_BUFFER indexed "
1543 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001544 return false;
1545 }
1546
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001547 ASSERT(caps.uniformBufferOffsetAlignment);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001548 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1549 {
1550 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 InvalidValue()
1552 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001553 return false;
1554 }
1555 break;
1556 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001557 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001558 {
1559 if (context->getClientVersion() < ES_3_1)
1560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidEnum()
1562 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001563 return false;
1564 }
1565 if (index >= caps.maxAtomicCounterBufferBindings)
1566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001567 context->handleError(InvalidValue() << "index is greater than or equal to the "
1568 "number of ATOMIC_COUNTER_BUFFER "
1569 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001570 return false;
1571 }
1572 if (buffer != 0 && (offset % 4) != 0)
1573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001574 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001575 return false;
1576 }
1577 break;
1578 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001579 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001580 {
1581 if (context->getClientVersion() < ES_3_1)
1582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001583 context->handleError(InvalidEnum()
1584 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001585 return false;
1586 }
1587 if (index >= caps.maxShaderStorageBufferBindings)
1588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001589 context->handleError(InvalidValue() << "index is greater than or equal to the "
1590 "number of SHADER_STORAGE_BUFFER "
1591 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001592 return false;
1593 }
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001594 ASSERT(caps.shaderStorageBufferOffsetAlignment);
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001595 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidValue() << "offset must be multiple of value of "
1598 "SHADER_STORAGE_BUFFER_OFFSET_"
1599 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001600 return false;
1601 }
1602 break;
1603 }
1604 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001605 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001606 return false;
1607 }
1608
1609 return true;
1610}
1611
Corentin Wallez336129f2017-10-17 15:55:40 -04001612bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001613{
1614 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1615}
1616
1617bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001618 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001619 GLuint index,
1620 GLuint buffer,
1621 GLintptr offset,
1622 GLsizeiptr size)
1623{
1624 if (buffer != 0 && size <= 0)
1625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001626 context->handleError(InvalidValue()
1627 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001628 return false;
1629 }
1630 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1631}
1632
Geoff Langc5629752015-12-07 16:29:04 -05001633bool ValidateProgramBinary(Context *context,
1634 GLuint program,
1635 GLenum binaryFormat,
1636 const void *binary,
1637 GLint length)
1638{
Martin Radev1be913c2016-07-11 17:59:16 +03001639 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001640 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001641 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001642 return false;
1643 }
1644
1645 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1646}
1647
1648bool ValidateGetProgramBinary(Context *context,
1649 GLuint program,
1650 GLsizei bufSize,
1651 GLsizei *length,
1652 GLenum *binaryFormat,
1653 void *binary)
1654{
Martin Radev1be913c2016-07-11 17:59:16 +03001655 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001656 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001658 return false;
1659 }
1660
1661 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1662}
1663
Olli Etuahof0fee072016-03-30 15:11:58 +03001664bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001665{
Martin Radev1be913c2016-07-11 17:59:16 +03001666 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001669 return false;
1670 }
1671
1672 if (GetValidProgram(context, program) == nullptr)
1673 {
1674 return false;
1675 }
1676
1677 switch (pname)
1678 {
1679 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001680 if (value != GL_FALSE && value != GL_TRUE)
1681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001682 context->handleError(InvalidValue()
1683 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001684 return false;
1685 }
Geoff Langc5629752015-12-07 16:29:04 -05001686 break;
1687
Yunchao He61afff12017-03-14 15:34:03 +08001688 case GL_PROGRAM_SEPARABLE:
1689 if (context->getClientVersion() < ES_3_1)
1690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidEnum()
1692 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001693 return false;
1694 }
1695
1696 if (value != GL_FALSE && value != GL_TRUE)
1697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001698 context->handleError(InvalidValue()
1699 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001700 return false;
1701 }
1702 break;
1703
Geoff Langc5629752015-12-07 16:29:04 -05001704 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidEnum()
1706 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001707 return false;
1708 }
1709
1710 return true;
1711}
Jamie Madillc29968b2016-01-20 11:17:23 -05001712
1713bool ValidateBlitFramebuffer(Context *context,
1714 GLint srcX0,
1715 GLint srcY0,
1716 GLint srcX1,
1717 GLint srcY1,
1718 GLint dstX0,
1719 GLint dstY0,
1720 GLint dstX1,
1721 GLint dstY1,
1722 GLbitfield mask,
1723 GLenum filter)
1724{
Martin Radev1be913c2016-07-11 17:59:16 +03001725 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001728 return false;
1729 }
1730
1731 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1732 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001733}
Jamie Madillc29968b2016-01-20 11:17:23 -05001734
Jamie Madill5b772312018-03-08 20:28:32 -05001735bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001736{
1737 switch (buffer)
1738 {
1739 case GL_COLOR:
1740 if (drawbuffer < 0 ||
1741 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001744 return false;
1745 }
Geoff Lang76e65652017-03-27 14:58:02 -04001746 if (context->getExtensions().webglCompatibility)
1747 {
1748 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001749 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001750 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1751 {
1752 return false;
1753 }
1754 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001755 break;
1756
1757 case GL_STENCIL:
1758 if (drawbuffer != 0)
1759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
1763 break;
1764
1765 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001767 return false;
1768 }
1769
1770 return ValidateClearBuffer(context);
1771}
1772
Jamie Madill5b772312018-03-08 20:28:32 -05001773bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001774{
1775 switch (buffer)
1776 {
1777 case GL_COLOR:
1778 if (drawbuffer < 0 ||
1779 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001781 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001782 return false;
1783 }
Geoff Lang76e65652017-03-27 14:58:02 -04001784 if (context->getExtensions().webglCompatibility)
1785 {
1786 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001787 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001788 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1789 {
1790 return false;
1791 }
1792 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001793 break;
1794
1795 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001796 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001797 return false;
1798 }
1799
1800 return ValidateClearBuffer(context);
1801}
1802
Jamie Madill5b772312018-03-08 20:28:32 -05001803bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001804{
1805 switch (buffer)
1806 {
1807 case GL_COLOR:
1808 if (drawbuffer < 0 ||
1809 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001811 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
Geoff Lang76e65652017-03-27 14:58:02 -04001814 if (context->getExtensions().webglCompatibility)
1815 {
1816 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1817 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001818 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001819 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1820 {
1821 return false;
1822 }
1823 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 break;
1825
1826 case GL_DEPTH:
1827 if (drawbuffer != 0)
1828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001829 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832 break;
1833
1834 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001836 return false;
1837 }
1838
1839 return ValidateClearBuffer(context);
1840}
1841
Jamie Madill5b772312018-03-08 20:28:32 -05001842bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001843 GLenum buffer,
1844 GLint drawbuffer,
1845 GLfloat depth,
1846 GLint stencil)
1847{
1848 switch (buffer)
1849 {
1850 case GL_DEPTH_STENCIL:
1851 if (drawbuffer != 0)
1852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001853 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001854 return false;
1855 }
1856 break;
1857
1858 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001859 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001860 return false;
1861 }
1862
1863 return ValidateClearBuffer(context);
1864}
1865
Jamie Madill5b772312018-03-08 20:28:32 -05001866bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001867{
Martin Radev1be913c2016-07-11 17:59:16 +03001868 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001871 return false;
1872 }
1873
1874 return ValidateDrawBuffersBase(context, n, bufs);
1875}
1876
1877bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001878 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001879 GLint level,
1880 GLint xoffset,
1881 GLint yoffset,
1882 GLint zoffset,
1883 GLint x,
1884 GLint y,
1885 GLsizei width,
1886 GLsizei height)
1887{
Martin Radev1be913c2016-07-11 17:59:16 +03001888 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001889 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001891 return false;
1892 }
1893
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001894 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1895 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001896}
1897
Jamie Madill73a84962016-02-12 09:27:23 -05001898bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001899 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001900 GLint level,
1901 GLint internalformat,
1902 GLsizei width,
1903 GLsizei height,
1904 GLsizei depth,
1905 GLint border,
1906 GLenum format,
1907 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001908 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001909{
Martin Radev1be913c2016-07-11 17:59:16 +03001910 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001911 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001913 return false;
1914 }
1915
1916 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001917 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001918 pixels);
1919}
1920
Geoff Langc52f6f12016-10-14 10:18:00 -04001921bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001922 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001923 GLint level,
1924 GLint internalformat,
1925 GLsizei width,
1926 GLsizei height,
1927 GLsizei depth,
1928 GLint border,
1929 GLenum format,
1930 GLenum type,
1931 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001932 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001933{
1934 if (context->getClientMajorVersion() < 3)
1935 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001937 return false;
1938 }
1939
1940 if (!ValidateRobustEntryPoint(context, bufSize))
1941 {
1942 return false;
1943 }
1944
1945 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1946 0, 0, width, height, depth, border, format, type,
1947 bufSize, pixels);
1948}
1949
Jamie Madill73a84962016-02-12 09:27:23 -05001950bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001951 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001952 GLint level,
1953 GLint xoffset,
1954 GLint yoffset,
1955 GLint zoffset,
1956 GLsizei width,
1957 GLsizei height,
1958 GLsizei depth,
1959 GLenum format,
1960 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001961 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001962{
Martin Radev1be913c2016-07-11 17:59:16 +03001963 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001964 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001966 return false;
1967 }
1968
1969 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1970 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001971 -1, pixels);
1972}
1973
1974bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001975 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001976 GLint level,
1977 GLint xoffset,
1978 GLint yoffset,
1979 GLint zoffset,
1980 GLsizei width,
1981 GLsizei height,
1982 GLsizei depth,
1983 GLenum format,
1984 GLenum type,
1985 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001986 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001987{
1988 if (context->getClientMajorVersion() < 3)
1989 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001991 return false;
1992 }
1993
1994 if (!ValidateRobustEntryPoint(context, bufSize))
1995 {
1996 return false;
1997 }
1998
1999 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2000 yoffset, zoffset, width, height, depth, 0, format, type,
2001 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002002}
2003
2004bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002005 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002006 GLint level,
2007 GLint xoffset,
2008 GLint yoffset,
2009 GLint zoffset,
2010 GLsizei width,
2011 GLsizei height,
2012 GLsizei depth,
2013 GLenum format,
2014 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002015 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002016{
Martin Radev1be913c2016-07-11 17:59:16 +03002017 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002018 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002020 return false;
2021 }
2022
Geoff Langca271392017-04-05 12:30:00 -04002023 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002024 if (!formatInfo.compressed)
2025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002026 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002027 return false;
2028 }
2029
Jamie Madillca2ff382018-07-11 09:01:17 -04002030 GLuint blockSize = 0;
2031 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002032 {
Jamie Madillca2ff382018-07-11 09:01:17 -04002033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madille2e406c2016-06-02 13:04:10 -04002034 return false;
2035 }
Jamie Madillca2ff382018-07-11 09:01:17 -04002036
2037 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill73a84962016-02-12 09:27:23 -05002038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002039 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002040 return false;
2041 }
2042
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002043 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2044 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2045 -1, data))
2046 {
2047 return false;
2048 }
2049
Jamie Madill73a84962016-02-12 09:27:23 -05002050 if (!data)
2051 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002052 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002053 return false;
2054 }
2055
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002056 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002057}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002058
Corentin Wallezb2931602017-04-11 15:58:57 -04002059bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002060 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002061 GLint level,
2062 GLint xoffset,
2063 GLint yoffset,
2064 GLint zoffset,
2065 GLsizei width,
2066 GLsizei height,
2067 GLsizei depth,
2068 GLenum format,
2069 GLsizei imageSize,
2070 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002071 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002072{
2073 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2074 {
2075 return false;
2076 }
2077
2078 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2079 height, depth, format, imageSize, data);
2080}
Jamie Madill73a84962016-02-12 09:27:23 -05002081
Olli Etuaho41997e72016-03-10 13:38:39 +02002082bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2083{
2084 return ValidateGenOrDeleteES3(context, n);
2085}
2086
2087bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2088{
2089 return ValidateGenOrDeleteES3(context, n);
2090}
2091
2092bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2093{
2094 return ValidateGenOrDeleteCountES3(context, count);
2095}
2096
2097bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2098{
2099 return ValidateGenOrDeleteCountES3(context, count);
2100}
2101
2102bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2103{
2104 return ValidateGenOrDeleteES3(context, n);
2105}
2106
2107bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2108{
2109 if (!ValidateGenOrDeleteES3(context, n))
2110 {
2111 return false;
2112 }
2113 for (GLint i = 0; i < n; ++i)
2114 {
2115 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2116 if (transformFeedback != nullptr && transformFeedback->isActive())
2117 {
2118 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002119 context->handleError(InvalidOperation()
2120 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002121 return false;
2122 }
2123 }
2124 return true;
2125}
2126
2127bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2128{
2129 return ValidateGenOrDeleteES3(context, n);
2130}
2131
2132bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2133{
2134 return ValidateGenOrDeleteES3(context, n);
2135}
2136
Jamie Madill493f9572018-05-24 19:52:15 -04002137bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMode)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002138{
Martin Radev1be913c2016-07-11 17:59:16 +03002139 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002140 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002142 return false;
2143 }
2144 switch (primitiveMode)
2145 {
Jamie Madill493f9572018-05-24 19:52:15 -04002146 case PrimitiveMode::Triangles:
2147 case PrimitiveMode::Lines:
2148 case PrimitiveMode::Points:
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002149 break;
2150
2151 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002152 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002153 return false;
2154 }
2155
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002156 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002157 ASSERT(transformFeedback != nullptr);
2158
2159 if (transformFeedback->isActive())
2160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002161 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002162 return false;
2163 }
Geoff Lang79f71042017-08-14 16:43:43 -04002164
2165 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2166 {
2167 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2168 if (buffer.get() && buffer->isMapped())
2169 {
2170 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2171 return false;
2172 }
2173 }
2174
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002175 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002176
2177 if (!program)
2178 {
2179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2180 return false;
2181 }
2182
2183 if (program->getTransformFeedbackVaryingCount() == 0)
2184 {
2185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2186 return false;
2187 }
2188
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002189 return true;
2190}
2191
Corentin Wallez336129f2017-10-17 15:55:40 -04002192bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002193{
Geoff Lang496c02d2016-10-20 11:38:11 -07002194 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2195}
2196
2197bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002198 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002199 GLenum pname,
2200 GLsizei bufSize,
2201 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002202 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002203{
2204 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002205 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002206 return false;
2207 }
2208
Brandon Jonesd1049182018-03-28 10:02:20 -07002209 GLsizei numParams = 0;
2210
2211 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002212 {
2213 return false;
2214 }
2215
Brandon Jonesd1049182018-03-28 10:02:20 -07002216 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002217 {
2218 return false;
2219 }
2220
Brandon Jonesd1049182018-03-28 10:02:20 -07002221 SetRobustLengthParam(length, numParams);
2222
Geoff Lang496c02d2016-10-20 11:38:11 -07002223 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002224}
2225
Corentin Wallez336129f2017-10-17 15:55:40 -04002226bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002227{
Martin Radev1be913c2016-07-11 17:59:16 +03002228 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002229 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002231 return false;
2232 }
2233
2234 return ValidateUnmapBufferBase(context, target);
2235}
2236
2237bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002238 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002239 GLintptr offset,
2240 GLsizeiptr length,
2241 GLbitfield access)
2242{
Martin Radev1be913c2016-07-11 17:59:16 +03002243 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002244 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002246 return false;
2247 }
2248
2249 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2250}
2251
2252bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002253 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002254 GLintptr offset,
2255 GLsizeiptr length)
2256{
Martin Radev1be913c2016-07-11 17:59:16 +03002257 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002258 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002260 return false;
2261 }
2262
2263 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2264}
2265
Jamie Madill5b772312018-03-08 20:28:32 -05002266bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002267{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002268 if (length)
2269 {
2270 *length = 0;
2271 }
2272
Martin Radev66fb8202016-07-28 11:45:20 +03002273 GLenum nativeType;
2274 unsigned int numParams;
2275 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002277 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002278 return false;
2279 }
2280
2281 const Caps &caps = context->getCaps();
2282 switch (pname)
2283 {
2284 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2285 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2286 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2287 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002289 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002290 return false;
2291 }
2292 break;
2293
2294 case GL_UNIFORM_BUFFER_START:
2295 case GL_UNIFORM_BUFFER_SIZE:
2296 case GL_UNIFORM_BUFFER_BINDING:
2297 if (index >= caps.maxUniformBufferBindings)
2298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002299 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002300 return false;
2301 }
2302 break;
Shao80957d92017-02-20 21:25:59 +08002303
Martin Radev66fb8202016-07-28 11:45:20 +03002304 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2305 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2306 if (index >= 3u)
2307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002308 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002309 return false;
2310 }
2311 break;
Shao80957d92017-02-20 21:25:59 +08002312
Jiajia Qin6eafb042016-12-27 17:04:07 +08002313 case GL_ATOMIC_COUNTER_BUFFER_START:
2314 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2315 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2316 if (context->getClientVersion() < ES_3_1)
2317 {
2318 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002319 InvalidEnum()
2320 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002321 return false;
2322 }
2323 if (index >= caps.maxAtomicCounterBufferBindings)
2324 {
2325 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002326 InvalidValue()
2327 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002328 return false;
2329 }
2330 break;
Shao80957d92017-02-20 21:25:59 +08002331
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002332 case GL_SHADER_STORAGE_BUFFER_START:
2333 case GL_SHADER_STORAGE_BUFFER_SIZE:
2334 case GL_SHADER_STORAGE_BUFFER_BINDING:
2335 if (context->getClientVersion() < ES_3_1)
2336 {
2337 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002338 InvalidEnum()
2339 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002340 return false;
2341 }
2342 if (index >= caps.maxShaderStorageBufferBindings)
2343 {
2344 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 InvalidValue()
2346 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002347 return false;
2348 }
2349 break;
2350
Shao80957d92017-02-20 21:25:59 +08002351 case GL_VERTEX_BINDING_BUFFER:
2352 case GL_VERTEX_BINDING_DIVISOR:
2353 case GL_VERTEX_BINDING_OFFSET:
2354 case GL_VERTEX_BINDING_STRIDE:
2355 if (context->getClientVersion() < ES_3_1)
2356 {
2357 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002358 InvalidEnum()
2359 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002360 return false;
2361 }
2362 if (index >= caps.maxVertexAttribBindings)
2363 {
2364 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 InvalidValue()
2366 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002367 return false;
2368 }
2369 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002370 case GL_SAMPLE_MASK_VALUE:
2371 if (context->getClientVersion() < ES_3_1)
2372 {
2373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2374 return false;
2375 }
2376 if (index >= caps.maxSampleMaskWords)
2377 {
2378 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2379 return false;
2380 }
2381 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002382 case GL_IMAGE_BINDING_NAME:
2383 case GL_IMAGE_BINDING_LEVEL:
2384 case GL_IMAGE_BINDING_LAYERED:
2385 case GL_IMAGE_BINDING_LAYER:
2386 case GL_IMAGE_BINDING_ACCESS:
2387 case GL_IMAGE_BINDING_FORMAT:
2388 if (context->getClientVersion() < ES_3_1)
2389 {
2390 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2391 return false;
2392 }
2393 if (index >= caps.maxImageUnits)
2394 {
2395 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2396 return false;
2397 }
2398 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002399 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002400 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002401 return false;
2402 }
2403
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002404 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002405 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002406 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002407 }
2408
2409 return true;
2410}
2411
Jamie Madill5b772312018-03-08 20:28:32 -05002412bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002413{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002414 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002415 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002416 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002417 return false;
2418 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002419 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002420}
2421
Jamie Madill5b772312018-03-08 20:28:32 -05002422bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002423 GLenum target,
2424 GLuint index,
2425 GLsizei bufSize,
2426 GLsizei *length,
2427 GLint *data)
2428{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002429 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002430 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002432 return false;
2433 }
2434
2435 if (!ValidateRobustEntryPoint(context, bufSize))
2436 {
2437 return false;
2438 }
2439
Brandon Jonesd1049182018-03-28 10:02:20 -07002440 GLsizei numParams = 0;
2441
2442 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002443 {
2444 return false;
2445 }
2446
Brandon Jonesd1049182018-03-28 10:02:20 -07002447 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002448 {
2449 return false;
2450 }
2451
Brandon Jonesd1049182018-03-28 10:02:20 -07002452 SetRobustLengthParam(length, numParams);
2453
Geoff Langcf255ea2016-10-20 11:39:09 -07002454 return true;
2455}
2456
Jamie Madill5b772312018-03-08 20:28:32 -05002457bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002458{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002459 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002460 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002461 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002462 return false;
2463 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002464 return ValidateIndexedStateQuery(context, target, index, nullptr);
2465}
2466
Jamie Madill5b772312018-03-08 20:28:32 -05002467bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002468 GLenum target,
2469 GLuint index,
2470 GLsizei bufSize,
2471 GLsizei *length,
2472 GLint64 *data)
2473{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002474 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002475 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002477 return false;
2478 }
2479
2480 if (!ValidateRobustEntryPoint(context, bufSize))
2481 {
2482 return false;
2483 }
2484
Brandon Jonesd1049182018-03-28 10:02:20 -07002485 GLsizei numParams = 0;
2486
2487 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002488 {
2489 return false;
2490 }
2491
Brandon Jonesd1049182018-03-28 10:02:20 -07002492 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002493 {
2494 return false;
2495 }
2496
Brandon Jonesd1049182018-03-28 10:02:20 -07002497 SetRobustLengthParam(length, numParams);
2498
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002499 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002500}
2501
Jamie Madill5b772312018-03-08 20:28:32 -05002502bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002503 BufferBinding readTarget,
2504 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002505 GLintptr readOffset,
2506 GLintptr writeOffset,
2507 GLsizeiptr size)
2508{
2509 if (context->getClientMajorVersion() < 3)
2510 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002512 return false;
2513 }
2514
Corentin Walleze4477002017-12-01 14:39:58 -05002515 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002517 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002518 return false;
2519 }
2520
2521 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2522 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2523
2524 if (!readBuffer || !writeBuffer)
2525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002526 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002527 return false;
2528 }
2529
2530 // Verify that readBuffer and writeBuffer are not currently mapped
2531 if (readBuffer->isMapped() || writeBuffer->isMapped())
2532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002533 context->handleError(InvalidOperation()
2534 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002535 return false;
2536 }
2537
James Darpiniane8a93c62018-01-04 18:02:24 -08002538 if (context->getExtensions().webglCompatibility &&
2539 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2540 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2541 {
2542 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2543 return false;
2544 }
2545
Jamie Madilld2f0c742016-11-02 10:34:41 -04002546 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2547 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2548 CheckedNumeric<GLintptr> checkedSize(size);
2549
2550 auto checkedReadSum = checkedReadOffset + checkedSize;
2551 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2552
2553 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2554 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2555 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002557 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002558 return false;
2559 }
2560
Jamie Madilld2f0c742016-11-02 10:34:41 -04002561 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002563 context->handleError(InvalidValue()
2564 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002565 return false;
2566 }
2567
Jamie Madilld2f0c742016-11-02 10:34:41 -04002568 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2569 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002571 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002572 return false;
2573 }
2574
2575 if (readBuffer == writeBuffer)
2576 {
2577 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2578 if (!checkedOffsetDiff.IsValid())
2579 {
2580 // This shold not be possible.
2581 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002582 context->handleError(InvalidValue()
2583 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002584 return false;
2585 }
2586
2587 if (checkedOffsetDiff.ValueOrDie() < size)
2588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002589 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002590 return false;
2591 }
2592 }
2593
Jamie Madillb0817d12016-11-01 15:48:31 -04002594 return true;
2595}
2596
Geoff Langc339c4e2016-11-29 10:37:36 -05002597bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2598{
2599 if (context->getClientMajorVersion() < 3)
2600 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002601 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002602 return false;
2603 }
2604
2605 switch (name)
2606 {
2607 case GL_EXTENSIONS:
2608 if (index >= context->getExtensionStringCount())
2609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002610 context->handleError(InvalidValue()
2611 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002612 return false;
2613 }
2614 break;
2615
2616 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2617 if (!context->getExtensions().requestExtension)
2618 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002619 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002620 return false;
2621 }
2622 if (index >= context->getRequestableExtensionStringCount())
2623 {
2624 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002625 InvalidValue()
2626 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002627 return false;
2628 }
2629 break;
2630
2631 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002632 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002633 return false;
2634 }
2635
2636 return true;
2637}
2638
Jamie Madill5b772312018-03-08 20:28:32 -05002639bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002640 GLenum target,
2641 GLsizei samples,
2642 GLenum internalformat,
2643 GLsizei width,
2644 GLsizei height)
2645{
2646 if (context->getClientMajorVersion() < 3)
2647 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002649 return false;
2650 }
2651
2652 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2653 height))
2654 {
2655 return false;
2656 }
2657
2658 // 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 +08002659 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2660 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002661 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002662 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002663 {
Yunchao Hec0810202018-01-22 09:48:48 +08002664 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2665 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2666 {
2667 context->handleError(InvalidOperation());
2668 return false;
2669 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002670 }
2671
2672 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2673 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2674 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2675 {
2676 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002677 InvalidOperation()
2678 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002679 return false;
2680 }
2681
2682 return true;
2683}
2684
Jamie Madill5b772312018-03-08 20:28:32 -05002685bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002686 GLuint index,
2687 GLint size,
2688 GLenum type,
2689 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002690 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002691{
2692 if (context->getClientMajorVersion() < 3)
2693 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002695 return false;
2696 }
2697
Shao80957d92017-02-20 21:25:59 +08002698 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002699 {
Geoff Langaa086d62017-03-23 16:47:21 -04002700 return false;
2701 }
2702
Geoff Langaa086d62017-03-23 16:47:21 -04002703 if (stride < 0)
2704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002705 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002706 return false;
2707 }
2708
Shao80957d92017-02-20 21:25:59 +08002709 const Caps &caps = context->getCaps();
2710 if (context->getClientVersion() >= ES_3_1)
2711 {
2712 if (stride > caps.maxVertexAttribStride)
2713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002714 context->handleError(InvalidValue()
2715 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002716 return false;
2717 }
2718
2719 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2720 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2721 // validation should be inherited.
2722 if (index >= caps.maxVertexAttribBindings)
2723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002724 context->handleError(InvalidValue()
2725 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002726 return false;
2727 }
2728 }
2729
Geoff Langaa086d62017-03-23 16:47:21 -04002730 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2731 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2732 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2733 // and the pointer argument is not NULL.
2734 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002735 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002737 context
2738 ->handleError(InvalidOperation()
2739 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002740 return false;
2741 }
2742
Geoff Lang2d62ab72017-03-23 16:54:40 -04002743 if (context->getExtensions().webglCompatibility)
2744 {
2745 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2746 {
2747 return false;
2748 }
2749 }
2750
Geoff Langaa086d62017-03-23 16:47:21 -04002751 return true;
2752}
2753
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002754bool ValidateGetSynciv(Context *context,
2755 GLsync sync,
2756 GLenum pname,
2757 GLsizei bufSize,
2758 GLsizei *length,
2759 GLint *values)
2760{
2761 if (context->getClientMajorVersion() < 3)
2762 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002763 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002764 return false;
2765 }
2766
2767 if (bufSize < 0)
2768 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002769 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002770 return false;
2771 }
2772
Jamie Madill70b5bb02017-08-28 13:32:37 -04002773 Sync *syncObject = context->getSync(sync);
2774 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002776 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002777 return false;
2778 }
2779
2780 switch (pname)
2781 {
2782 case GL_OBJECT_TYPE:
2783 case GL_SYNC_CONDITION:
2784 case GL_SYNC_FLAGS:
2785 case GL_SYNC_STATUS:
2786 break;
2787
2788 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002790 return false;
2791 }
2792
2793 return true;
2794}
2795
Jamie Madill5b772312018-03-08 20:28:32 -05002796bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002797 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002798 GLsizei count,
2799 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002800 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002801 GLsizei instanceCount)
2802{
2803 if (context->getClientMajorVersion() < 3)
2804 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002806 return false;
2807 }
2808
2809 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2810}
2811
Martin Radev137032d2017-07-13 10:11:12 +03002812bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2813 GLenum target,
2814 GLenum attachment,
2815 GLuint texture,
2816 GLint level,
2817 GLint baseViewIndex,
2818 GLsizei numViews)
2819{
2820
2821 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2822 numViews))
2823 {
2824 return false;
2825 }
2826
Martin Radev137032d2017-07-13 10:11:12 +03002827 if (texture != 0)
2828 {
Martin Radev14b21262017-08-25 13:54:37 +03002829 if (baseViewIndex < 0)
2830 {
2831 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2832 return false;
2833 }
2834
Martin Radev137032d2017-07-13 10:11:12 +03002835 Texture *tex = context->getTexture(texture);
2836 ASSERT(tex);
2837
Corentin Wallez99d492c2018-02-27 15:17:10 -05002838 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002839 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002840 case TextureType::_2DArray:
Martin Radev137032d2017-07-13 10:11:12 +03002841 {
2842 const Caps &caps = context->getCaps();
2843 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2844 {
2845 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2846 "greater than "
2847 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2848 return false;
2849 }
2850 }
2851 break;
2852 default:
2853 context->handleError(InvalidOperation()
2854 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2855 return false;
2856 }
2857
2858 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2859 {
2860 return false;
2861 }
2862 }
2863
2864 return true;
2865}
2866
2867bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2868 GLenum target,
2869 GLenum attachment,
2870 GLuint texture,
2871 GLint level,
2872 GLsizei numViews,
2873 const GLint *viewportOffsets)
2874{
2875 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2876 numViews))
2877 {
2878 return false;
2879 }
2880
Martin Radev137032d2017-07-13 10:11:12 +03002881 if (texture != 0)
2882 {
Martin Radev14b21262017-08-25 13:54:37 +03002883 const GLsizei numViewportOffsetValues = numViews * 2;
2884 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2885 {
2886 if (viewportOffsets[i] < 0)
2887 {
2888 context->handleError(InvalidValue()
2889 << "viewportOffsets cannot contain negative values.");
2890 return false;
2891 }
2892 }
2893
Martin Radev137032d2017-07-13 10:11:12 +03002894 Texture *tex = context->getTexture(texture);
2895 ASSERT(tex);
2896
Corentin Wallez99d492c2018-02-27 15:17:10 -05002897 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002898 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002899 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002900 break;
2901 default:
2902 context->handleError(InvalidOperation()
2903 << "Texture's target must be GL_TEXTURE_2D.");
2904 return false;
2905 }
2906
2907 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2908 {
2909 return false;
2910 }
2911 }
2912
2913 return true;
2914}
2915
Jamie Madillff325f12017-08-26 15:06:05 -04002916bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2917{
2918 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2919}
2920
2921bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2922{
2923 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2924}
2925
2926bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2927{
2928 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2929}
2930
2931bool ValidateUniform4ui(Context *context,
2932 GLint location,
2933 GLuint v0,
2934 GLuint v1,
2935 GLuint v2,
2936 GLuint v3)
2937{
2938 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2939}
2940
2941bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2942{
2943 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2944}
2945
2946bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2947{
2948 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2949}
2950
2951bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2952{
2953 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2954}
2955
2956bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2957{
2958 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2959}
2960
Jamie Madillf0e04492017-08-26 15:28:42 -04002961bool ValidateIsQuery(Context *context, GLuint id)
2962{
2963 if (context->getClientMajorVersion() < 3)
2964 {
2965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2966 return false;
2967 }
2968
2969 return true;
2970}
2971
Jamie Madillc8c95812017-08-26 18:40:09 -04002972bool ValidateUniformMatrix2x3fv(Context *context,
2973 GLint location,
2974 GLsizei count,
2975 GLboolean transpose,
2976 const GLfloat *value)
2977{
2978 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2979}
2980
2981bool ValidateUniformMatrix3x2fv(Context *context,
2982 GLint location,
2983 GLsizei count,
2984 GLboolean transpose,
2985 const GLfloat *value)
2986{
2987 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2988}
2989
2990bool ValidateUniformMatrix2x4fv(Context *context,
2991 GLint location,
2992 GLsizei count,
2993 GLboolean transpose,
2994 const GLfloat *value)
2995{
2996 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2997}
2998
2999bool ValidateUniformMatrix4x2fv(Context *context,
3000 GLint location,
3001 GLsizei count,
3002 GLboolean transpose,
3003 const GLfloat *value)
3004{
3005 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3006}
3007
3008bool ValidateUniformMatrix3x4fv(Context *context,
3009 GLint location,
3010 GLsizei count,
3011 GLboolean transpose,
3012 const GLfloat *value)
3013{
3014 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3015}
3016
3017bool ValidateUniformMatrix4x3fv(Context *context,
3018 GLint location,
3019 GLsizei count,
3020 GLboolean transpose,
3021 const GLfloat *value)
3022{
3023 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3024}
3025
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003026bool ValidateEndTransformFeedback(Context *context)
3027{
3028 if (context->getClientMajorVersion() < 3)
3029 {
3030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3031 return false;
3032 }
3033
3034 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3035 ASSERT(transformFeedback != nullptr);
3036
3037 if (!transformFeedback->isActive())
3038 {
3039 context->handleError(InvalidOperation());
3040 return false;
3041 }
3042
3043 return true;
3044}
3045
3046bool ValidateTransformFeedbackVaryings(Context *context,
3047 GLuint program,
3048 GLsizei count,
3049 const GLchar *const *varyings,
3050 GLenum bufferMode)
3051{
3052 if (context->getClientMajorVersion() < 3)
3053 {
3054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3055 return false;
3056 }
3057
3058 if (count < 0)
3059 {
3060 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3061 return false;
3062 }
3063
3064 switch (bufferMode)
3065 {
3066 case GL_INTERLEAVED_ATTRIBS:
3067 break;
3068 case GL_SEPARATE_ATTRIBS:
3069 {
3070 const Caps &caps = context->getCaps();
3071 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3072 {
3073 context->handleError(InvalidValue());
3074 return false;
3075 }
3076 break;
3077 }
3078 default:
3079 context->handleError(InvalidEnum());
3080 return false;
3081 }
3082
3083 Program *programObject = GetValidProgram(context, program);
3084 if (!programObject)
3085 {
3086 return false;
3087 }
3088
3089 return true;
3090}
3091
3092bool ValidateGetTransformFeedbackVarying(Context *context,
3093 GLuint program,
3094 GLuint index,
3095 GLsizei bufSize,
3096 GLsizei *length,
3097 GLsizei *size,
3098 GLenum *type,
3099 GLchar *name)
3100{
3101 if (context->getClientMajorVersion() < 3)
3102 {
3103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3104 return false;
3105 }
3106
3107 if (bufSize < 0)
3108 {
3109 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3110 return false;
3111 }
3112
3113 Program *programObject = GetValidProgram(context, program);
3114 if (!programObject)
3115 {
3116 return false;
3117 }
3118
3119 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3120 {
3121 context->handleError(InvalidValue());
3122 return false;
3123 }
3124
3125 return true;
3126}
3127
3128bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3129{
3130 if (context->getClientMajorVersion() < 3)
3131 {
3132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3133 return false;
3134 }
3135
3136 switch (target)
3137 {
3138 case GL_TRANSFORM_FEEDBACK:
3139 {
3140 // Cannot bind a transform feedback object if the current one is started and not
3141 // paused (3.0.2 pg 85 section 2.14.1)
3142 TransformFeedback *curTransformFeedback =
3143 context->getGLState().getCurrentTransformFeedback();
3144 if (curTransformFeedback && curTransformFeedback->isActive() &&
3145 !curTransformFeedback->isPaused())
3146 {
3147 context->handleError(InvalidOperation());
3148 return false;
3149 }
3150
3151 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3152 // 2.14.1)
3153 if (!context->isTransformFeedbackGenerated(id))
3154 {
3155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3156 return false;
3157 }
3158 }
3159 break;
3160
3161 default:
3162 context->handleError(InvalidEnum());
3163 return false;
3164 }
3165
3166 return true;
3167}
3168
3169bool ValidateIsTransformFeedback(Context *context, GLuint id)
3170{
3171 if (context->getClientMajorVersion() < 3)
3172 {
3173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3174 return false;
3175 }
3176
3177 return true;
3178}
3179
3180bool ValidatePauseTransformFeedback(Context *context)
3181{
3182 if (context->getClientMajorVersion() < 3)
3183 {
3184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3185 return false;
3186 }
3187
3188 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3189 ASSERT(transformFeedback != nullptr);
3190
3191 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3192 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3193 {
3194 context->handleError(InvalidOperation());
3195 return false;
3196 }
3197
3198 return true;
3199}
3200
3201bool ValidateResumeTransformFeedback(Context *context)
3202{
3203 if (context->getClientMajorVersion() < 3)
3204 {
3205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3206 return false;
3207 }
3208
3209 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3210 ASSERT(transformFeedback != nullptr);
3211
3212 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3213 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3214 {
3215 context->handleError(InvalidOperation());
3216 return false;
3217 }
3218
3219 return true;
3220}
3221
Jamie Madill12e957f2017-08-26 21:42:26 -04003222bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3223{
3224 if (context->getClientMajorVersion() < 3)
3225 {
3226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3227 return false;
3228 }
3229
3230 return ValidateVertexAttribIndex(context, index);
3231}
3232
3233bool ValidateVertexAttribI4ui(Context *context,
3234 GLuint index,
3235 GLuint x,
3236 GLuint y,
3237 GLuint z,
3238 GLuint w)
3239{
3240 if (context->getClientMajorVersion() < 3)
3241 {
3242 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3243 return false;
3244 }
3245
3246 return ValidateVertexAttribIndex(context, index);
3247}
3248
3249bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3250{
3251 if (context->getClientMajorVersion() < 3)
3252 {
3253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3254 return false;
3255 }
3256
3257 return ValidateVertexAttribIndex(context, index);
3258}
3259
3260bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3261{
3262 if (context->getClientMajorVersion() < 3)
3263 {
3264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3265 return false;
3266 }
3267
3268 return ValidateVertexAttribIndex(context, index);
3269}
3270
3271bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3272{
3273 if (context->getClientMajorVersion() < 3)
3274 {
3275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3276 return false;
3277 }
3278
3279 Program *programObject = GetValidProgram(context, program);
3280 if (!programObject)
3281 {
3282 return false;
3283 }
3284
3285 if (!programObject->isLinked())
3286 {
3287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3288 return false;
3289 }
3290
3291 return true;
3292}
3293
3294bool ValidateGetUniformIndices(Context *context,
3295 GLuint program,
3296 GLsizei uniformCount,
3297 const GLchar *const *uniformNames,
3298 GLuint *uniformIndices)
3299{
3300 if (context->getClientMajorVersion() < 3)
3301 {
3302 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3303 return false;
3304 }
3305
3306 if (uniformCount < 0)
3307 {
3308 context->handleError(InvalidValue());
3309 return false;
3310 }
3311
3312 Program *programObject = GetValidProgram(context, program);
3313 if (!programObject)
3314 {
3315 return false;
3316 }
3317
3318 return true;
3319}
3320
3321bool ValidateGetActiveUniformsiv(Context *context,
3322 GLuint program,
3323 GLsizei uniformCount,
3324 const GLuint *uniformIndices,
3325 GLenum pname,
3326 GLint *params)
3327{
3328 if (context->getClientMajorVersion() < 3)
3329 {
3330 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3331 return false;
3332 }
3333
3334 if (uniformCount < 0)
3335 {
3336 context->handleError(InvalidValue());
3337 return false;
3338 }
3339
3340 Program *programObject = GetValidProgram(context, program);
3341 if (!programObject)
3342 {
3343 return false;
3344 }
3345
3346 switch (pname)
3347 {
3348 case GL_UNIFORM_TYPE:
3349 case GL_UNIFORM_SIZE:
3350 case GL_UNIFORM_NAME_LENGTH:
3351 case GL_UNIFORM_BLOCK_INDEX:
3352 case GL_UNIFORM_OFFSET:
3353 case GL_UNIFORM_ARRAY_STRIDE:
3354 case GL_UNIFORM_MATRIX_STRIDE:
3355 case GL_UNIFORM_IS_ROW_MAJOR:
3356 break;
3357
3358 default:
3359 context->handleError(InvalidEnum());
3360 return false;
3361 }
3362
3363 if (uniformCount > programObject->getActiveUniformCount())
3364 {
3365 context->handleError(InvalidValue());
3366 return false;
3367 }
3368
3369 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3370 {
3371 const GLuint index = uniformIndices[uniformId];
3372
3373 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3374 {
3375 context->handleError(InvalidValue());
3376 return false;
3377 }
3378 }
3379
3380 return true;
3381}
3382
3383bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3384{
3385 if (context->getClientMajorVersion() < 3)
3386 {
3387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3388 return false;
3389 }
3390
3391 Program *programObject = GetValidProgram(context, program);
3392 if (!programObject)
3393 {
3394 return false;
3395 }
3396
3397 return true;
3398}
3399
3400bool ValidateGetActiveUniformBlockiv(Context *context,
3401 GLuint program,
3402 GLuint uniformBlockIndex,
3403 GLenum pname,
3404 GLint *params)
3405{
3406 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3407}
3408
3409bool ValidateGetActiveUniformBlockName(Context *context,
3410 GLuint program,
3411 GLuint uniformBlockIndex,
3412 GLsizei bufSize,
3413 GLsizei *length,
3414 GLchar *uniformBlockName)
3415{
3416 if (context->getClientMajorVersion() < 3)
3417 {
3418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3419 return false;
3420 }
3421
3422 Program *programObject = GetValidProgram(context, program);
3423 if (!programObject)
3424 {
3425 return false;
3426 }
3427
3428 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3429 {
3430 context->handleError(InvalidValue());
3431 return false;
3432 }
3433
3434 return true;
3435}
3436
3437bool ValidateUniformBlockBinding(Context *context,
3438 GLuint program,
3439 GLuint uniformBlockIndex,
3440 GLuint uniformBlockBinding)
3441{
3442 if (context->getClientMajorVersion() < 3)
3443 {
3444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3445 return false;
3446 }
3447
3448 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3449 {
3450 context->handleError(InvalidValue());
3451 return false;
3452 }
3453
3454 Program *programObject = GetValidProgram(context, program);
3455 if (!programObject)
3456 {
3457 return false;
3458 }
3459
3460 // if never linked, there won't be any uniform blocks
3461 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3462 {
3463 context->handleError(InvalidValue());
3464 return false;
3465 }
3466
3467 return true;
3468}
3469
3470bool ValidateDrawArraysInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003471 PrimitiveMode mode,
Jamie Madill12e957f2017-08-26 21:42:26 -04003472 GLint first,
3473 GLsizei count,
3474 GLsizei primcount)
3475{
3476 if (context->getClientMajorVersion() < 3)
3477 {
3478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3479 return false;
3480 }
3481
3482 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3483}
3484
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003485bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3486{
3487 if (context->getClientMajorVersion() < 3)
3488 {
3489 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3490 return false;
3491 }
3492
3493 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3494 {
3495 context->handleError(InvalidEnum());
3496 return false;
3497 }
3498
3499 if (flags != 0)
3500 {
3501 context->handleError(InvalidValue());
3502 return false;
3503 }
3504
3505 return true;
3506}
3507
3508bool ValidateIsSync(Context *context, GLsync sync)
3509{
3510 if (context->getClientMajorVersion() < 3)
3511 {
3512 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3513 return false;
3514 }
3515
3516 return true;
3517}
3518
3519bool ValidateDeleteSync(Context *context, GLsync sync)
3520{
3521 if (context->getClientMajorVersion() < 3)
3522 {
3523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3524 return false;
3525 }
3526
Jamie Madill70b5bb02017-08-28 13:32:37 -04003527 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003528 {
3529 context->handleError(InvalidValue());
3530 return false;
3531 }
3532
3533 return true;
3534}
3535
3536bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3537{
3538 if (context->getClientMajorVersion() < 3)
3539 {
3540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3541 return false;
3542 }
3543
3544 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3545 {
3546 context->handleError(InvalidValue());
3547 return false;
3548 }
3549
Jamie Madill70b5bb02017-08-28 13:32:37 -04003550 Sync *clientWaitSync = context->getSync(sync);
3551 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003552 {
3553 context->handleError(InvalidValue());
3554 return false;
3555 }
3556
3557 return true;
3558}
3559
3560bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3561{
3562 if (context->getClientMajorVersion() < 3)
3563 {
3564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3565 return false;
3566 }
3567
3568 if (flags != 0)
3569 {
3570 context->handleError(InvalidValue());
3571 return false;
3572 }
3573
3574 if (timeout != GL_TIMEOUT_IGNORED)
3575 {
3576 context->handleError(InvalidValue());
3577 return false;
3578 }
3579
Jamie Madill70b5bb02017-08-28 13:32:37 -04003580 Sync *waitSync = context->getSync(sync);
3581 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003582 {
3583 context->handleError(InvalidValue());
3584 return false;
3585 }
3586
3587 return true;
3588}
3589
3590bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3591{
3592 if (context->getClientMajorVersion() < 3)
3593 {
3594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3595 return false;
3596 }
3597
3598 GLenum nativeType = GL_NONE;
3599 unsigned int numParams = 0;
3600 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3601 {
3602 return false;
3603 }
3604
3605 return true;
3606}
3607
Jamie Madill3ef140a2017-08-26 23:11:21 -04003608bool ValidateIsSampler(Context *context, GLuint sampler)
3609{
3610 if (context->getClientMajorVersion() < 3)
3611 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003612 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003613 return false;
3614 }
3615
3616 return true;
3617}
3618
3619bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3620{
3621 if (context->getClientMajorVersion() < 3)
3622 {
3623 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3624 return false;
3625 }
3626
3627 if (sampler != 0 && !context->isSampler(sampler))
3628 {
3629 context->handleError(InvalidOperation());
3630 return false;
3631 }
3632
3633 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3634 {
3635 context->handleError(InvalidValue());
3636 return false;
3637 }
3638
3639 return true;
3640}
3641
3642bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3643{
3644 if (context->getClientMajorVersion() < 3)
3645 {
3646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3647 return false;
3648 }
3649
3650 return ValidateVertexAttribIndex(context, index);
3651}
3652
3653bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003654 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003655 GLsizei levels,
3656 GLenum internalformat,
3657 GLsizei width,
3658 GLsizei height)
3659{
3660 if (context->getClientMajorVersion() < 3)
3661 {
3662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3663 return false;
3664 }
3665
3666 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3667 1))
3668 {
3669 return false;
3670 }
3671
3672 return true;
3673}
3674
3675bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003676 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003677 GLsizei levels,
3678 GLenum internalformat,
3679 GLsizei width,
3680 GLsizei height,
3681 GLsizei depth)
3682{
3683 if (context->getClientMajorVersion() < 3)
3684 {
3685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3686 return false;
3687 }
3688
3689 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3690 depth))
3691 {
3692 return false;
3693 }
3694
3695 return true;
3696}
3697
Jamie Madill5b772312018-03-08 20:28:32 -05003698bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003699 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003700 GLenum pname,
3701 GLint64 *params)
3702{
3703 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3704}
3705
3706bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3707{
3708 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3709}
3710
3711bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3712{
3713 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3714}
3715
3716bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3717{
3718 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3719}
3720
3721bool ValidateSamplerParameterfv(Context *context,
3722 GLuint sampler,
3723 GLenum pname,
3724 const GLfloat *params)
3725{
3726 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3727}
3728
3729bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3730{
3731 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3732}
3733
3734bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3735{
3736 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3737}
3738
3739bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3740{
3741 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3742}
3743
3744bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3745{
3746 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3747}
3748
3749bool ValidateGetInternalformativ(Context *context,
3750 GLenum target,
3751 GLenum internalformat,
3752 GLenum pname,
3753 GLsizei bufSize,
3754 GLint *params)
3755{
3756 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3757 nullptr);
3758}
3759
Jamie Madillc29968b2016-01-20 11:17:23 -05003760} // namespace gl