blob: f132e696a1d9bfb7801a1e9c9b74a452b72b3d55 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
Corentin Wallezf0e89be2017-11-08 14:00:32 -080069 TextureType type = texture->getType();
70 if (!ValidMipLevel(context, type, level))
Martin Radev137032d2017-07-13 10:11:12 +030071 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
Corentin Wallezf0e89be2017-11-08 14:00:32 -080076 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
Martin Radev137032d2017-07-13 10:11:12 +030077 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800140 TextureType target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800174 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
Geoff Langca271392017-04-05 12:30:00 -0400175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800201 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800218 TextureType texType = TextureTargetToType(target);
219
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 // Validate image size
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800221 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500223 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 }
226
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 // Verify zero border
228 if (border != 0)
229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
Jamie Madill6f38f822014-06-06 17:12:20 -0400234 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
235 std::numeric_limits<GLsizei>::max() - xoffset < width ||
236 std::numeric_limits<GLsizei>::max() - yoffset < height ||
237 std::numeric_limits<GLsizei>::max() - zoffset < depth)
238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500239 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400240 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400241 }
242
Geoff Langaae65a42014-05-26 12:43:44 -0400243 const gl::Caps &caps = context->getCaps();
244
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800245 switch (texType)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800247 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800248 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
249 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500251 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800252 return false;
253 }
254 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800256 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257 ASSERT(level == 0);
258 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
259 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
260 {
261 context->handleError(InvalidValue());
262 return false;
263 }
264 if (isCompressed)
265 {
266 context->handleError(InvalidEnum()
267 << "Rectangle texture cannot have a compressed format.");
268 return false;
269 }
270 break;
271
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800272 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800273 if (!isSubImage && width != height)
274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500275 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800276 return false;
277 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400278
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500281 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 return false;
283 }
284 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800286 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800287 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
288 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
289 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500291 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800292 return false;
293 }
294 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800296 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800297 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
298 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
299 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500301 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800302 return false;
303 }
304 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305
He Yunchaoced53ae2016-11-29 15:00:51 +0800306 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500307 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 }
310
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800311 gl::Texture *texture = context->getTargetTexture(texType);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 if (!texture)
313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 }
317
Geoff Lang69cce582015-09-17 13:20:36 -0400318 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
324 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400325 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400326 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500327 if (isSubImage && actualInternalFormat == GL_NONE)
328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500330 return false;
331 }
332
Geoff Langc4e93662017-05-01 10:45:59 -0400333 const gl::InternalFormat &actualFormatInfo = isSubImage
334 ? *texture->getFormat(target, level).info
335 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 if (isCompressed)
337 {
tmartino7c102692015-10-02 16:43:40 -0400338 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500340 context->handleError(
341 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400342 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 }
344
Geoff Lang966c9402017-04-18 12:38:27 -0400345 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 {
Geoff Lang966c9402017-04-18 12:38:27 -0400347 if (!ValidCompressedSubImageSize(
348 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
349 texture->getWidth(target, level), texture->getHeight(target, level)))
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400352 return false;
353 }
354
355 if (format != actualInternalFormat)
356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500357 context->handleError(InvalidOperation()
358 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400359 return false;
360 }
Geoff Lang86f81162017-10-30 15:10:45 -0400361
362 if (actualInternalFormat == GL_ETC1_RGB8_OES)
363 {
364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
365 return false;
366 }
Geoff Lang966c9402017-04-18 12:38:27 -0400367 }
368 else
369 {
370 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500372 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400373 return false;
374 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 }
376
Geoff Langeb66a6e2016-10-31 13:06:12 -0400377 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500379 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400380 return false;
381 }
382
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800383 if (texType == TextureType::_3D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388 }
389 else
390 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800391 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
392 type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 {
Geoff Lang5d601382014-07-22 15:14:06 -0400394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 }
397
398 // Validate sub image parameters
399 if (isSubImage)
400 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500401 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500403 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 }
406
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500409 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 }
412
413 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
414 std::numeric_limits<GLsizei>::max() - yoffset < height ||
415 std::numeric_limits<GLsizei>::max() - zoffset < depth)
416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420
Geoff Langa9be0dc2014-12-17 12:34:40 -0500421 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
422 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
423 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500425 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 }
Geoff Langfb052642017-10-24 13:42:09 -0400428
429 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400430 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400431 {
432 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
433 return false;
434 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 }
436
Geoff Langdbcced82017-06-06 15:55:54 -0400437 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800438 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
Geoff Langdbcced82017-06-06 15:55:54 -0400439 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400440 {
441 return false;
442 }
443
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400444 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400445 gl::Buffer *pixelUnpackBuffer =
446 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400447 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400448 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 // ...data is not evenly divisible into the number of bytes needed to store in memory a
450 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400451 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400452 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400453 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400454 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400455 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
456
Geoff Langff5b2d52016-09-07 11:32:23 -0400457 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500459 context->handleError(InvalidOperation()
460 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 return false;
462 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400463 }
464
Jamie Madill7a5f7382014-03-05 15:01:24 -0500465 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700466 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500468 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400469 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500470 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400471 }
472
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400473 return true;
474}
475
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500476bool ValidateES3TexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800477 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500478 GLint level,
479 GLenum internalformat,
480 bool isCompressed,
481 bool isSubImage,
482 GLint xoffset,
483 GLint yoffset,
484 GLint zoffset,
485 GLsizei width,
486 GLsizei height,
487 GLsizei depth,
488 GLint border,
489 GLenum format,
490 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400491 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400492 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500493{
494 if (!ValidTexture2DDestinationTarget(context, target))
495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500496 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500497 return false;
498 }
499
500 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
501 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400502 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500503}
504
505bool ValidateES3TexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800506 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500507 GLint level,
508 GLenum internalformat,
509 bool isCompressed,
510 bool isSubImage,
511 GLint xoffset,
512 GLint yoffset,
513 GLint zoffset,
514 GLsizei width,
515 GLsizei height,
516 GLsizei depth,
517 GLint border,
518 GLenum format,
519 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400520 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400521 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522{
523 if (!ValidTexture3DDestinationTarget(context, target))
524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500525 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526 return false;
527 }
528
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 if (IsETC2EACFormat(format) && target != TextureType::_2DArray)
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500530 {
531 // ES 3.1, Section 8.7, page 169.
532 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
533 return false;
534 }
535
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800536 return ValidateES3TexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
537 internalformat, isCompressed, isSubImage, xoffset,
538 yoffset, zoffset, width, height, depth, border, format,
539 type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540}
541
Geoff Lang5d601382014-07-22 15:14:06 -0400542struct EffectiveInternalFormatInfo
543{
Jamie Madill76648fe2016-10-05 17:01:41 -0400544 GLenum effectiveFormat;
545 GLenum destFormat;
546 GLuint minRedBits;
547 GLuint maxRedBits;
548 GLuint minGreenBits;
549 GLuint maxGreenBits;
550 GLuint minBlueBits;
551 GLuint maxBlueBits;
552 GLuint minAlphaBits;
553 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400554};
555
Jamie Madill76648fe2016-10-05 17:01:41 -0400556static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
557 GLenum targetFormat,
558 const EffectiveInternalFormatInfo *list,
559 size_t size,
560 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400561{
Jamie Madill76648fe2016-10-05 17:01:41 -0400562 for (size_t curFormat = 0; curFormat < size; ++curFormat)
563 {
564 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
565 if ((formatInfo.destFormat == targetFormat) &&
566 (formatInfo.minRedBits <= srcFormat.redBits &&
567 formatInfo.maxRedBits >= srcFormat.redBits) &&
568 (formatInfo.minGreenBits <= srcFormat.greenBits &&
569 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
570 (formatInfo.minBlueBits <= srcFormat.blueBits &&
571 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
572 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
573 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
574 {
575 *outEffectiveFormat = formatInfo.effectiveFormat;
576 return true;
577 }
578 }
Geoff Lang5d601382014-07-22 15:14:06 -0400579
Jamie Madill76648fe2016-10-05 17:01:41 -0400580 *outEffectiveFormat = GL_NONE;
581 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400582}
583
Jamie Madill76648fe2016-10-05 17:01:41 -0400584bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
585 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400586{
Jamie Madill76648fe2016-10-05 17:01:41 -0400587 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
588 // Effective internal format coresponding to destination internal format and linear source
589 // buffer component sizes.
590 // | Source channel min/max sizes |
591 // Effective Internal Format | N/A | R | G | B | A |
592 // clang-format off
593 constexpr EffectiveInternalFormatInfo list[] = {
594 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
595 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
596 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
597 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
598 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
599 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
600 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
601 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
602 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
603 };
604 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400605
Jamie Madill76648fe2016-10-05 17:01:41 -0400606 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
607}
Geoff Lang5d601382014-07-22 15:14:06 -0400608
Jamie Madill76648fe2016-10-05 17:01:41 -0400609bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
610 const InternalFormat &destFormat,
611 GLenum *outEffectiveFormat)
612{
613 constexpr GLuint umax = UINT_MAX;
614
615 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
616 // Effective internal format coresponding to destination internal format andlinear source buffer
617 // component sizes.
618 // | Source channel min/max sizes |
619 // Effective Internal Format | Dest Format | R | G | B | A |
620 // clang-format off
621 constexpr EffectiveInternalFormatInfo list[] = {
622 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
623 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
624 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
625 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
626 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
627 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
628 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
629 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
630 };
631 // clang-format on
632
633 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
634 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400635}
636
He Yunchaoced53ae2016-11-29 15:00:51 +0800637static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
638 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400639 GLenum *outEffectiveFormat)
640{
Geoff Langca271392017-04-05 12:30:00 -0400641 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400642 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400643 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400644 }
645 else
646 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400647 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400648 }
Geoff Lang5d601382014-07-22 15:14:06 -0400649}
650
Corentin Wallez76287682016-04-25 09:23:38 -0400651static bool EqualOrFirstZero(GLuint first, GLuint second)
652{
653 return first == 0 || first == second;
654}
655
Geoff Langca271392017-04-05 12:30:00 -0400656static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
657 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400658 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400659{
Jamie Madill21b786b2016-11-01 17:41:31 -0400660 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400661 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400662 return false;
663 }
Geoff Lang5d601382014-07-22 15:14:06 -0400664
Jamie Madill21b786b2016-11-01 17:41:31 -0400665 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
666 // must both be signed, unsigned, or fixed point and both source and destinations
667 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
668 // conversion between fixed and floating point.
669
670 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
671 (framebufferFormatInfo.colorEncoding == GL_SRGB))
672 {
673 return false;
674 }
675
676 if (((textureFormatInfo.componentType == GL_INT) !=
677 (framebufferFormatInfo.componentType == GL_INT)) ||
678 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
679 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
680 {
681 return false;
682 }
683
684 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
685 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
686 textureFormatInfo.componentType == GL_FLOAT) &&
687 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
688 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
689 framebufferFormatInfo.componentType == GL_FLOAT))
690 {
691 return false;
692 }
693
694 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
695 // The effective internal format of the source buffer is determined with the following rules
696 // applied in order:
697 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
698 // format then the effective internal format is the source buffer's sized internal format.
699 // * If the source buffer is a texture that was created with an unsized base internal format,
700 // then the effective internal format is the source image array's effective internal
701 // format, as specified by table 3.12, which is determined from the <format> and <type>
702 // that were used when the source image array was specified by TexImage*.
703 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
704 // where Destination Internal Format matches internalformat and where the [source channel
705 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
706 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
707 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800708 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400709 if (readBufferHandle != 0)
710 {
711 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
712 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400713 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400714 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400715 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400716 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 else
Geoff Lang5d601382014-07-22 15:14:06 -0400718 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 // Renderbuffers cannot be created with an unsized internal format, so this must be an
720 // unsized-format texture. We can use the same table we use when creating textures to
721 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400722 sourceEffectiveFormat =
723 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400724 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400725 }
726 else
727 {
728 // The effective internal format must be derived from the source framebuffer's channel
729 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
730 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400731 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400732 GLenum effectiveFormat;
733 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
734 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400735 {
Geoff Langca271392017-04-05 12:30:00 -0400736 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400737 }
738 else
739 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400740 return false;
741 }
742 }
743 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
744 {
745 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400746 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400747 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
748 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
749 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
750 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
751 {
Geoff Langca271392017-04-05 12:30:00 -0400752 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400753 }
754 else
755 {
756 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400757 }
758 }
759 else
760 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400761 UNREACHABLE();
762 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400763 }
Geoff Lang5d601382014-07-22 15:14:06 -0400764 }
765
Geoff Langca271392017-04-05 12:30:00 -0400766 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400767 {
768 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
769 // sized, component sizes of the source and destination formats must exactly match if the
770 // destination format exists.
771 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
772 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
773 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
774 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
775 {
776 return false;
777 }
778 }
779
780 return true; // A conversion function exists, and no rule in the specification has precluded
781 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400782}
783
Jamie Madill5b772312018-03-08 20:28:32 -0500784bool ValidateES3CopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800785 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786 GLint level,
787 GLenum internalformat,
788 bool isSubImage,
789 GLint xoffset,
790 GLint yoffset,
791 GLint zoffset,
792 GLint x,
793 GLint y,
794 GLsizei width,
795 GLsizei height,
796 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400798 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400799 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 xoffset, yoffset, zoffset, x, y, width, height, border,
801 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400802 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400803 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400805 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806
Jamie Madill51f40ec2016-06-15 14:06:00 -0400807 const auto &state = context->getGLState();
808 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
809 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400810
Jamie Madill427064d2018-04-13 16:20:34 -0400811 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400814 }
815
Jamie Madille98b1b52018-03-08 09:47:23 -0500816 if (readFramebufferID != 0 && !ValidateFramebufferNotMultisampled(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400817 {
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400819 }
820
Jamie Madill0c8abca2016-07-22 20:21:26 -0400821 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822
Yunchao He096a6c82018-02-27 23:48:21 +0800823 // According to ES 3.x spec, if the internalformat of the texture
824 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
825 if (textureFormat.info->internalFormat == GL_RGB9_E5)
826 {
827 context->handleError(InvalidOperation());
828 return false;
829 }
830
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 if (isSubImage)
832 {
Geoff Langca271392017-04-05 12:30:00 -0400833 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500834 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500836 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 }
839 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400840 else
841 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400842 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400843 const InternalFormat &framebufferFormat = *source->getFormat().info;
844 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400845 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500847 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400849 }
850 }
851
Geoff Lang784a8fd2013-09-24 12:33:16 -0400852 // If width or height is zero, it is a no-op. Return false without setting an error.
853 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854}
855
Jamie Madill5b772312018-03-08 20:28:32 -0500856bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800857 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500858 GLint level,
859 GLenum internalformat,
860 bool isSubImage,
861 GLint xoffset,
862 GLint yoffset,
863 GLint zoffset,
864 GLint x,
865 GLint y,
866 GLsizei width,
867 GLsizei height,
868 GLint border)
869{
870 if (!ValidTexture2DDestinationTarget(context, target))
871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500872 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500873 return false;
874 }
875
876 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
877 xoffset, yoffset, zoffset, x, y, width, height,
878 border);
879}
880
Jamie Madill5b772312018-03-08 20:28:32 -0500881bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800882 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 GLint level,
884 GLenum internalformat,
885 bool isSubImage,
886 GLint xoffset,
887 GLint yoffset,
888 GLint zoffset,
889 GLint x,
890 GLint y,
891 GLsizei width,
892 GLsizei height,
893 GLint border)
894{
895 if (!ValidTexture3DDestinationTarget(context, target))
896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500897 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898 return false;
899 }
900
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
902 internalformat, isSubImage, xoffset, yoffset,
903 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500904}
905
906bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800907 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500908 GLsizei levels,
909 GLenum internalformat,
910 GLsizei width,
911 GLsizei height,
912 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913{
914 if (width < 1 || height < 1 || depth < 1 || levels < 1)
915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 }
919
Geoff Langb92c1332015-09-04 12:54:55 -0400920 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800921 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400922 {
923 maxDim = std::max(maxDim, depth);
924 }
925
926 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500928 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 }
931
Geoff Langaae65a42014-05-26 12:43:44 -0400932 const gl::Caps &caps = context->getCaps();
933
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 switch (target)
935 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800936 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 {
Geoff Langaae65a42014-05-26 12:43:44 -0400938 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
939 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 }
944 }
945 break;
946
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800947 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400948 {
949 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
950 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
951 {
952 context->handleError(InvalidValue());
953 return false;
954 }
955 }
956 break;
957
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800958 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 if (width != height)
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965
Geoff Langaae65a42014-05-26 12:43:44 -0400966 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400969 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 }
971 }
972 break;
973
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800974 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 {
Geoff Langaae65a42014-05-26 12:43:44 -0400976 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
977 static_cast<GLuint>(height) > caps.max3DTextureSize ||
978 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500980 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400981 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 }
983 }
984 break;
985
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800986 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400987 {
Geoff Langaae65a42014-05-26 12:43:44 -0400988 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
989 static_cast<GLuint>(height) > caps.max2DTextureSize ||
990 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500992 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400993 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400994 }
995 }
996 break;
997
He Yunchaoced53ae2016-11-29 15:00:51 +0800998 default:
999 UNREACHABLE();
1000 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001001 }
1002
Geoff Lang691e58c2014-12-19 17:03:25 -05001003 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 if (!texture || texture->id() == 0)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Geoff Lang69cce582015-09-17 13:20:36 -04001010 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 }
1015
Geoff Langca271392017-04-05 12:30:00 -04001016 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001017 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022
Geoff Langca271392017-04-05 12:30:00 -04001023 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001025 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001026 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 }
1028
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001029 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001030 {
1031 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1032 return false;
1033 }
1034
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 return true;
1036}
1037
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001038bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001039 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001040 GLsizei levels,
1041 GLenum internalformat,
1042 GLsizei width,
1043 GLsizei height,
1044 GLsizei depth)
1045{
1046 if (!ValidTexture2DTarget(context, target))
1047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001049 return false;
1050 }
1051
1052 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1053 height, depth);
1054}
1055
1056bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001057 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001058 GLsizei levels,
1059 GLenum internalformat,
1060 GLsizei width,
1061 GLsizei height,
1062 GLsizei depth)
1063{
1064 if (!ValidTexture3DTarget(context, target))
1065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001066 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001067 return false;
1068 }
1069
1070 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1071 height, depth);
1072}
1073
Corentin Wallezad3ae902018-03-09 13:40:42 -05001074bool ValidateBeginQuery(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001075{
Martin Radev1be913c2016-07-11 17:59:16 +03001076 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001077 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001079 return false;
1080 }
1081
1082 return ValidateBeginQueryBase(context, target, id);
1083}
1084
Corentin Wallezad3ae902018-03-09 13:40:42 -05001085bool ValidateEndQuery(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086{
Martin Radev1be913c2016-07-11 17:59:16 +03001087 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001088 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001090 return false;
1091 }
1092
1093 return ValidateEndQueryBase(context, target);
1094}
1095
Corentin Wallezad3ae902018-03-09 13:40:42 -05001096bool ValidateGetQueryiv(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097{
Martin Radev1be913c2016-07-11 17:59:16 +03001098 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001099 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001101 return false;
1102 }
1103
Geoff Lang2186c382016-10-14 10:54:54 -04001104 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001105}
1106
1107bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1108{
Martin Radev1be913c2016-07-11 17:59:16 +03001109 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001110 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001112 return false;
1113 }
1114
Geoff Lang2186c382016-10-14 10:54:54 -04001115 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001116}
1117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118bool ValidateFramebufferTextureLayer(Context *context,
1119 GLenum target,
1120 GLenum attachment,
1121 GLuint texture,
1122 GLint level,
1123 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001124{
Martin Radev1be913c2016-07-11 17:59:16 +03001125 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001126 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001128 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001129 }
1130
Jamie Madill55ec3b12014-07-03 10:38:57 -04001131 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1132 {
1133 return false;
1134 }
1135
1136 const gl::Caps &caps = context->getCaps();
1137 if (texture != 0)
1138 {
Geoff Lang23e02842017-10-17 13:24:09 -04001139 if (layer < 0)
1140 {
1141 context->handleError(InvalidValue());
1142 return false;
1143 }
1144
Jamie Madill55ec3b12014-07-03 10:38:57 -04001145 gl::Texture *tex = context->getTexture(texture);
1146 ASSERT(tex);
1147
Corentin Wallez99d492c2018-02-27 15:17:10 -05001148 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001149 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001150 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001151 {
1152 if (level > gl::log2(caps.max2DTextureSize))
1153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001156 }
1157
1158 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001160 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001161 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001162 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001163 }
1164 break;
1165
Corentin Wallez99d492c2018-02-27 15:17:10 -05001166 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001167 {
1168 if (level > gl::log2(caps.max3DTextureSize))
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001172 }
1173
1174 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001176 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001178 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001179 }
1180 break;
1181
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001183 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001185 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001186
Corentin Wallez99d492c2018-02-27 15:17:10 -05001187 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001188 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001190 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001191 return false;
1192 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001193 }
1194
1195 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001196}
1197
He Yunchaoced53ae2016-11-29 15:00:51 +08001198bool ValidateInvalidateFramebuffer(Context *context,
1199 GLenum target,
1200 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001201 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202{
Martin Radev1be913c2016-07-11 17:59:16 +03001203 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001206 return false;
1207 }
1208
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001209 bool defaultFramebuffer = false;
1210
1211 switch (target)
1212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 case GL_DRAW_FRAMEBUFFER:
1214 case GL_FRAMEBUFFER:
1215 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1216 break;
1217 case GL_READ_FRAMEBUFFER:
1218 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1219 break;
1220 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1226 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227}
1228
Jamie Madill3ef140a2017-08-26 23:11:21 -04001229bool ValidateInvalidateSubFramebuffer(Context *context,
1230 GLenum target,
1231 GLsizei numAttachments,
1232 const GLenum *attachments,
1233 GLint x,
1234 GLint y,
1235 GLsizei width,
1236 GLsizei height)
1237{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001238 if (width < 0 || height < 0)
1239 {
1240 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1241 return false;
1242 }
1243
Jamie Madill3ef140a2017-08-26 23:11:21 -04001244 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1245}
1246
Jamie Madill5b772312018-03-08 20:28:32 -05001247bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001248{
Martin Radev1be913c2016-07-11 17:59:16 +03001249 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001253 }
1254
Jamie Madill427064d2018-04-13 16:20:34 -04001255 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001256 {
Geoff Langb1196682014-07-23 13:47:29 -04001257 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001258 }
1259
1260 return true;
1261}
1262
Olli Etuaho71dfb362016-03-10 14:04:27 +02001263bool ValidateDrawRangeElements(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001264 PrimitiveMode mode,
Olli Etuaho71dfb362016-03-10 14:04:27 +02001265 GLuint start,
1266 GLuint end,
1267 GLsizei count,
1268 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001269 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001270{
Martin Radev1be913c2016-07-11 17:59:16 +03001271 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001272 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001274 return false;
1275 }
1276
1277 if (end < start)
1278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001280 return false;
1281 }
1282
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001283 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001284 {
1285 return false;
1286 }
1287
Jamie Madill9fdaa492018-02-16 10:52:11 -05001288 // Skip range checks for no-op calls.
1289 if (count <= 0)
1290 {
1291 return true;
1292 }
1293
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001294 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04001295 const DrawCallParams &params = context->getParams<DrawCallParams>();
1296 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001297
Jamie Madill6f5444d2018-03-14 10:08:11 -04001298 const IndexRange &indexRange = params.getIndexRange();
1299
1300 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001301 {
1302 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001304 return false;
1305 }
1306 return true;
1307}
1308
He Yunchaoced53ae2016-11-29 15:00:51 +08001309bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001310{
Martin Radev1be913c2016-07-11 17:59:16 +03001311 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001312 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001315 }
1316
Jamie Madill78f41802014-08-25 15:47:55 -04001317 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001318}
1319
Jamie Madillb885e572015-02-03 16:16:04 -05001320bool ValidateReadBuffer(Context *context, GLenum src)
1321{
Martin Radev1be913c2016-07-11 17:59:16 +03001322 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001323 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001325 return false;
1326 }
1327
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001328 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001329
1330 if (readFBO == nullptr)
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001333 return false;
1334 }
1335
1336 if (src == GL_NONE)
1337 {
1338 return true;
1339 }
1340
Olli Etuaho84c9f592016-03-09 14:37:25 +02001341 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001344 return false;
1345 }
1346
1347 if (readFBO->id() == 0)
1348 {
1349 if (src != GL_BACK)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(
1352 InvalidOperation()
1353 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001354 return false;
1355 }
1356 }
1357 else
1358 {
1359 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1360
1361 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001364 return false;
1365 }
1366 }
1367
1368 return true;
1369}
1370
Jamie Madill86af3d22015-07-21 15:14:07 -04001371bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001372 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001373 GLint level,
1374 GLenum internalformat,
1375 GLsizei width,
1376 GLsizei height,
1377 GLsizei depth,
1378 GLint border,
1379 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001380 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001381{
Martin Radev1be913c2016-07-11 17:59:16 +03001382 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001384 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001385 return false;
1386 }
1387
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001388 if (!ValidTextureTarget(context, target))
1389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001391 return false;
1392 }
1393
Jamie Madille2e406c2016-06-02 13:04:10 -04001394 // Validate image size
1395 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001398 return false;
1399 }
1400
Geoff Langca271392017-04-05 12:30:00 -04001401 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001402 if (!formatInfo.compressed)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001405 return false;
1406 }
1407
Jeff Gilbert48590352017-11-07 16:03:38 -08001408 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001409 if (blockSizeOrErr.isError())
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001412 return false;
1413 }
1414 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001417 return false;
1418 }
1419
1420 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001421 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001424 return false;
1425 }
1426
1427 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001428 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001429 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1430 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001431 {
1432 return false;
1433 }
1434
1435 return true;
1436}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001437
Corentin Wallezb2931602017-04-11 15:58:57 -04001438bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001439 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001440 GLint level,
1441 GLenum internalformat,
1442 GLsizei width,
1443 GLsizei height,
1444 GLsizei depth,
1445 GLint border,
1446 GLsizei imageSize,
1447 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001448 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001449{
1450 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1451 {
1452 return false;
1453 }
1454
1455 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1456 depth, border, imageSize, data);
1457}
1458
Austin Kinrossbc781f32015-10-26 09:27:38 -07001459bool ValidateBindVertexArray(Context *context, GLuint array)
1460{
Martin Radev1be913c2016-07-11 17:59:16 +03001461 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001462 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001464 return false;
1465 }
1466
1467 return ValidateBindVertexArrayBase(context, array);
1468}
1469
Jamie Madilld7576732017-08-26 18:49:50 -04001470bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001471{
Martin Radev1be913c2016-07-11 17:59:16 +03001472 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001473 {
Jamie Madilld7576732017-08-26 18:49:50 -04001474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001475 return false;
1476 }
1477
1478 return true;
1479}
Geoff Langc5629752015-12-07 16:29:04 -05001480
Jiajia Qin6eafb042016-12-27 17:04:07 +08001481static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001482 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001483 GLuint index,
1484 GLuint buffer,
1485 GLintptr offset,
1486 GLsizeiptr size)
1487{
1488 if (context->getClientMajorVersion() < 3)
1489 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001491 return false;
1492 }
1493
1494 if (buffer != 0 && offset < 0)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001497 return false;
1498 }
1499
1500 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1501 !context->isBufferGenerated(buffer))
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 return false;
1505 }
1506
1507 const Caps &caps = context->getCaps();
1508 switch (target)
1509 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001510 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001511 {
1512 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidValue() << "index is greater than or equal to the "
1515 "number of TRANSFORM_FEEDBACK_BUFFER "
1516 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001517 return false;
1518 }
1519 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001522 return false;
1523 }
1524
1525 TransformFeedback *curTransformFeedback =
1526 context->getGLState().getCurrentTransformFeedback();
1527 if (curTransformFeedback && curTransformFeedback->isActive())
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation()
1530 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1531 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 return false;
1533 }
1534 break;
1535 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001536 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001537 {
1538 if (index >= caps.maxUniformBufferBindings)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidValue() << "index is greater than or equal to the "
1541 "number of UNIFORM_BUFFER indexed "
1542 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001543 return false;
1544 }
1545
1546 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1547 {
1548 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001549 InvalidValue()
1550 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001551 return false;
1552 }
1553 break;
1554 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001555 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001556 {
1557 if (context->getClientVersion() < ES_3_1)
1558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001559 context->handleError(InvalidEnum()
1560 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001561 return false;
1562 }
1563 if (index >= caps.maxAtomicCounterBufferBindings)
1564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001565 context->handleError(InvalidValue() << "index is greater than or equal to the "
1566 "number of ATOMIC_COUNTER_BUFFER "
1567 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001568 return false;
1569 }
1570 if (buffer != 0 && (offset % 4) != 0)
1571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001572 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001573 return false;
1574 }
1575 break;
1576 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001577 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001578 {
1579 if (context->getClientVersion() < ES_3_1)
1580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001581 context->handleError(InvalidEnum()
1582 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001583 return false;
1584 }
1585 if (index >= caps.maxShaderStorageBufferBindings)
1586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidValue() << "index is greater than or equal to the "
1588 "number of SHADER_STORAGE_BUFFER "
1589 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001590 return false;
1591 }
1592 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidValue() << "offset must be multiple of value of "
1595 "SHADER_STORAGE_BUFFER_OFFSET_"
1596 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001597 return false;
1598 }
1599 break;
1600 }
1601 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001602 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001603 return false;
1604 }
1605
1606 return true;
1607}
1608
Corentin Wallez336129f2017-10-17 15:55:40 -04001609bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001610{
1611 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1612}
1613
1614bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001615 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001616 GLuint index,
1617 GLuint buffer,
1618 GLintptr offset,
1619 GLsizeiptr size)
1620{
1621 if (buffer != 0 && size <= 0)
1622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001623 context->handleError(InvalidValue()
1624 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001625 return false;
1626 }
1627 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1628}
1629
Geoff Langc5629752015-12-07 16:29:04 -05001630bool ValidateProgramBinary(Context *context,
1631 GLuint program,
1632 GLenum binaryFormat,
1633 const void *binary,
1634 GLint length)
1635{
Martin Radev1be913c2016-07-11 17:59:16 +03001636 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001637 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001639 return false;
1640 }
1641
1642 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1643}
1644
1645bool ValidateGetProgramBinary(Context *context,
1646 GLuint program,
1647 GLsizei bufSize,
1648 GLsizei *length,
1649 GLenum *binaryFormat,
1650 void *binary)
1651{
Martin Radev1be913c2016-07-11 17:59:16 +03001652 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001653 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001655 return false;
1656 }
1657
1658 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1659}
1660
Olli Etuahof0fee072016-03-30 15:11:58 +03001661bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001662{
Martin Radev1be913c2016-07-11 17:59:16 +03001663 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001664 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001666 return false;
1667 }
1668
1669 if (GetValidProgram(context, program) == nullptr)
1670 {
1671 return false;
1672 }
1673
1674 switch (pname)
1675 {
1676 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001677 if (value != GL_FALSE && value != GL_TRUE)
1678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001679 context->handleError(InvalidValue()
1680 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001681 return false;
1682 }
Geoff Langc5629752015-12-07 16:29:04 -05001683 break;
1684
Yunchao He61afff12017-03-14 15:34:03 +08001685 case GL_PROGRAM_SEPARABLE:
1686 if (context->getClientVersion() < ES_3_1)
1687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(InvalidEnum()
1689 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001690 return false;
1691 }
1692
1693 if (value != GL_FALSE && value != GL_TRUE)
1694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001695 context->handleError(InvalidValue()
1696 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001697 return false;
1698 }
1699 break;
1700
Geoff Langc5629752015-12-07 16:29:04 -05001701 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(InvalidEnum()
1703 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001704 return false;
1705 }
1706
1707 return true;
1708}
Jamie Madillc29968b2016-01-20 11:17:23 -05001709
1710bool ValidateBlitFramebuffer(Context *context,
1711 GLint srcX0,
1712 GLint srcY0,
1713 GLint srcX1,
1714 GLint srcY1,
1715 GLint dstX0,
1716 GLint dstY0,
1717 GLint dstX1,
1718 GLint dstY1,
1719 GLbitfield mask,
1720 GLenum filter)
1721{
Martin Radev1be913c2016-07-11 17:59:16 +03001722 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
1727
1728 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1729 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001730}
Jamie Madillc29968b2016-01-20 11:17:23 -05001731
Jamie Madill5b772312018-03-08 20:28:32 -05001732bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001733{
1734 switch (buffer)
1735 {
1736 case GL_COLOR:
1737 if (drawbuffer < 0 ||
1738 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001741 return false;
1742 }
Geoff Lang76e65652017-03-27 14:58:02 -04001743 if (context->getExtensions().webglCompatibility)
1744 {
1745 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001746 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001747 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1748 {
1749 return false;
1750 }
1751 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001752 break;
1753
1754 case GL_STENCIL:
1755 if (drawbuffer != 0)
1756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001757 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001758 return false;
1759 }
1760 break;
1761
1762 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001763 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001764 return false;
1765 }
1766
1767 return ValidateClearBuffer(context);
1768}
1769
Jamie Madill5b772312018-03-08 20:28:32 -05001770bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001771{
1772 switch (buffer)
1773 {
1774 case GL_COLOR:
1775 if (drawbuffer < 0 ||
1776 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001778 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 return false;
1780 }
Geoff Lang76e65652017-03-27 14:58:02 -04001781 if (context->getExtensions().webglCompatibility)
1782 {
1783 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001784 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001785 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1786 {
1787 return false;
1788 }
1789 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001790 break;
1791
1792 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001794 return false;
1795 }
1796
1797 return ValidateClearBuffer(context);
1798}
1799
Jamie Madill5b772312018-03-08 20:28:32 -05001800bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001801{
1802 switch (buffer)
1803 {
1804 case GL_COLOR:
1805 if (drawbuffer < 0 ||
1806 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001809 return false;
1810 }
Geoff Lang76e65652017-03-27 14:58:02 -04001811 if (context->getExtensions().webglCompatibility)
1812 {
1813 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1814 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001815 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001816 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1817 {
1818 return false;
1819 }
1820 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001821 break;
1822
1823 case GL_DEPTH:
1824 if (drawbuffer != 0)
1825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001826 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001827 return false;
1828 }
1829 break;
1830
1831 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001832 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001833 return false;
1834 }
1835
1836 return ValidateClearBuffer(context);
1837}
1838
Jamie Madill5b772312018-03-08 20:28:32 -05001839bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 GLenum buffer,
1841 GLint drawbuffer,
1842 GLfloat depth,
1843 GLint stencil)
1844{
1845 switch (buffer)
1846 {
1847 case GL_DEPTH_STENCIL:
1848 if (drawbuffer != 0)
1849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001850 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 return false;
1852 }
1853 break;
1854
1855 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001856 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001857 return false;
1858 }
1859
1860 return ValidateClearBuffer(context);
1861}
1862
Jamie Madill5b772312018-03-08 20:28:32 -05001863bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001864{
Martin Radev1be913c2016-07-11 17:59:16 +03001865 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001866 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001868 return false;
1869 }
1870
1871 return ValidateDrawBuffersBase(context, n, bufs);
1872}
1873
1874bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001875 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 GLint level,
1877 GLint xoffset,
1878 GLint yoffset,
1879 GLint zoffset,
1880 GLint x,
1881 GLint y,
1882 GLsizei width,
1883 GLsizei height)
1884{
Martin Radev1be913c2016-07-11 17:59:16 +03001885 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001887 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 return false;
1889 }
1890
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001891 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1892 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001893}
1894
Jamie Madill73a84962016-02-12 09:27:23 -05001895bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001896 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001897 GLint level,
1898 GLint internalformat,
1899 GLsizei width,
1900 GLsizei height,
1901 GLsizei depth,
1902 GLint border,
1903 GLenum format,
1904 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001905 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001906{
Martin Radev1be913c2016-07-11 17:59:16 +03001907 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001908 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001910 return false;
1911 }
1912
1913 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001914 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001915 pixels);
1916}
1917
Geoff Langc52f6f12016-10-14 10:18:00 -04001918bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001919 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001920 GLint level,
1921 GLint internalformat,
1922 GLsizei width,
1923 GLsizei height,
1924 GLsizei depth,
1925 GLint border,
1926 GLenum format,
1927 GLenum type,
1928 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001929 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001930{
1931 if (context->getClientMajorVersion() < 3)
1932 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001934 return false;
1935 }
1936
1937 if (!ValidateRobustEntryPoint(context, bufSize))
1938 {
1939 return false;
1940 }
1941
1942 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1943 0, 0, width, height, depth, border, format, type,
1944 bufSize, pixels);
1945}
1946
Jamie Madill73a84962016-02-12 09:27:23 -05001947bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001948 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001949 GLint level,
1950 GLint xoffset,
1951 GLint yoffset,
1952 GLint zoffset,
1953 GLsizei width,
1954 GLsizei height,
1955 GLsizei depth,
1956 GLenum format,
1957 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001958 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001959{
Martin Radev1be913c2016-07-11 17:59:16 +03001960 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001961 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001962 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001963 return false;
1964 }
1965
1966 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1967 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001968 -1, pixels);
1969}
1970
1971bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001972 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001973 GLint level,
1974 GLint xoffset,
1975 GLint yoffset,
1976 GLint zoffset,
1977 GLsizei width,
1978 GLsizei height,
1979 GLsizei depth,
1980 GLenum format,
1981 GLenum type,
1982 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001983 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001984{
1985 if (context->getClientMajorVersion() < 3)
1986 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001988 return false;
1989 }
1990
1991 if (!ValidateRobustEntryPoint(context, bufSize))
1992 {
1993 return false;
1994 }
1995
1996 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1997 yoffset, zoffset, width, height, depth, 0, format, type,
1998 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001999}
2000
2001bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002002 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002003 GLint level,
2004 GLint xoffset,
2005 GLint yoffset,
2006 GLint zoffset,
2007 GLsizei width,
2008 GLsizei height,
2009 GLsizei depth,
2010 GLenum format,
2011 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002012 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002013{
Martin Radev1be913c2016-07-11 17:59:16 +03002014 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002015 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002016 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002017 return false;
2018 }
2019
Geoff Langca271392017-04-05 12:30:00 -04002020 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002021 if (!formatInfo.compressed)
2022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002023 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002024 return false;
2025 }
2026
Jeff Gilbert48590352017-11-07 16:03:38 -08002027 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002028 if (blockSizeOrErr.isError())
2029 {
2030 context->handleError(blockSizeOrErr.getError());
2031 return false;
2032 }
2033 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002035 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002036 return false;
2037 }
2038
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002039 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2040 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2041 -1, data))
2042 {
2043 return false;
2044 }
2045
Jamie Madill73a84962016-02-12 09:27:23 -05002046 if (!data)
2047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002048 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002049 return false;
2050 }
2051
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002052 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002053}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002054
Corentin Wallezb2931602017-04-11 15:58:57 -04002055bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002056 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002057 GLint level,
2058 GLint xoffset,
2059 GLint yoffset,
2060 GLint zoffset,
2061 GLsizei width,
2062 GLsizei height,
2063 GLsizei depth,
2064 GLenum format,
2065 GLsizei imageSize,
2066 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002067 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002068{
2069 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2070 {
2071 return false;
2072 }
2073
2074 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2075 height, depth, format, imageSize, data);
2076}
Jamie Madill73a84962016-02-12 09:27:23 -05002077
Olli Etuaho41997e72016-03-10 13:38:39 +02002078bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2079{
2080 return ValidateGenOrDeleteES3(context, n);
2081}
2082
2083bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2084{
2085 return ValidateGenOrDeleteES3(context, n);
2086}
2087
2088bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2089{
2090 return ValidateGenOrDeleteCountES3(context, count);
2091}
2092
2093bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2094{
2095 return ValidateGenOrDeleteCountES3(context, count);
2096}
2097
2098bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2099{
2100 return ValidateGenOrDeleteES3(context, n);
2101}
2102
2103bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2104{
2105 if (!ValidateGenOrDeleteES3(context, n))
2106 {
2107 return false;
2108 }
2109 for (GLint i = 0; i < n; ++i)
2110 {
2111 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2112 if (transformFeedback != nullptr && transformFeedback->isActive())
2113 {
2114 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002115 context->handleError(InvalidOperation()
2116 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002117 return false;
2118 }
2119 }
2120 return true;
2121}
2122
2123bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2124{
2125 return ValidateGenOrDeleteES3(context, n);
2126}
2127
2128bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2129{
2130 return ValidateGenOrDeleteES3(context, n);
2131}
2132
Jamie Madill493f9572018-05-24 19:52:15 -04002133bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMode)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002134{
Martin Radev1be913c2016-07-11 17:59:16 +03002135 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002136 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002138 return false;
2139 }
2140 switch (primitiveMode)
2141 {
Jamie Madill493f9572018-05-24 19:52:15 -04002142 case PrimitiveMode::Triangles:
2143 case PrimitiveMode::Lines:
2144 case PrimitiveMode::Points:
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002145 break;
2146
2147 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002148 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002149 return false;
2150 }
2151
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002152 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002153 ASSERT(transformFeedback != nullptr);
2154
2155 if (transformFeedback->isActive())
2156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002157 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002158 return false;
2159 }
Geoff Lang79f71042017-08-14 16:43:43 -04002160
2161 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2162 {
2163 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2164 if (buffer.get() && buffer->isMapped())
2165 {
2166 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2167 return false;
2168 }
2169 }
2170
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002171 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002172
2173 if (!program)
2174 {
2175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2176 return false;
2177 }
2178
2179 if (program->getTransformFeedbackVaryingCount() == 0)
2180 {
2181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2182 return false;
2183 }
2184
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002185 return true;
2186}
2187
Corentin Wallez336129f2017-10-17 15:55:40 -04002188bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002189{
Geoff Lang496c02d2016-10-20 11:38:11 -07002190 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2191}
2192
2193bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002194 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002195 GLenum pname,
2196 GLsizei bufSize,
2197 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002198 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002199{
2200 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002201 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002202 return false;
2203 }
2204
Brandon Jonesd1049182018-03-28 10:02:20 -07002205 GLsizei numParams = 0;
2206
2207 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002208 {
2209 return false;
2210 }
2211
Brandon Jonesd1049182018-03-28 10:02:20 -07002212 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002213 {
2214 return false;
2215 }
2216
Brandon Jonesd1049182018-03-28 10:02:20 -07002217 SetRobustLengthParam(length, numParams);
2218
Geoff Lang496c02d2016-10-20 11:38:11 -07002219 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002220}
2221
Corentin Wallez336129f2017-10-17 15:55:40 -04002222bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002223{
Martin Radev1be913c2016-07-11 17:59:16 +03002224 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002225 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002227 return false;
2228 }
2229
2230 return ValidateUnmapBufferBase(context, target);
2231}
2232
2233bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002234 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002235 GLintptr offset,
2236 GLsizeiptr length,
2237 GLbitfield access)
2238{
Martin Radev1be913c2016-07-11 17:59:16 +03002239 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002240 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002242 return false;
2243 }
2244
2245 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2246}
2247
2248bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002249 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002250 GLintptr offset,
2251 GLsizeiptr length)
2252{
Martin Radev1be913c2016-07-11 17:59:16 +03002253 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002254 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002256 return false;
2257 }
2258
2259 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2260}
2261
Jamie Madill5b772312018-03-08 20:28:32 -05002262bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002263{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002264 if (length)
2265 {
2266 *length = 0;
2267 }
2268
Martin Radev66fb8202016-07-28 11:45:20 +03002269 GLenum nativeType;
2270 unsigned int numParams;
2271 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002273 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002274 return false;
2275 }
2276
2277 const Caps &caps = context->getCaps();
2278 switch (pname)
2279 {
2280 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2281 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2282 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2283 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002285 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002286 return false;
2287 }
2288 break;
2289
2290 case GL_UNIFORM_BUFFER_START:
2291 case GL_UNIFORM_BUFFER_SIZE:
2292 case GL_UNIFORM_BUFFER_BINDING:
2293 if (index >= caps.maxUniformBufferBindings)
2294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002295 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002296 return false;
2297 }
2298 break;
Shao80957d92017-02-20 21:25:59 +08002299
Martin Radev66fb8202016-07-28 11:45:20 +03002300 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2301 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2302 if (index >= 3u)
2303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002304 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002305 return false;
2306 }
2307 break;
Shao80957d92017-02-20 21:25:59 +08002308
Jiajia Qin6eafb042016-12-27 17:04:07 +08002309 case GL_ATOMIC_COUNTER_BUFFER_START:
2310 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2311 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2312 if (context->getClientVersion() < ES_3_1)
2313 {
2314 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002315 InvalidEnum()
2316 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002317 return false;
2318 }
2319 if (index >= caps.maxAtomicCounterBufferBindings)
2320 {
2321 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002322 InvalidValue()
2323 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002324 return false;
2325 }
2326 break;
Shao80957d92017-02-20 21:25:59 +08002327
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002328 case GL_SHADER_STORAGE_BUFFER_START:
2329 case GL_SHADER_STORAGE_BUFFER_SIZE:
2330 case GL_SHADER_STORAGE_BUFFER_BINDING:
2331 if (context->getClientVersion() < ES_3_1)
2332 {
2333 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002334 InvalidEnum()
2335 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002336 return false;
2337 }
2338 if (index >= caps.maxShaderStorageBufferBindings)
2339 {
2340 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002341 InvalidValue()
2342 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002343 return false;
2344 }
2345 break;
2346
Shao80957d92017-02-20 21:25:59 +08002347 case GL_VERTEX_BINDING_BUFFER:
2348 case GL_VERTEX_BINDING_DIVISOR:
2349 case GL_VERTEX_BINDING_OFFSET:
2350 case GL_VERTEX_BINDING_STRIDE:
2351 if (context->getClientVersion() < ES_3_1)
2352 {
2353 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002354 InvalidEnum()
2355 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002356 return false;
2357 }
2358 if (index >= caps.maxVertexAttribBindings)
2359 {
2360 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002361 InvalidValue()
2362 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002363 return false;
2364 }
2365 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002366 case GL_SAMPLE_MASK_VALUE:
2367 if (context->getClientVersion() < ES_3_1)
2368 {
2369 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2370 return false;
2371 }
2372 if (index >= caps.maxSampleMaskWords)
2373 {
2374 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2375 return false;
2376 }
2377 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002378 case GL_IMAGE_BINDING_NAME:
2379 case GL_IMAGE_BINDING_LEVEL:
2380 case GL_IMAGE_BINDING_LAYERED:
2381 case GL_IMAGE_BINDING_LAYER:
2382 case GL_IMAGE_BINDING_ACCESS:
2383 case GL_IMAGE_BINDING_FORMAT:
2384 if (context->getClientVersion() < ES_3_1)
2385 {
2386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2387 return false;
2388 }
2389 if (index >= caps.maxImageUnits)
2390 {
2391 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2392 return false;
2393 }
2394 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002395 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002397 return false;
2398 }
2399
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002400 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002401 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002402 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002403 }
2404
2405 return true;
2406}
2407
Jamie Madill5b772312018-03-08 20:28:32 -05002408bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002409{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002410 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002412 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002413 return false;
2414 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002415 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002416}
2417
Jamie Madill5b772312018-03-08 20:28:32 -05002418bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002419 GLenum target,
2420 GLuint index,
2421 GLsizei bufSize,
2422 GLsizei *length,
2423 GLint *data)
2424{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002425 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002426 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002427 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002428 return false;
2429 }
2430
2431 if (!ValidateRobustEntryPoint(context, bufSize))
2432 {
2433 return false;
2434 }
2435
Brandon Jonesd1049182018-03-28 10:02:20 -07002436 GLsizei numParams = 0;
2437
2438 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002439 {
2440 return false;
2441 }
2442
Brandon Jonesd1049182018-03-28 10:02:20 -07002443 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002444 {
2445 return false;
2446 }
2447
Brandon Jonesd1049182018-03-28 10:02:20 -07002448 SetRobustLengthParam(length, numParams);
2449
Geoff Langcf255ea2016-10-20 11:39:09 -07002450 return true;
2451}
2452
Jamie Madill5b772312018-03-08 20:28:32 -05002453bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002454{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002455 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002458 return false;
2459 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002460 return ValidateIndexedStateQuery(context, target, index, nullptr);
2461}
2462
Jamie Madill5b772312018-03-08 20:28:32 -05002463bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002464 GLenum target,
2465 GLuint index,
2466 GLsizei bufSize,
2467 GLsizei *length,
2468 GLint64 *data)
2469{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002470 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002471 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002473 return false;
2474 }
2475
2476 if (!ValidateRobustEntryPoint(context, bufSize))
2477 {
2478 return false;
2479 }
2480
Brandon Jonesd1049182018-03-28 10:02:20 -07002481 GLsizei numParams = 0;
2482
2483 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002484 {
2485 return false;
2486 }
2487
Brandon Jonesd1049182018-03-28 10:02:20 -07002488 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002489 {
2490 return false;
2491 }
2492
Brandon Jonesd1049182018-03-28 10:02:20 -07002493 SetRobustLengthParam(length, numParams);
2494
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002495 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002496}
2497
Jamie Madill5b772312018-03-08 20:28:32 -05002498bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002499 BufferBinding readTarget,
2500 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002501 GLintptr readOffset,
2502 GLintptr writeOffset,
2503 GLsizeiptr size)
2504{
2505 if (context->getClientMajorVersion() < 3)
2506 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002508 return false;
2509 }
2510
Corentin Walleze4477002017-12-01 14:39:58 -05002511 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002514 return false;
2515 }
2516
2517 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2518 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2519
2520 if (!readBuffer || !writeBuffer)
2521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002523 return false;
2524 }
2525
2526 // Verify that readBuffer and writeBuffer are not currently mapped
2527 if (readBuffer->isMapped() || writeBuffer->isMapped())
2528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidOperation()
2530 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002531 return false;
2532 }
2533
James Darpiniane8a93c62018-01-04 18:02:24 -08002534 if (context->getExtensions().webglCompatibility &&
2535 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2536 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2537 {
2538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2539 return false;
2540 }
2541
Jamie Madilld2f0c742016-11-02 10:34:41 -04002542 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2543 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2544 CheckedNumeric<GLintptr> checkedSize(size);
2545
2546 auto checkedReadSum = checkedReadOffset + checkedSize;
2547 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2548
2549 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2550 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2551 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002553 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002554 return false;
2555 }
2556
Jamie Madilld2f0c742016-11-02 10:34:41 -04002557 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidValue()
2560 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002561 return false;
2562 }
2563
Jamie Madilld2f0c742016-11-02 10:34:41 -04002564 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2565 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002567 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002568 return false;
2569 }
2570
2571 if (readBuffer == writeBuffer)
2572 {
2573 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2574 if (!checkedOffsetDiff.IsValid())
2575 {
2576 // This shold not be possible.
2577 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002578 context->handleError(InvalidValue()
2579 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002580 return false;
2581 }
2582
2583 if (checkedOffsetDiff.ValueOrDie() < size)
2584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002585 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002586 return false;
2587 }
2588 }
2589
Jamie Madillb0817d12016-11-01 15:48:31 -04002590 return true;
2591}
2592
Geoff Langc339c4e2016-11-29 10:37:36 -05002593bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2594{
2595 if (context->getClientMajorVersion() < 3)
2596 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002598 return false;
2599 }
2600
2601 switch (name)
2602 {
2603 case GL_EXTENSIONS:
2604 if (index >= context->getExtensionStringCount())
2605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002606 context->handleError(InvalidValue()
2607 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002608 return false;
2609 }
2610 break;
2611
2612 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2613 if (!context->getExtensions().requestExtension)
2614 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002616 return false;
2617 }
2618 if (index >= context->getRequestableExtensionStringCount())
2619 {
2620 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002621 InvalidValue()
2622 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002623 return false;
2624 }
2625 break;
2626
2627 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002628 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002629 return false;
2630 }
2631
2632 return true;
2633}
2634
Jamie Madill5b772312018-03-08 20:28:32 -05002635bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002636 GLenum target,
2637 GLsizei samples,
2638 GLenum internalformat,
2639 GLsizei width,
2640 GLsizei height)
2641{
2642 if (context->getClientMajorVersion() < 3)
2643 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002645 return false;
2646 }
2647
2648 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2649 height))
2650 {
2651 return false;
2652 }
2653
2654 // 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 +08002655 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2656 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002657 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002658 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002659 {
Yunchao Hec0810202018-01-22 09:48:48 +08002660 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2661 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2662 {
2663 context->handleError(InvalidOperation());
2664 return false;
2665 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002666 }
2667
2668 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2669 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2670 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2671 {
2672 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002673 InvalidOperation()
2674 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002675 return false;
2676 }
2677
2678 return true;
2679}
2680
Jamie Madill5b772312018-03-08 20:28:32 -05002681bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002682 GLuint index,
2683 GLint size,
2684 GLenum type,
2685 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002686 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002687{
2688 if (context->getClientMajorVersion() < 3)
2689 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002690 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002691 return false;
2692 }
2693
Shao80957d92017-02-20 21:25:59 +08002694 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002695 {
Geoff Langaa086d62017-03-23 16:47:21 -04002696 return false;
2697 }
2698
Geoff Langaa086d62017-03-23 16:47:21 -04002699 if (stride < 0)
2700 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002701 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002702 return false;
2703 }
2704
Shao80957d92017-02-20 21:25:59 +08002705 const Caps &caps = context->getCaps();
2706 if (context->getClientVersion() >= ES_3_1)
2707 {
2708 if (stride > caps.maxVertexAttribStride)
2709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002710 context->handleError(InvalidValue()
2711 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002712 return false;
2713 }
2714
2715 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2716 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2717 // validation should be inherited.
2718 if (index >= caps.maxVertexAttribBindings)
2719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002720 context->handleError(InvalidValue()
2721 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002722 return false;
2723 }
2724 }
2725
Geoff Langaa086d62017-03-23 16:47:21 -04002726 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2727 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2728 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2729 // and the pointer argument is not NULL.
2730 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002731 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002733 context
2734 ->handleError(InvalidOperation()
2735 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002736 return false;
2737 }
2738
Geoff Lang2d62ab72017-03-23 16:54:40 -04002739 if (context->getExtensions().webglCompatibility)
2740 {
2741 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2742 {
2743 return false;
2744 }
2745 }
2746
Geoff Langaa086d62017-03-23 16:47:21 -04002747 return true;
2748}
2749
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002750bool ValidateGetSynciv(Context *context,
2751 GLsync sync,
2752 GLenum pname,
2753 GLsizei bufSize,
2754 GLsizei *length,
2755 GLint *values)
2756{
2757 if (context->getClientMajorVersion() < 3)
2758 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002759 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002760 return false;
2761 }
2762
2763 if (bufSize < 0)
2764 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002765 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002766 return false;
2767 }
2768
Jamie Madill70b5bb02017-08-28 13:32:37 -04002769 Sync *syncObject = context->getSync(sync);
2770 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002772 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002773 return false;
2774 }
2775
2776 switch (pname)
2777 {
2778 case GL_OBJECT_TYPE:
2779 case GL_SYNC_CONDITION:
2780 case GL_SYNC_FLAGS:
2781 case GL_SYNC_STATUS:
2782 break;
2783
2784 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002786 return false;
2787 }
2788
2789 return true;
2790}
2791
Jamie Madill5b772312018-03-08 20:28:32 -05002792bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002793 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002794 GLsizei count,
2795 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002796 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002797 GLsizei instanceCount)
2798{
2799 if (context->getClientMajorVersion() < 3)
2800 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002802 return false;
2803 }
2804
2805 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2806}
2807
Martin Radev137032d2017-07-13 10:11:12 +03002808bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2809 GLenum target,
2810 GLenum attachment,
2811 GLuint texture,
2812 GLint level,
2813 GLint baseViewIndex,
2814 GLsizei numViews)
2815{
2816
2817 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2818 numViews))
2819 {
2820 return false;
2821 }
2822
Martin Radev137032d2017-07-13 10:11:12 +03002823 if (texture != 0)
2824 {
Martin Radev14b21262017-08-25 13:54:37 +03002825 if (baseViewIndex < 0)
2826 {
2827 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2828 return false;
2829 }
2830
Martin Radev137032d2017-07-13 10:11:12 +03002831 Texture *tex = context->getTexture(texture);
2832 ASSERT(tex);
2833
Corentin Wallez99d492c2018-02-27 15:17:10 -05002834 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002835 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002836 case TextureType::_2DArray:
Martin Radev137032d2017-07-13 10:11:12 +03002837 {
2838 const Caps &caps = context->getCaps();
2839 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2840 {
2841 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2842 "greater than "
2843 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2844 return false;
2845 }
2846 }
2847 break;
2848 default:
2849 context->handleError(InvalidOperation()
2850 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2851 return false;
2852 }
2853
2854 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2855 {
2856 return false;
2857 }
2858 }
2859
2860 return true;
2861}
2862
2863bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2864 GLenum target,
2865 GLenum attachment,
2866 GLuint texture,
2867 GLint level,
2868 GLsizei numViews,
2869 const GLint *viewportOffsets)
2870{
2871 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2872 numViews))
2873 {
2874 return false;
2875 }
2876
Martin Radev137032d2017-07-13 10:11:12 +03002877 if (texture != 0)
2878 {
Martin Radev14b21262017-08-25 13:54:37 +03002879 const GLsizei numViewportOffsetValues = numViews * 2;
2880 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2881 {
2882 if (viewportOffsets[i] < 0)
2883 {
2884 context->handleError(InvalidValue()
2885 << "viewportOffsets cannot contain negative values.");
2886 return false;
2887 }
2888 }
2889
Martin Radev137032d2017-07-13 10:11:12 +03002890 Texture *tex = context->getTexture(texture);
2891 ASSERT(tex);
2892
Corentin Wallez99d492c2018-02-27 15:17:10 -05002893 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002894 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002895 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002896 break;
2897 default:
2898 context->handleError(InvalidOperation()
2899 << "Texture's target must be GL_TEXTURE_2D.");
2900 return false;
2901 }
2902
2903 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2904 {
2905 return false;
2906 }
2907 }
2908
2909 return true;
2910}
2911
Jamie Madillff325f12017-08-26 15:06:05 -04002912bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2913{
2914 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2915}
2916
2917bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2918{
2919 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2920}
2921
2922bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2923{
2924 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2925}
2926
2927bool ValidateUniform4ui(Context *context,
2928 GLint location,
2929 GLuint v0,
2930 GLuint v1,
2931 GLuint v2,
2932 GLuint v3)
2933{
2934 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2935}
2936
2937bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2938{
2939 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2940}
2941
2942bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2943{
2944 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2945}
2946
2947bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2948{
2949 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2950}
2951
2952bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2953{
2954 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2955}
2956
Jamie Madillf0e04492017-08-26 15:28:42 -04002957bool ValidateIsQuery(Context *context, GLuint id)
2958{
2959 if (context->getClientMajorVersion() < 3)
2960 {
2961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2962 return false;
2963 }
2964
2965 return true;
2966}
2967
Jamie Madillc8c95812017-08-26 18:40:09 -04002968bool ValidateUniformMatrix2x3fv(Context *context,
2969 GLint location,
2970 GLsizei count,
2971 GLboolean transpose,
2972 const GLfloat *value)
2973{
2974 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2975}
2976
2977bool ValidateUniformMatrix3x2fv(Context *context,
2978 GLint location,
2979 GLsizei count,
2980 GLboolean transpose,
2981 const GLfloat *value)
2982{
2983 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2984}
2985
2986bool ValidateUniformMatrix2x4fv(Context *context,
2987 GLint location,
2988 GLsizei count,
2989 GLboolean transpose,
2990 const GLfloat *value)
2991{
2992 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2993}
2994
2995bool ValidateUniformMatrix4x2fv(Context *context,
2996 GLint location,
2997 GLsizei count,
2998 GLboolean transpose,
2999 const GLfloat *value)
3000{
3001 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3002}
3003
3004bool ValidateUniformMatrix3x4fv(Context *context,
3005 GLint location,
3006 GLsizei count,
3007 GLboolean transpose,
3008 const GLfloat *value)
3009{
3010 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3011}
3012
3013bool ValidateUniformMatrix4x3fv(Context *context,
3014 GLint location,
3015 GLsizei count,
3016 GLboolean transpose,
3017 const GLfloat *value)
3018{
3019 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3020}
3021
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003022bool ValidateEndTransformFeedback(Context *context)
3023{
3024 if (context->getClientMajorVersion() < 3)
3025 {
3026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3027 return false;
3028 }
3029
3030 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3031 ASSERT(transformFeedback != nullptr);
3032
3033 if (!transformFeedback->isActive())
3034 {
3035 context->handleError(InvalidOperation());
3036 return false;
3037 }
3038
3039 return true;
3040}
3041
3042bool ValidateTransformFeedbackVaryings(Context *context,
3043 GLuint program,
3044 GLsizei count,
3045 const GLchar *const *varyings,
3046 GLenum bufferMode)
3047{
3048 if (context->getClientMajorVersion() < 3)
3049 {
3050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3051 return false;
3052 }
3053
3054 if (count < 0)
3055 {
3056 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3057 return false;
3058 }
3059
3060 switch (bufferMode)
3061 {
3062 case GL_INTERLEAVED_ATTRIBS:
3063 break;
3064 case GL_SEPARATE_ATTRIBS:
3065 {
3066 const Caps &caps = context->getCaps();
3067 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3068 {
3069 context->handleError(InvalidValue());
3070 return false;
3071 }
3072 break;
3073 }
3074 default:
3075 context->handleError(InvalidEnum());
3076 return false;
3077 }
3078
3079 Program *programObject = GetValidProgram(context, program);
3080 if (!programObject)
3081 {
3082 return false;
3083 }
3084
3085 return true;
3086}
3087
3088bool ValidateGetTransformFeedbackVarying(Context *context,
3089 GLuint program,
3090 GLuint index,
3091 GLsizei bufSize,
3092 GLsizei *length,
3093 GLsizei *size,
3094 GLenum *type,
3095 GLchar *name)
3096{
3097 if (context->getClientMajorVersion() < 3)
3098 {
3099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3100 return false;
3101 }
3102
3103 if (bufSize < 0)
3104 {
3105 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3106 return false;
3107 }
3108
3109 Program *programObject = GetValidProgram(context, program);
3110 if (!programObject)
3111 {
3112 return false;
3113 }
3114
3115 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3116 {
3117 context->handleError(InvalidValue());
3118 return false;
3119 }
3120
3121 return true;
3122}
3123
3124bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3125{
3126 if (context->getClientMajorVersion() < 3)
3127 {
3128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3129 return false;
3130 }
3131
3132 switch (target)
3133 {
3134 case GL_TRANSFORM_FEEDBACK:
3135 {
3136 // Cannot bind a transform feedback object if the current one is started and not
3137 // paused (3.0.2 pg 85 section 2.14.1)
3138 TransformFeedback *curTransformFeedback =
3139 context->getGLState().getCurrentTransformFeedback();
3140 if (curTransformFeedback && curTransformFeedback->isActive() &&
3141 !curTransformFeedback->isPaused())
3142 {
3143 context->handleError(InvalidOperation());
3144 return false;
3145 }
3146
3147 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3148 // 2.14.1)
3149 if (!context->isTransformFeedbackGenerated(id))
3150 {
3151 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3152 return false;
3153 }
3154 }
3155 break;
3156
3157 default:
3158 context->handleError(InvalidEnum());
3159 return false;
3160 }
3161
3162 return true;
3163}
3164
3165bool ValidateIsTransformFeedback(Context *context, GLuint id)
3166{
3167 if (context->getClientMajorVersion() < 3)
3168 {
3169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3170 return false;
3171 }
3172
3173 return true;
3174}
3175
3176bool ValidatePauseTransformFeedback(Context *context)
3177{
3178 if (context->getClientMajorVersion() < 3)
3179 {
3180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3181 return false;
3182 }
3183
3184 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3185 ASSERT(transformFeedback != nullptr);
3186
3187 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3188 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3189 {
3190 context->handleError(InvalidOperation());
3191 return false;
3192 }
3193
3194 return true;
3195}
3196
3197bool ValidateResumeTransformFeedback(Context *context)
3198{
3199 if (context->getClientMajorVersion() < 3)
3200 {
3201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3202 return false;
3203 }
3204
3205 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3206 ASSERT(transformFeedback != nullptr);
3207
3208 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3209 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3210 {
3211 context->handleError(InvalidOperation());
3212 return false;
3213 }
3214
3215 return true;
3216}
3217
Jamie Madill12e957f2017-08-26 21:42:26 -04003218bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3219{
3220 if (context->getClientMajorVersion() < 3)
3221 {
3222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3223 return false;
3224 }
3225
3226 return ValidateVertexAttribIndex(context, index);
3227}
3228
3229bool ValidateVertexAttribI4ui(Context *context,
3230 GLuint index,
3231 GLuint x,
3232 GLuint y,
3233 GLuint z,
3234 GLuint w)
3235{
3236 if (context->getClientMajorVersion() < 3)
3237 {
3238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3239 return false;
3240 }
3241
3242 return ValidateVertexAttribIndex(context, index);
3243}
3244
3245bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3246{
3247 if (context->getClientMajorVersion() < 3)
3248 {
3249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3250 return false;
3251 }
3252
3253 return ValidateVertexAttribIndex(context, index);
3254}
3255
3256bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3257{
3258 if (context->getClientMajorVersion() < 3)
3259 {
3260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3261 return false;
3262 }
3263
3264 return ValidateVertexAttribIndex(context, index);
3265}
3266
3267bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3268{
3269 if (context->getClientMajorVersion() < 3)
3270 {
3271 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3272 return false;
3273 }
3274
3275 Program *programObject = GetValidProgram(context, program);
3276 if (!programObject)
3277 {
3278 return false;
3279 }
3280
3281 if (!programObject->isLinked())
3282 {
3283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3284 return false;
3285 }
3286
3287 return true;
3288}
3289
3290bool ValidateGetUniformIndices(Context *context,
3291 GLuint program,
3292 GLsizei uniformCount,
3293 const GLchar *const *uniformNames,
3294 GLuint *uniformIndices)
3295{
3296 if (context->getClientMajorVersion() < 3)
3297 {
3298 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3299 return false;
3300 }
3301
3302 if (uniformCount < 0)
3303 {
3304 context->handleError(InvalidValue());
3305 return false;
3306 }
3307
3308 Program *programObject = GetValidProgram(context, program);
3309 if (!programObject)
3310 {
3311 return false;
3312 }
3313
3314 return true;
3315}
3316
3317bool ValidateGetActiveUniformsiv(Context *context,
3318 GLuint program,
3319 GLsizei uniformCount,
3320 const GLuint *uniformIndices,
3321 GLenum pname,
3322 GLint *params)
3323{
3324 if (context->getClientMajorVersion() < 3)
3325 {
3326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3327 return false;
3328 }
3329
3330 if (uniformCount < 0)
3331 {
3332 context->handleError(InvalidValue());
3333 return false;
3334 }
3335
3336 Program *programObject = GetValidProgram(context, program);
3337 if (!programObject)
3338 {
3339 return false;
3340 }
3341
3342 switch (pname)
3343 {
3344 case GL_UNIFORM_TYPE:
3345 case GL_UNIFORM_SIZE:
3346 case GL_UNIFORM_NAME_LENGTH:
3347 case GL_UNIFORM_BLOCK_INDEX:
3348 case GL_UNIFORM_OFFSET:
3349 case GL_UNIFORM_ARRAY_STRIDE:
3350 case GL_UNIFORM_MATRIX_STRIDE:
3351 case GL_UNIFORM_IS_ROW_MAJOR:
3352 break;
3353
3354 default:
3355 context->handleError(InvalidEnum());
3356 return false;
3357 }
3358
3359 if (uniformCount > programObject->getActiveUniformCount())
3360 {
3361 context->handleError(InvalidValue());
3362 return false;
3363 }
3364
3365 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3366 {
3367 const GLuint index = uniformIndices[uniformId];
3368
3369 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3370 {
3371 context->handleError(InvalidValue());
3372 return false;
3373 }
3374 }
3375
3376 return true;
3377}
3378
3379bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3380{
3381 if (context->getClientMajorVersion() < 3)
3382 {
3383 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3384 return false;
3385 }
3386
3387 Program *programObject = GetValidProgram(context, program);
3388 if (!programObject)
3389 {
3390 return false;
3391 }
3392
3393 return true;
3394}
3395
3396bool ValidateGetActiveUniformBlockiv(Context *context,
3397 GLuint program,
3398 GLuint uniformBlockIndex,
3399 GLenum pname,
3400 GLint *params)
3401{
3402 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3403}
3404
3405bool ValidateGetActiveUniformBlockName(Context *context,
3406 GLuint program,
3407 GLuint uniformBlockIndex,
3408 GLsizei bufSize,
3409 GLsizei *length,
3410 GLchar *uniformBlockName)
3411{
3412 if (context->getClientMajorVersion() < 3)
3413 {
3414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3415 return false;
3416 }
3417
3418 Program *programObject = GetValidProgram(context, program);
3419 if (!programObject)
3420 {
3421 return false;
3422 }
3423
3424 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3425 {
3426 context->handleError(InvalidValue());
3427 return false;
3428 }
3429
3430 return true;
3431}
3432
3433bool ValidateUniformBlockBinding(Context *context,
3434 GLuint program,
3435 GLuint uniformBlockIndex,
3436 GLuint uniformBlockBinding)
3437{
3438 if (context->getClientMajorVersion() < 3)
3439 {
3440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3441 return false;
3442 }
3443
3444 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3445 {
3446 context->handleError(InvalidValue());
3447 return false;
3448 }
3449
3450 Program *programObject = GetValidProgram(context, program);
3451 if (!programObject)
3452 {
3453 return false;
3454 }
3455
3456 // if never linked, there won't be any uniform blocks
3457 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3458 {
3459 context->handleError(InvalidValue());
3460 return false;
3461 }
3462
3463 return true;
3464}
3465
3466bool ValidateDrawArraysInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003467 PrimitiveMode mode,
Jamie Madill12e957f2017-08-26 21:42:26 -04003468 GLint first,
3469 GLsizei count,
3470 GLsizei primcount)
3471{
3472 if (context->getClientMajorVersion() < 3)
3473 {
3474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3475 return false;
3476 }
3477
3478 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3479}
3480
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003481bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3482{
3483 if (context->getClientMajorVersion() < 3)
3484 {
3485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3486 return false;
3487 }
3488
3489 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3490 {
3491 context->handleError(InvalidEnum());
3492 return false;
3493 }
3494
3495 if (flags != 0)
3496 {
3497 context->handleError(InvalidValue());
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
3504bool ValidateIsSync(Context *context, GLsync sync)
3505{
3506 if (context->getClientMajorVersion() < 3)
3507 {
3508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3509 return false;
3510 }
3511
3512 return true;
3513}
3514
3515bool ValidateDeleteSync(Context *context, GLsync sync)
3516{
3517 if (context->getClientMajorVersion() < 3)
3518 {
3519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3520 return false;
3521 }
3522
Jamie Madill70b5bb02017-08-28 13:32:37 -04003523 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003524 {
3525 context->handleError(InvalidValue());
3526 return false;
3527 }
3528
3529 return true;
3530}
3531
3532bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3533{
3534 if (context->getClientMajorVersion() < 3)
3535 {
3536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3537 return false;
3538 }
3539
3540 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3541 {
3542 context->handleError(InvalidValue());
3543 return false;
3544 }
3545
Jamie Madill70b5bb02017-08-28 13:32:37 -04003546 Sync *clientWaitSync = context->getSync(sync);
3547 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003548 {
3549 context->handleError(InvalidValue());
3550 return false;
3551 }
3552
3553 return true;
3554}
3555
3556bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3557{
3558 if (context->getClientMajorVersion() < 3)
3559 {
3560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3561 return false;
3562 }
3563
3564 if (flags != 0)
3565 {
3566 context->handleError(InvalidValue());
3567 return false;
3568 }
3569
3570 if (timeout != GL_TIMEOUT_IGNORED)
3571 {
3572 context->handleError(InvalidValue());
3573 return false;
3574 }
3575
Jamie Madill70b5bb02017-08-28 13:32:37 -04003576 Sync *waitSync = context->getSync(sync);
3577 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003578 {
3579 context->handleError(InvalidValue());
3580 return false;
3581 }
3582
3583 return true;
3584}
3585
3586bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3587{
3588 if (context->getClientMajorVersion() < 3)
3589 {
3590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3591 return false;
3592 }
3593
3594 GLenum nativeType = GL_NONE;
3595 unsigned int numParams = 0;
3596 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3597 {
3598 return false;
3599 }
3600
3601 return true;
3602}
3603
Jamie Madill3ef140a2017-08-26 23:11:21 -04003604bool ValidateIsSampler(Context *context, GLuint sampler)
3605{
3606 if (context->getClientMajorVersion() < 3)
3607 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003609 return false;
3610 }
3611
3612 return true;
3613}
3614
3615bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3616{
3617 if (context->getClientMajorVersion() < 3)
3618 {
3619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3620 return false;
3621 }
3622
3623 if (sampler != 0 && !context->isSampler(sampler))
3624 {
3625 context->handleError(InvalidOperation());
3626 return false;
3627 }
3628
3629 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3630 {
3631 context->handleError(InvalidValue());
3632 return false;
3633 }
3634
3635 return true;
3636}
3637
3638bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3639{
3640 if (context->getClientMajorVersion() < 3)
3641 {
3642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3643 return false;
3644 }
3645
3646 return ValidateVertexAttribIndex(context, index);
3647}
3648
3649bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003650 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003651 GLsizei levels,
3652 GLenum internalformat,
3653 GLsizei width,
3654 GLsizei height)
3655{
3656 if (context->getClientMajorVersion() < 3)
3657 {
3658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3659 return false;
3660 }
3661
3662 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3663 1))
3664 {
3665 return false;
3666 }
3667
3668 return true;
3669}
3670
3671bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003672 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003673 GLsizei levels,
3674 GLenum internalformat,
3675 GLsizei width,
3676 GLsizei height,
3677 GLsizei depth)
3678{
3679 if (context->getClientMajorVersion() < 3)
3680 {
3681 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3682 return false;
3683 }
3684
3685 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3686 depth))
3687 {
3688 return false;
3689 }
3690
3691 return true;
3692}
3693
Jamie Madill5b772312018-03-08 20:28:32 -05003694bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003695 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003696 GLenum pname,
3697 GLint64 *params)
3698{
3699 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3700}
3701
3702bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3703{
3704 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3705}
3706
3707bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3708{
3709 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3710}
3711
3712bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3713{
3714 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3715}
3716
3717bool ValidateSamplerParameterfv(Context *context,
3718 GLuint sampler,
3719 GLenum pname,
3720 const GLfloat *params)
3721{
3722 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3723}
3724
3725bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3726{
3727 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3728}
3729
3730bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3731{
3732 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3733}
3734
3735bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3736{
3737 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3738}
3739
3740bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3741{
3742 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3743}
3744
3745bool ValidateGetInternalformativ(Context *context,
3746 GLenum target,
3747 GLenum internalformat,
3748 GLenum pname,
3749 GLsizei bufSize,
3750 GLint *params)
3751{
3752 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3753 nullptr);
3754}
3755
Jamie Madillc29968b2016-01-20 11:17:23 -05003756} // namespace gl