blob: 07f80584195c8553269289f3cb1a79985bfa44ce [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 Madille98b1b52018-03-08 09:47:23 -0500811 if (!ValidateFramebufferComplete(context, framebuffer, true))
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
823 if (isSubImage)
824 {
Geoff Langca271392017-04-05 12:30:00 -0400825 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500826 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 }
831 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400832 else
833 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400834 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400835 const InternalFormat &framebufferFormat = *source->getFormat().info;
836 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400837 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500839 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400841 }
842 }
843
Geoff Lang784a8fd2013-09-24 12:33:16 -0400844 // If width or height is zero, it is a no-op. Return false without setting an error.
845 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846}
847
Jamie Madill5b772312018-03-08 20:28:32 -0500848bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800849 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500850 GLint level,
851 GLenum internalformat,
852 bool isSubImage,
853 GLint xoffset,
854 GLint yoffset,
855 GLint zoffset,
856 GLint x,
857 GLint y,
858 GLsizei width,
859 GLsizei height,
860 GLint border)
861{
862 if (!ValidTexture2DDestinationTarget(context, target))
863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500864 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500865 return false;
866 }
867
868 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
869 xoffset, yoffset, zoffset, x, y, width, height,
870 border);
871}
872
Jamie Madill5b772312018-03-08 20:28:32 -0500873bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800874 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500875 GLint level,
876 GLenum internalformat,
877 bool isSubImage,
878 GLint xoffset,
879 GLint yoffset,
880 GLint zoffset,
881 GLint x,
882 GLint y,
883 GLsizei width,
884 GLsizei height,
885 GLint border)
886{
887 if (!ValidTexture3DDestinationTarget(context, target))
888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500889 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500890 return false;
891 }
892
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800893 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
894 internalformat, isSubImage, xoffset, yoffset,
895 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500896}
897
898bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800899 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500900 GLsizei levels,
901 GLenum internalformat,
902 GLsizei width,
903 GLsizei height,
904 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905{
906 if (width < 1 || height < 1 || depth < 1 || levels < 1)
907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500908 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400909 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 }
911
Geoff Langb92c1332015-09-04 12:54:55 -0400912 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800913 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400914 {
915 maxDim = std::max(maxDim, depth);
916 }
917
918 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500920 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400921 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 }
923
Geoff Langaae65a42014-05-26 12:43:44 -0400924 const gl::Caps &caps = context->getCaps();
925
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 switch (target)
927 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800928 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929 {
Geoff Langaae65a42014-05-26 12:43:44 -0400930 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
931 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500933 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936 }
937 break;
938
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800939 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400940 {
941 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
942 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
943 {
944 context->handleError(InvalidValue());
945 return false;
946 }
947 }
948 break;
949
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800950 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 if (width != height)
953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500954 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 }
957
Geoff Langaae65a42014-05-26 12:43:44 -0400958 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400961 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962 }
963 }
964 break;
965
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800966 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 {
Geoff Langaae65a42014-05-26 12:43:44 -0400968 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
969 static_cast<GLuint>(height) > caps.max3DTextureSize ||
970 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500972 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400973 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 }
975 }
976 break;
977
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800978 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 {
Geoff Langaae65a42014-05-26 12:43:44 -0400980 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
981 static_cast<GLuint>(height) > caps.max2DTextureSize ||
982 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500984 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400985 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400986 }
987 }
988 break;
989
He Yunchaoced53ae2016-11-29 15:00:51 +0800990 default:
991 UNREACHABLE();
992 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 }
994
Geoff Lang691e58c2014-12-19 17:03:25 -0500995 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 if (!texture || texture->id() == 0)
997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500998 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400999 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 }
1001
Geoff Lang69cce582015-09-17 13:20:36 -04001002 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001004 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001005 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 }
1007
Geoff Langca271392017-04-05 12:30:00 -04001008 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001009 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001011 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 }
1014
Geoff Langca271392017-04-05 12:30:00 -04001015 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001021 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001022 {
1023 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1024 return false;
1025 }
1026
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 return true;
1028}
1029
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001030bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001031 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001032 GLsizei levels,
1033 GLenum internalformat,
1034 GLsizei width,
1035 GLsizei height,
1036 GLsizei depth)
1037{
1038 if (!ValidTexture2DTarget(context, target))
1039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001040 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001041 return false;
1042 }
1043
1044 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1045 height, depth);
1046}
1047
1048bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001049 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001050 GLsizei levels,
1051 GLenum internalformat,
1052 GLsizei width,
1053 GLsizei height,
1054 GLsizei depth)
1055{
1056 if (!ValidTexture3DTarget(context, target))
1057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001058 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001059 return false;
1060 }
1061
1062 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1063 height, depth);
1064}
1065
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001066bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1067{
Martin Radev1be913c2016-07-11 17:59:16 +03001068 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001069 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001071 return false;
1072 }
1073
1074 return ValidateBeginQueryBase(context, target, id);
1075}
1076
1077bool ValidateEndQuery(gl::Context *context, GLenum target)
1078{
Martin Radev1be913c2016-07-11 17:59:16 +03001079 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001080 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001082 return false;
1083 }
1084
1085 return ValidateEndQueryBase(context, target);
1086}
1087
1088bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1089{
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001091 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093 return false;
1094 }
1095
Geoff Lang2186c382016-10-14 10:54:54 -04001096 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097}
1098
1099bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1100{
Martin Radev1be913c2016-07-11 17:59:16 +03001101 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001102 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001104 return false;
1105 }
1106
Geoff Lang2186c382016-10-14 10:54:54 -04001107 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001108}
1109
He Yunchaoced53ae2016-11-29 15:00:51 +08001110bool ValidateFramebufferTextureLayer(Context *context,
1111 GLenum target,
1112 GLenum attachment,
1113 GLuint texture,
1114 GLint level,
1115 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001116{
Martin Radev1be913c2016-07-11 17:59:16 +03001117 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001118 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001120 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001121 }
1122
Jamie Madill55ec3b12014-07-03 10:38:57 -04001123 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1124 {
1125 return false;
1126 }
1127
1128 const gl::Caps &caps = context->getCaps();
1129 if (texture != 0)
1130 {
Geoff Lang23e02842017-10-17 13:24:09 -04001131 if (layer < 0)
1132 {
1133 context->handleError(InvalidValue());
1134 return false;
1135 }
1136
Jamie Madill55ec3b12014-07-03 10:38:57 -04001137 gl::Texture *tex = context->getTexture(texture);
1138 ASSERT(tex);
1139
Corentin Wallez99d492c2018-02-27 15:17:10 -05001140 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001141 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001142 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001143 {
1144 if (level > gl::log2(caps.max2DTextureSize))
1145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001146 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001148 }
1149
1150 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001152 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001153 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001154 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001155 }
1156 break;
1157
Corentin Wallez99d492c2018-02-27 15:17:10 -05001158 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001159 {
1160 if (level > gl::log2(caps.max3DTextureSize))
1161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001162 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001163 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001164 }
1165
1166 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001168 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001170 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001171 }
1172 break;
1173
He Yunchaoced53ae2016-11-29 15:00:51 +08001174 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001175 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001177 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001178
Corentin Wallez99d492c2018-02-27 15:17:10 -05001179 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001180 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001182 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001183 return false;
1184 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001185 }
1186
1187 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001188}
1189
He Yunchaoced53ae2016-11-29 15:00:51 +08001190bool ValidateInvalidateFramebuffer(Context *context,
1191 GLenum target,
1192 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001193 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194{
Martin Radev1be913c2016-07-11 17:59:16 +03001195 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001196 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001198 return false;
1199 }
1200
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201 bool defaultFramebuffer = false;
1202
1203 switch (target)
1204 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001205 case GL_DRAW_FRAMEBUFFER:
1206 case GL_FRAMEBUFFER:
1207 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1208 break;
1209 case GL_READ_FRAMEBUFFER:
1210 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1211 break;
1212 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215 }
1216
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1218 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219}
1220
Jamie Madill3ef140a2017-08-26 23:11:21 -04001221bool ValidateInvalidateSubFramebuffer(Context *context,
1222 GLenum target,
1223 GLsizei numAttachments,
1224 const GLenum *attachments,
1225 GLint x,
1226 GLint y,
1227 GLsizei width,
1228 GLsizei height)
1229{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001230 if (width < 0 || height < 0)
1231 {
1232 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1233 return false;
1234 }
1235
Jamie Madill3ef140a2017-08-26 23:11:21 -04001236 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1237}
1238
Jamie Madill5b772312018-03-08 20:28:32 -05001239bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001240{
Martin Radev1be913c2016-07-11 17:59:16 +03001241 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001242 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001245 }
1246
Jamie Madille98b1b52018-03-08 09:47:23 -05001247 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer(), true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001248 {
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 }
1251
1252 return true;
1253}
1254
Olli Etuaho71dfb362016-03-10 14:04:27 +02001255bool ValidateDrawRangeElements(Context *context,
1256 GLenum mode,
1257 GLuint start,
1258 GLuint end,
1259 GLsizei count,
1260 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001261 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001262{
Martin Radev1be913c2016-07-11 17:59:16 +03001263 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001264 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001266 return false;
1267 }
1268
1269 if (end < start)
1270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001271 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001272 return false;
1273 }
1274
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001275 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001276 {
1277 return false;
1278 }
1279
Jamie Madill9fdaa492018-02-16 10:52:11 -05001280 // Skip range checks for no-op calls.
1281 if (count <= 0)
1282 {
1283 return true;
1284 }
1285
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001286 // Use the parameter buffer to retrieve and cache the index range.
1287 const auto &params = context->getParams<HasIndexRange>();
1288 const auto &indexRangeOpt = params.getIndexRange();
1289 if (!indexRangeOpt.valid())
1290 {
1291 // Unexpected error.
1292 return false;
1293 }
1294
1295 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001296 {
1297 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001298 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001299 return false;
1300 }
1301 return true;
1302}
1303
He Yunchaoced53ae2016-11-29 15:00:51 +08001304bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001305{
Martin Radev1be913c2016-07-11 17:59:16 +03001306 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001307 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001308 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001309 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001310 }
1311
Jamie Madill78f41802014-08-25 15:47:55 -04001312 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001313}
1314
Jamie Madillb885e572015-02-03 16:16:04 -05001315bool ValidateReadBuffer(Context *context, GLenum src)
1316{
Martin Radev1be913c2016-07-11 17:59:16 +03001317 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001318 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001320 return false;
1321 }
1322
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001323 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001324
1325 if (readFBO == nullptr)
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001328 return false;
1329 }
1330
1331 if (src == GL_NONE)
1332 {
1333 return true;
1334 }
1335
Olli Etuaho84c9f592016-03-09 14:37:25 +02001336 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001338 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001339 return false;
1340 }
1341
1342 if (readFBO->id() == 0)
1343 {
1344 if (src != GL_BACK)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(
1347 InvalidOperation()
1348 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001349 return false;
1350 }
1351 }
1352 else
1353 {
1354 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1355
1356 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001358 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001359 return false;
1360 }
1361 }
1362
1363 return true;
1364}
1365
Jamie Madill86af3d22015-07-21 15:14:07 -04001366bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001367 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001368 GLint level,
1369 GLenum internalformat,
1370 GLsizei width,
1371 GLsizei height,
1372 GLsizei depth,
1373 GLint border,
1374 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001375 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001376{
Martin Radev1be913c2016-07-11 17:59:16 +03001377 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001378 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001380 return false;
1381 }
1382
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001383 if (!ValidTextureTarget(context, target))
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001386 return false;
1387 }
1388
Jamie Madille2e406c2016-06-02 13:04:10 -04001389 // Validate image size
1390 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001393 return false;
1394 }
1395
Geoff Langca271392017-04-05 12:30:00 -04001396 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001397 if (!formatInfo.compressed)
1398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001400 return false;
1401 }
1402
Jeff Gilbert48590352017-11-07 16:03:38 -08001403 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001404 if (blockSizeOrErr.isError())
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001407 return false;
1408 }
1409 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001412 return false;
1413 }
1414
1415 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001416 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001418 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001419 return false;
1420 }
1421
1422 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001423 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001424 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1425 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001426 {
1427 return false;
1428 }
1429
1430 return true;
1431}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001432
Corentin Wallezb2931602017-04-11 15:58:57 -04001433bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001434 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001435 GLint level,
1436 GLenum internalformat,
1437 GLsizei width,
1438 GLsizei height,
1439 GLsizei depth,
1440 GLint border,
1441 GLsizei imageSize,
1442 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001443 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001444{
1445 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1446 {
1447 return false;
1448 }
1449
1450 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1451 depth, border, imageSize, data);
1452}
1453
Austin Kinrossbc781f32015-10-26 09:27:38 -07001454bool ValidateBindVertexArray(Context *context, GLuint array)
1455{
Martin Radev1be913c2016-07-11 17:59:16 +03001456 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001457 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001459 return false;
1460 }
1461
1462 return ValidateBindVertexArrayBase(context, array);
1463}
1464
Jamie Madilld7576732017-08-26 18:49:50 -04001465bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001466{
Martin Radev1be913c2016-07-11 17:59:16 +03001467 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001468 {
Jamie Madilld7576732017-08-26 18:49:50 -04001469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001470 return false;
1471 }
1472
1473 return true;
1474}
Geoff Langc5629752015-12-07 16:29:04 -05001475
Jiajia Qin6eafb042016-12-27 17:04:07 +08001476static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001477 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001478 GLuint index,
1479 GLuint buffer,
1480 GLintptr offset,
1481 GLsizeiptr size)
1482{
1483 if (context->getClientMajorVersion() < 3)
1484 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001486 return false;
1487 }
1488
1489 if (buffer != 0 && offset < 0)
1490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001492 return false;
1493 }
1494
1495 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1496 !context->isBufferGenerated(buffer))
1497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001498 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001499 return false;
1500 }
1501
1502 const Caps &caps = context->getCaps();
1503 switch (target)
1504 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001505 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001506 {
1507 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidValue() << "index is greater than or equal to the "
1510 "number of TRANSFORM_FEEDBACK_BUFFER "
1511 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001512 return false;
1513 }
1514 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001516 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001517 return false;
1518 }
1519
1520 TransformFeedback *curTransformFeedback =
1521 context->getGLState().getCurrentTransformFeedback();
1522 if (curTransformFeedback && curTransformFeedback->isActive())
1523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001524 context->handleError(InvalidOperation()
1525 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1526 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001527 return false;
1528 }
1529 break;
1530 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001531 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 {
1533 if (index >= caps.maxUniformBufferBindings)
1534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(InvalidValue() << "index is greater than or equal to the "
1536 "number of UNIFORM_BUFFER indexed "
1537 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001538 return false;
1539 }
1540
1541 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1542 {
1543 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001544 InvalidValue()
1545 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001546 return false;
1547 }
1548 break;
1549 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001550 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001551 {
1552 if (context->getClientVersion() < ES_3_1)
1553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001554 context->handleError(InvalidEnum()
1555 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001556 return false;
1557 }
1558 if (index >= caps.maxAtomicCounterBufferBindings)
1559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidValue() << "index is greater than or equal to the "
1561 "number of ATOMIC_COUNTER_BUFFER "
1562 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001563 return false;
1564 }
1565 if (buffer != 0 && (offset % 4) != 0)
1566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001567 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001568 return false;
1569 }
1570 break;
1571 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001572 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001573 {
1574 if (context->getClientVersion() < ES_3_1)
1575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidEnum()
1577 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001578 return false;
1579 }
1580 if (index >= caps.maxShaderStorageBufferBindings)
1581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidValue() << "index is greater than or equal to the "
1583 "number of SHADER_STORAGE_BUFFER "
1584 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001585 return false;
1586 }
1587 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001589 context->handleError(InvalidValue() << "offset must be multiple of value of "
1590 "SHADER_STORAGE_BUFFER_OFFSET_"
1591 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001592 return false;
1593 }
1594 break;
1595 }
1596 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001598 return false;
1599 }
1600
1601 return true;
1602}
1603
Corentin Wallez336129f2017-10-17 15:55:40 -04001604bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001605{
1606 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1607}
1608
1609bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001610 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001611 GLuint index,
1612 GLuint buffer,
1613 GLintptr offset,
1614 GLsizeiptr size)
1615{
1616 if (buffer != 0 && size <= 0)
1617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001618 context->handleError(InvalidValue()
1619 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001620 return false;
1621 }
1622 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1623}
1624
Geoff Langc5629752015-12-07 16:29:04 -05001625bool ValidateProgramBinary(Context *context,
1626 GLuint program,
1627 GLenum binaryFormat,
1628 const void *binary,
1629 GLint length)
1630{
Martin Radev1be913c2016-07-11 17:59:16 +03001631 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001632 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001633 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001634 return false;
1635 }
1636
1637 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1638}
1639
1640bool ValidateGetProgramBinary(Context *context,
1641 GLuint program,
1642 GLsizei bufSize,
1643 GLsizei *length,
1644 GLenum *binaryFormat,
1645 void *binary)
1646{
Martin Radev1be913c2016-07-11 17:59:16 +03001647 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001648 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001649 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001650 return false;
1651 }
1652
1653 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1654}
1655
Olli Etuahof0fee072016-03-30 15:11:58 +03001656bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001657{
Martin Radev1be913c2016-07-11 17:59:16 +03001658 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001659 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001661 return false;
1662 }
1663
1664 if (GetValidProgram(context, program) == nullptr)
1665 {
1666 return false;
1667 }
1668
1669 switch (pname)
1670 {
1671 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001672 if (value != GL_FALSE && value != GL_TRUE)
1673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001674 context->handleError(InvalidValue()
1675 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001676 return false;
1677 }
Geoff Langc5629752015-12-07 16:29:04 -05001678 break;
1679
Yunchao He61afff12017-03-14 15:34:03 +08001680 case GL_PROGRAM_SEPARABLE:
1681 if (context->getClientVersion() < ES_3_1)
1682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001683 context->handleError(InvalidEnum()
1684 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001685 return false;
1686 }
1687
1688 if (value != GL_FALSE && value != GL_TRUE)
1689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001690 context->handleError(InvalidValue()
1691 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001692 return false;
1693 }
1694 break;
1695
Geoff Langc5629752015-12-07 16:29:04 -05001696 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001697 context->handleError(InvalidEnum()
1698 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001699 return false;
1700 }
1701
1702 return true;
1703}
Jamie Madillc29968b2016-01-20 11:17:23 -05001704
1705bool ValidateBlitFramebuffer(Context *context,
1706 GLint srcX0,
1707 GLint srcY0,
1708 GLint srcX1,
1709 GLint srcY1,
1710 GLint dstX0,
1711 GLint dstY0,
1712 GLint dstX1,
1713 GLint dstY1,
1714 GLbitfield mask,
1715 GLenum filter)
1716{
Martin Radev1be913c2016-07-11 17:59:16 +03001717 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001718 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001720 return false;
1721 }
1722
1723 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1724 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725}
Jamie Madillc29968b2016-01-20 11:17:23 -05001726
Jamie Madill5b772312018-03-08 20:28:32 -05001727bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001728{
1729 switch (buffer)
1730 {
1731 case GL_COLOR:
1732 if (drawbuffer < 0 ||
1733 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001735 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001736 return false;
1737 }
Geoff Lang76e65652017-03-27 14:58:02 -04001738 if (context->getExtensions().webglCompatibility)
1739 {
1740 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001741 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001742 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1743 {
1744 return false;
1745 }
1746 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001747 break;
1748
1749 case GL_STENCIL:
1750 if (drawbuffer != 0)
1751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001752 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001753 return false;
1754 }
1755 break;
1756
1757 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001759 return false;
1760 }
1761
1762 return ValidateClearBuffer(context);
1763}
1764
Jamie Madill5b772312018-03-08 20:28:32 -05001765bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001766{
1767 switch (buffer)
1768 {
1769 case GL_COLOR:
1770 if (drawbuffer < 0 ||
1771 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001773 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001774 return false;
1775 }
Geoff Lang76e65652017-03-27 14:58:02 -04001776 if (context->getExtensions().webglCompatibility)
1777 {
1778 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001779 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001780 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1781 {
1782 return false;
1783 }
1784 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 break;
1786
1787 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001788 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001789 return false;
1790 }
1791
1792 return ValidateClearBuffer(context);
1793}
1794
Jamie Madill5b772312018-03-08 20:28:32 -05001795bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001796{
1797 switch (buffer)
1798 {
1799 case GL_COLOR:
1800 if (drawbuffer < 0 ||
1801 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001803 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 return false;
1805 }
Geoff Lang76e65652017-03-27 14:58:02 -04001806 if (context->getExtensions().webglCompatibility)
1807 {
1808 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1809 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001810 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001811 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1812 {
1813 return false;
1814 }
1815 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 break;
1817
1818 case GL_DEPTH:
1819 if (drawbuffer != 0)
1820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001821 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001822 return false;
1823 }
1824 break;
1825
1826 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001827 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 return false;
1829 }
1830
1831 return ValidateClearBuffer(context);
1832}
1833
Jamie Madill5b772312018-03-08 20:28:32 -05001834bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001835 GLenum buffer,
1836 GLint drawbuffer,
1837 GLfloat depth,
1838 GLint stencil)
1839{
1840 switch (buffer)
1841 {
1842 case GL_DEPTH_STENCIL:
1843 if (drawbuffer != 0)
1844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001845 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001846 return false;
1847 }
1848 break;
1849
1850 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001851 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001852 return false;
1853 }
1854
1855 return ValidateClearBuffer(context);
1856}
1857
Jamie Madill5b772312018-03-08 20:28:32 -05001858bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001859{
Martin Radev1be913c2016-07-11 17:59:16 +03001860 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001861 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001862 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 return false;
1864 }
1865
1866 return ValidateDrawBuffersBase(context, n, bufs);
1867}
1868
1869bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001870 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001871 GLint level,
1872 GLint xoffset,
1873 GLint yoffset,
1874 GLint zoffset,
1875 GLint x,
1876 GLint y,
1877 GLsizei width,
1878 GLsizei height)
1879{
Martin Radev1be913c2016-07-11 17:59:16 +03001880 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001881 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001883 return false;
1884 }
1885
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001886 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1887 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001888}
1889
Jamie Madill73a84962016-02-12 09:27:23 -05001890bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001891 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001892 GLint level,
1893 GLint internalformat,
1894 GLsizei width,
1895 GLsizei height,
1896 GLsizei depth,
1897 GLint border,
1898 GLenum format,
1899 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001900 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001901{
Martin Radev1be913c2016-07-11 17:59:16 +03001902 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001903 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001905 return false;
1906 }
1907
1908 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001909 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001910 pixels);
1911}
1912
Geoff Langc52f6f12016-10-14 10:18:00 -04001913bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001914 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001915 GLint level,
1916 GLint internalformat,
1917 GLsizei width,
1918 GLsizei height,
1919 GLsizei depth,
1920 GLint border,
1921 GLenum format,
1922 GLenum type,
1923 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001924 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001925{
1926 if (context->getClientMajorVersion() < 3)
1927 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001929 return false;
1930 }
1931
1932 if (!ValidateRobustEntryPoint(context, bufSize))
1933 {
1934 return false;
1935 }
1936
1937 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1938 0, 0, width, height, depth, border, format, type,
1939 bufSize, pixels);
1940}
1941
Jamie Madill73a84962016-02-12 09:27:23 -05001942bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001943 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001944 GLint level,
1945 GLint xoffset,
1946 GLint yoffset,
1947 GLint zoffset,
1948 GLsizei width,
1949 GLsizei height,
1950 GLsizei depth,
1951 GLenum format,
1952 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001953 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001954{
Martin Radev1be913c2016-07-11 17:59:16 +03001955 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001956 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001958 return false;
1959 }
1960
1961 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1962 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001963 -1, pixels);
1964}
1965
1966bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001967 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001968 GLint level,
1969 GLint xoffset,
1970 GLint yoffset,
1971 GLint zoffset,
1972 GLsizei width,
1973 GLsizei height,
1974 GLsizei depth,
1975 GLenum format,
1976 GLenum type,
1977 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001978 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001979{
1980 if (context->getClientMajorVersion() < 3)
1981 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001982 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001983 return false;
1984 }
1985
1986 if (!ValidateRobustEntryPoint(context, bufSize))
1987 {
1988 return false;
1989 }
1990
1991 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1992 yoffset, zoffset, width, height, depth, 0, format, type,
1993 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001994}
1995
1996bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001997 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001998 GLint level,
1999 GLint xoffset,
2000 GLint yoffset,
2001 GLint zoffset,
2002 GLsizei width,
2003 GLsizei height,
2004 GLsizei depth,
2005 GLenum format,
2006 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002007 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002008{
Martin Radev1be913c2016-07-11 17:59:16 +03002009 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002010 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002012 return false;
2013 }
2014
Geoff Langca271392017-04-05 12:30:00 -04002015 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002016 if (!formatInfo.compressed)
2017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002018 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002019 return false;
2020 }
2021
Jeff Gilbert48590352017-11-07 16:03:38 -08002022 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002023 if (blockSizeOrErr.isError())
2024 {
2025 context->handleError(blockSizeOrErr.getError());
2026 return false;
2027 }
2028 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002030 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002031 return false;
2032 }
2033
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002034 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2035 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2036 -1, data))
2037 {
2038 return false;
2039 }
2040
Jamie Madill73a84962016-02-12 09:27:23 -05002041 if (!data)
2042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002043 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002044 return false;
2045 }
2046
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002047 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002048}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002049
Corentin Wallezb2931602017-04-11 15:58:57 -04002050bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002051 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002052 GLint level,
2053 GLint xoffset,
2054 GLint yoffset,
2055 GLint zoffset,
2056 GLsizei width,
2057 GLsizei height,
2058 GLsizei depth,
2059 GLenum format,
2060 GLsizei imageSize,
2061 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002062 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002063{
2064 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2065 {
2066 return false;
2067 }
2068
2069 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2070 height, depth, format, imageSize, data);
2071}
Jamie Madill73a84962016-02-12 09:27:23 -05002072
Olli Etuaho41997e72016-03-10 13:38:39 +02002073bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2074{
2075 return ValidateGenOrDeleteES3(context, n);
2076}
2077
2078bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2079{
2080 return ValidateGenOrDeleteES3(context, n);
2081}
2082
2083bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2084{
2085 return ValidateGenOrDeleteCountES3(context, count);
2086}
2087
2088bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2089{
2090 return ValidateGenOrDeleteCountES3(context, count);
2091}
2092
2093bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2094{
2095 return ValidateGenOrDeleteES3(context, n);
2096}
2097
2098bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2099{
2100 if (!ValidateGenOrDeleteES3(context, n))
2101 {
2102 return false;
2103 }
2104 for (GLint i = 0; i < n; ++i)
2105 {
2106 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2107 if (transformFeedback != nullptr && transformFeedback->isActive())
2108 {
2109 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002110 context->handleError(InvalidOperation()
2111 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002112 return false;
2113 }
2114 }
2115 return true;
2116}
2117
2118bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2119{
2120 return ValidateGenOrDeleteES3(context, n);
2121}
2122
2123bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2124{
2125 return ValidateGenOrDeleteES3(context, n);
2126}
2127
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002128bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2129{
Martin Radev1be913c2016-07-11 17:59:16 +03002130 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002131 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002133 return false;
2134 }
2135 switch (primitiveMode)
2136 {
2137 case GL_TRIANGLES:
2138 case GL_LINES:
2139 case GL_POINTS:
2140 break;
2141
2142 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002144 return false;
2145 }
2146
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002147 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002148 ASSERT(transformFeedback != nullptr);
2149
2150 if (transformFeedback->isActive())
2151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002152 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002153 return false;
2154 }
Geoff Lang79f71042017-08-14 16:43:43 -04002155
2156 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2157 {
2158 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2159 if (buffer.get() && buffer->isMapped())
2160 {
2161 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2162 return false;
2163 }
2164 }
2165
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002166 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002167
2168 if (!program)
2169 {
2170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2171 return false;
2172 }
2173
2174 if (program->getTransformFeedbackVaryingCount() == 0)
2175 {
2176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2177 return false;
2178 }
2179
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002180 return true;
2181}
2182
Corentin Wallez336129f2017-10-17 15:55:40 -04002183bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002184{
Geoff Lang496c02d2016-10-20 11:38:11 -07002185 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2186}
2187
2188bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002189 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002190 GLenum pname,
2191 GLsizei bufSize,
2192 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002193 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002194{
2195 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002196 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002197 return false;
2198 }
2199
Geoff Lang496c02d2016-10-20 11:38:11 -07002200 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2201 {
2202 return false;
2203 }
2204
2205 if (!ValidateRobustBufferSize(context, bufSize, *length))
2206 {
2207 return false;
2208 }
2209
2210 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002211}
2212
Corentin Wallez336129f2017-10-17 15:55:40 -04002213bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002214{
Martin Radev1be913c2016-07-11 17:59:16 +03002215 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002216 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002218 return false;
2219 }
2220
2221 return ValidateUnmapBufferBase(context, target);
2222}
2223
2224bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002225 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002226 GLintptr offset,
2227 GLsizeiptr length,
2228 GLbitfield access)
2229{
Martin Radev1be913c2016-07-11 17:59:16 +03002230 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002231 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002232 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002233 return false;
2234 }
2235
2236 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2237}
2238
2239bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002240 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002241 GLintptr offset,
2242 GLsizeiptr length)
2243{
Martin Radev1be913c2016-07-11 17:59:16 +03002244 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002245 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002247 return false;
2248 }
2249
2250 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2251}
2252
Jamie Madill5b772312018-03-08 20:28:32 -05002253bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002254{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002255 if (length)
2256 {
2257 *length = 0;
2258 }
2259
Martin Radev66fb8202016-07-28 11:45:20 +03002260 GLenum nativeType;
2261 unsigned int numParams;
2262 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002264 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002265 return false;
2266 }
2267
2268 const Caps &caps = context->getCaps();
2269 switch (pname)
2270 {
2271 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2272 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2273 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2274 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002276 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002277 return false;
2278 }
2279 break;
2280
2281 case GL_UNIFORM_BUFFER_START:
2282 case GL_UNIFORM_BUFFER_SIZE:
2283 case GL_UNIFORM_BUFFER_BINDING:
2284 if (index >= caps.maxUniformBufferBindings)
2285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002286 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002287 return false;
2288 }
2289 break;
Shao80957d92017-02-20 21:25:59 +08002290
Martin Radev66fb8202016-07-28 11:45:20 +03002291 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2292 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2293 if (index >= 3u)
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
Jiajia Qin6eafb042016-12-27 17:04:07 +08002300 case GL_ATOMIC_COUNTER_BUFFER_START:
2301 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2302 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2303 if (context->getClientVersion() < ES_3_1)
2304 {
2305 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002306 InvalidEnum()
2307 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002308 return false;
2309 }
2310 if (index >= caps.maxAtomicCounterBufferBindings)
2311 {
2312 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002313 InvalidValue()
2314 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002315 return false;
2316 }
2317 break;
Shao80957d92017-02-20 21:25:59 +08002318
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002319 case GL_SHADER_STORAGE_BUFFER_START:
2320 case GL_SHADER_STORAGE_BUFFER_SIZE:
2321 case GL_SHADER_STORAGE_BUFFER_BINDING:
2322 if (context->getClientVersion() < ES_3_1)
2323 {
2324 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002325 InvalidEnum()
2326 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002327 return false;
2328 }
2329 if (index >= caps.maxShaderStorageBufferBindings)
2330 {
2331 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002332 InvalidValue()
2333 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002334 return false;
2335 }
2336 break;
2337
Shao80957d92017-02-20 21:25:59 +08002338 case GL_VERTEX_BINDING_BUFFER:
2339 case GL_VERTEX_BINDING_DIVISOR:
2340 case GL_VERTEX_BINDING_OFFSET:
2341 case GL_VERTEX_BINDING_STRIDE:
2342 if (context->getClientVersion() < ES_3_1)
2343 {
2344 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 InvalidEnum()
2346 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002347 return false;
2348 }
2349 if (index >= caps.maxVertexAttribBindings)
2350 {
2351 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002352 InvalidValue()
2353 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002354 return false;
2355 }
2356 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002357 case GL_SAMPLE_MASK_VALUE:
2358 if (context->getClientVersion() < ES_3_1)
2359 {
2360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2361 return false;
2362 }
2363 if (index >= caps.maxSampleMaskWords)
2364 {
2365 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2366 return false;
2367 }
2368 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002369 case GL_IMAGE_BINDING_NAME:
2370 case GL_IMAGE_BINDING_LEVEL:
2371 case GL_IMAGE_BINDING_LAYERED:
2372 case GL_IMAGE_BINDING_LAYER:
2373 case GL_IMAGE_BINDING_ACCESS:
2374 case GL_IMAGE_BINDING_FORMAT:
2375 if (context->getClientVersion() < ES_3_1)
2376 {
2377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2378 return false;
2379 }
2380 if (index >= caps.maxImageUnits)
2381 {
2382 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2383 return false;
2384 }
2385 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002386 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002387 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002388 return false;
2389 }
2390
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002391 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002392 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002393 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002394 }
2395
2396 return true;
2397}
2398
Jamie Madill5b772312018-03-08 20:28:32 -05002399bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002400{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002401 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002402 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002404 return false;
2405 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002406 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002407}
2408
Jamie Madill5b772312018-03-08 20:28:32 -05002409bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002410 GLenum target,
2411 GLuint index,
2412 GLsizei bufSize,
2413 GLsizei *length,
2414 GLint *data)
2415{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002416 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002417 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002419 return false;
2420 }
2421
2422 if (!ValidateRobustEntryPoint(context, bufSize))
2423 {
2424 return false;
2425 }
2426
2427 if (!ValidateIndexedStateQuery(context, target, index, length))
2428 {
2429 return false;
2430 }
2431
2432 if (!ValidateRobustBufferSize(context, bufSize, *length))
2433 {
2434 return false;
2435 }
2436
2437 return true;
2438}
2439
Jamie Madill5b772312018-03-08 20:28:32 -05002440bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002441{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002442 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002443 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002445 return false;
2446 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002447 return ValidateIndexedStateQuery(context, target, index, nullptr);
2448}
2449
Jamie Madill5b772312018-03-08 20:28:32 -05002450bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002451 GLenum target,
2452 GLuint index,
2453 GLsizei bufSize,
2454 GLsizei *length,
2455 GLint64 *data)
2456{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002457 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002460 return false;
2461 }
2462
2463 if (!ValidateRobustEntryPoint(context, bufSize))
2464 {
2465 return false;
2466 }
2467
2468 if (!ValidateIndexedStateQuery(context, target, index, length))
2469 {
2470 return false;
2471 }
2472
2473 if (!ValidateRobustBufferSize(context, bufSize, *length))
2474 {
2475 return false;
2476 }
2477
2478 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002479}
2480
Jamie Madill5b772312018-03-08 20:28:32 -05002481bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002482 BufferBinding readTarget,
2483 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002484 GLintptr readOffset,
2485 GLintptr writeOffset,
2486 GLsizeiptr size)
2487{
2488 if (context->getClientMajorVersion() < 3)
2489 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002491 return false;
2492 }
2493
Corentin Walleze4477002017-12-01 14:39:58 -05002494 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002496 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002497 return false;
2498 }
2499
2500 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2501 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2502
2503 if (!readBuffer || !writeBuffer)
2504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002505 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002506 return false;
2507 }
2508
2509 // Verify that readBuffer and writeBuffer are not currently mapped
2510 if (readBuffer->isMapped() || writeBuffer->isMapped())
2511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002512 context->handleError(InvalidOperation()
2513 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002514 return false;
2515 }
2516
James Darpiniane8a93c62018-01-04 18:02:24 -08002517 if (context->getExtensions().webglCompatibility &&
2518 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2519 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2520 {
2521 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2522 return false;
2523 }
2524
Jamie Madilld2f0c742016-11-02 10:34:41 -04002525 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2526 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2527 CheckedNumeric<GLintptr> checkedSize(size);
2528
2529 auto checkedReadSum = checkedReadOffset + checkedSize;
2530 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2531
2532 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2533 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2534 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002536 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002537 return false;
2538 }
2539
Jamie Madilld2f0c742016-11-02 10:34:41 -04002540 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 context->handleError(InvalidValue()
2543 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002544 return false;
2545 }
2546
Jamie Madilld2f0c742016-11-02 10:34:41 -04002547 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2548 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002550 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002551 return false;
2552 }
2553
2554 if (readBuffer == writeBuffer)
2555 {
2556 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2557 if (!checkedOffsetDiff.IsValid())
2558 {
2559 // This shold not be possible.
2560 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002561 context->handleError(InvalidValue()
2562 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002563 return false;
2564 }
2565
2566 if (checkedOffsetDiff.ValueOrDie() < size)
2567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002569 return false;
2570 }
2571 }
2572
Jamie Madillb0817d12016-11-01 15:48:31 -04002573 return true;
2574}
2575
Geoff Langc339c4e2016-11-29 10:37:36 -05002576bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2577{
2578 if (context->getClientMajorVersion() < 3)
2579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002581 return false;
2582 }
2583
2584 switch (name)
2585 {
2586 case GL_EXTENSIONS:
2587 if (index >= context->getExtensionStringCount())
2588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002589 context->handleError(InvalidValue()
2590 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002591 return false;
2592 }
2593 break;
2594
2595 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2596 if (!context->getExtensions().requestExtension)
2597 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002598 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002599 return false;
2600 }
2601 if (index >= context->getRequestableExtensionStringCount())
2602 {
2603 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002604 InvalidValue()
2605 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002606 return false;
2607 }
2608 break;
2609
2610 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002612 return false;
2613 }
2614
2615 return true;
2616}
2617
Jamie Madill5b772312018-03-08 20:28:32 -05002618bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002619 GLenum target,
2620 GLsizei samples,
2621 GLenum internalformat,
2622 GLsizei width,
2623 GLsizei height)
2624{
2625 if (context->getClientMajorVersion() < 3)
2626 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002627 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002628 return false;
2629 }
2630
2631 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2632 height))
2633 {
2634 return false;
2635 }
2636
2637 // 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 +08002638 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2639 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002640 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002641 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002642 {
Yunchao Hec0810202018-01-22 09:48:48 +08002643 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2644 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2645 {
2646 context->handleError(InvalidOperation());
2647 return false;
2648 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002649 }
2650
2651 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2652 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2653 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2654 {
2655 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002656 InvalidOperation()
2657 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002658 return false;
2659 }
2660
2661 return true;
2662}
2663
Jamie Madill5b772312018-03-08 20:28:32 -05002664bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002665 GLuint index,
2666 GLint size,
2667 GLenum type,
2668 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002669 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002670{
2671 if (context->getClientMajorVersion() < 3)
2672 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002674 return false;
2675 }
2676
Shao80957d92017-02-20 21:25:59 +08002677 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002678 {
Geoff Langaa086d62017-03-23 16:47:21 -04002679 return false;
2680 }
2681
Geoff Langaa086d62017-03-23 16:47:21 -04002682 if (stride < 0)
2683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002684 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002685 return false;
2686 }
2687
Shao80957d92017-02-20 21:25:59 +08002688 const Caps &caps = context->getCaps();
2689 if (context->getClientVersion() >= ES_3_1)
2690 {
2691 if (stride > caps.maxVertexAttribStride)
2692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002693 context->handleError(InvalidValue()
2694 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002695 return false;
2696 }
2697
2698 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2699 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2700 // validation should be inherited.
2701 if (index >= caps.maxVertexAttribBindings)
2702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002703 context->handleError(InvalidValue()
2704 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002705 return false;
2706 }
2707 }
2708
Geoff Langaa086d62017-03-23 16:47:21 -04002709 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2710 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2711 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2712 // and the pointer argument is not NULL.
2713 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002714 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002716 context
2717 ->handleError(InvalidOperation()
2718 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002719 return false;
2720 }
2721
Geoff Lang2d62ab72017-03-23 16:54:40 -04002722 if (context->getExtensions().webglCompatibility)
2723 {
2724 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2725 {
2726 return false;
2727 }
2728 }
2729
Geoff Langaa086d62017-03-23 16:47:21 -04002730 return true;
2731}
2732
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002733bool ValidateGetSynciv(Context *context,
2734 GLsync sync,
2735 GLenum pname,
2736 GLsizei bufSize,
2737 GLsizei *length,
2738 GLint *values)
2739{
2740 if (context->getClientMajorVersion() < 3)
2741 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002742 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002743 return false;
2744 }
2745
2746 if (bufSize < 0)
2747 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002748 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002749 return false;
2750 }
2751
Jamie Madill70b5bb02017-08-28 13:32:37 -04002752 Sync *syncObject = context->getSync(sync);
2753 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002755 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002756 return false;
2757 }
2758
2759 switch (pname)
2760 {
2761 case GL_OBJECT_TYPE:
2762 case GL_SYNC_CONDITION:
2763 case GL_SYNC_FLAGS:
2764 case GL_SYNC_STATUS:
2765 break;
2766
2767 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002769 return false;
2770 }
2771
2772 return true;
2773}
2774
Jamie Madill5b772312018-03-08 20:28:32 -05002775bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002776 GLenum mode,
2777 GLsizei count,
2778 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002779 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002780 GLsizei instanceCount)
2781{
2782 if (context->getClientMajorVersion() < 3)
2783 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002784 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002785 return false;
2786 }
2787
2788 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2789}
2790
Martin Radev137032d2017-07-13 10:11:12 +03002791bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2792 GLenum target,
2793 GLenum attachment,
2794 GLuint texture,
2795 GLint level,
2796 GLint baseViewIndex,
2797 GLsizei numViews)
2798{
2799
2800 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2801 numViews))
2802 {
2803 return false;
2804 }
2805
Martin Radev137032d2017-07-13 10:11:12 +03002806 if (texture != 0)
2807 {
Martin Radev14b21262017-08-25 13:54:37 +03002808 if (baseViewIndex < 0)
2809 {
2810 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2811 return false;
2812 }
2813
Martin Radev137032d2017-07-13 10:11:12 +03002814 Texture *tex = context->getTexture(texture);
2815 ASSERT(tex);
2816
Corentin Wallez99d492c2018-02-27 15:17:10 -05002817 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002818 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002819 case TextureType::_2DArray:
Martin Radev137032d2017-07-13 10:11:12 +03002820 {
2821 const Caps &caps = context->getCaps();
2822 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2823 {
2824 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2825 "greater than "
2826 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2827 return false;
2828 }
2829 }
2830 break;
2831 default:
2832 context->handleError(InvalidOperation()
2833 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2834 return false;
2835 }
2836
2837 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2838 {
2839 return false;
2840 }
2841 }
2842
2843 return true;
2844}
2845
2846bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2847 GLenum target,
2848 GLenum attachment,
2849 GLuint texture,
2850 GLint level,
2851 GLsizei numViews,
2852 const GLint *viewportOffsets)
2853{
2854 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2855 numViews))
2856 {
2857 return false;
2858 }
2859
Martin Radev137032d2017-07-13 10:11:12 +03002860 if (texture != 0)
2861 {
Martin Radev14b21262017-08-25 13:54:37 +03002862 const GLsizei numViewportOffsetValues = numViews * 2;
2863 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2864 {
2865 if (viewportOffsets[i] < 0)
2866 {
2867 context->handleError(InvalidValue()
2868 << "viewportOffsets cannot contain negative values.");
2869 return false;
2870 }
2871 }
2872
Martin Radev137032d2017-07-13 10:11:12 +03002873 Texture *tex = context->getTexture(texture);
2874 ASSERT(tex);
2875
Corentin Wallez99d492c2018-02-27 15:17:10 -05002876 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002877 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002878 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002879 break;
2880 default:
2881 context->handleError(InvalidOperation()
2882 << "Texture's target must be GL_TEXTURE_2D.");
2883 return false;
2884 }
2885
2886 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2887 {
2888 return false;
2889 }
2890 }
2891
2892 return true;
2893}
2894
Jamie Madillff325f12017-08-26 15:06:05 -04002895bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2896{
2897 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2898}
2899
2900bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2901{
2902 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2903}
2904
2905bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2906{
2907 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2908}
2909
2910bool ValidateUniform4ui(Context *context,
2911 GLint location,
2912 GLuint v0,
2913 GLuint v1,
2914 GLuint v2,
2915 GLuint v3)
2916{
2917 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2918}
2919
2920bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2921{
2922 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2923}
2924
2925bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2926{
2927 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2928}
2929
2930bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2931{
2932 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2933}
2934
2935bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2936{
2937 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2938}
2939
Jamie Madillf0e04492017-08-26 15:28:42 -04002940bool ValidateIsQuery(Context *context, GLuint id)
2941{
2942 if (context->getClientMajorVersion() < 3)
2943 {
2944 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2945 return false;
2946 }
2947
2948 return true;
2949}
2950
Jamie Madillc8c95812017-08-26 18:40:09 -04002951bool ValidateUniformMatrix2x3fv(Context *context,
2952 GLint location,
2953 GLsizei count,
2954 GLboolean transpose,
2955 const GLfloat *value)
2956{
2957 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2958}
2959
2960bool ValidateUniformMatrix3x2fv(Context *context,
2961 GLint location,
2962 GLsizei count,
2963 GLboolean transpose,
2964 const GLfloat *value)
2965{
2966 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2967}
2968
2969bool ValidateUniformMatrix2x4fv(Context *context,
2970 GLint location,
2971 GLsizei count,
2972 GLboolean transpose,
2973 const GLfloat *value)
2974{
2975 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2976}
2977
2978bool ValidateUniformMatrix4x2fv(Context *context,
2979 GLint location,
2980 GLsizei count,
2981 GLboolean transpose,
2982 const GLfloat *value)
2983{
2984 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2985}
2986
2987bool ValidateUniformMatrix3x4fv(Context *context,
2988 GLint location,
2989 GLsizei count,
2990 GLboolean transpose,
2991 const GLfloat *value)
2992{
2993 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2994}
2995
2996bool ValidateUniformMatrix4x3fv(Context *context,
2997 GLint location,
2998 GLsizei count,
2999 GLboolean transpose,
3000 const GLfloat *value)
3001{
3002 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3003}
3004
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003005bool ValidateEndTransformFeedback(Context *context)
3006{
3007 if (context->getClientMajorVersion() < 3)
3008 {
3009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3010 return false;
3011 }
3012
3013 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3014 ASSERT(transformFeedback != nullptr);
3015
3016 if (!transformFeedback->isActive())
3017 {
3018 context->handleError(InvalidOperation());
3019 return false;
3020 }
3021
3022 return true;
3023}
3024
3025bool ValidateTransformFeedbackVaryings(Context *context,
3026 GLuint program,
3027 GLsizei count,
3028 const GLchar *const *varyings,
3029 GLenum bufferMode)
3030{
3031 if (context->getClientMajorVersion() < 3)
3032 {
3033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3034 return false;
3035 }
3036
3037 if (count < 0)
3038 {
3039 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3040 return false;
3041 }
3042
3043 switch (bufferMode)
3044 {
3045 case GL_INTERLEAVED_ATTRIBS:
3046 break;
3047 case GL_SEPARATE_ATTRIBS:
3048 {
3049 const Caps &caps = context->getCaps();
3050 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3051 {
3052 context->handleError(InvalidValue());
3053 return false;
3054 }
3055 break;
3056 }
3057 default:
3058 context->handleError(InvalidEnum());
3059 return false;
3060 }
3061
3062 Program *programObject = GetValidProgram(context, program);
3063 if (!programObject)
3064 {
3065 return false;
3066 }
3067
3068 return true;
3069}
3070
3071bool ValidateGetTransformFeedbackVarying(Context *context,
3072 GLuint program,
3073 GLuint index,
3074 GLsizei bufSize,
3075 GLsizei *length,
3076 GLsizei *size,
3077 GLenum *type,
3078 GLchar *name)
3079{
3080 if (context->getClientMajorVersion() < 3)
3081 {
3082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3083 return false;
3084 }
3085
3086 if (bufSize < 0)
3087 {
3088 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3089 return false;
3090 }
3091
3092 Program *programObject = GetValidProgram(context, program);
3093 if (!programObject)
3094 {
3095 return false;
3096 }
3097
3098 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3099 {
3100 context->handleError(InvalidValue());
3101 return false;
3102 }
3103
3104 return true;
3105}
3106
3107bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3108{
3109 if (context->getClientMajorVersion() < 3)
3110 {
3111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3112 return false;
3113 }
3114
3115 switch (target)
3116 {
3117 case GL_TRANSFORM_FEEDBACK:
3118 {
3119 // Cannot bind a transform feedback object if the current one is started and not
3120 // paused (3.0.2 pg 85 section 2.14.1)
3121 TransformFeedback *curTransformFeedback =
3122 context->getGLState().getCurrentTransformFeedback();
3123 if (curTransformFeedback && curTransformFeedback->isActive() &&
3124 !curTransformFeedback->isPaused())
3125 {
3126 context->handleError(InvalidOperation());
3127 return false;
3128 }
3129
3130 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3131 // 2.14.1)
3132 if (!context->isTransformFeedbackGenerated(id))
3133 {
3134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3135 return false;
3136 }
3137 }
3138 break;
3139
3140 default:
3141 context->handleError(InvalidEnum());
3142 return false;
3143 }
3144
3145 return true;
3146}
3147
3148bool ValidateIsTransformFeedback(Context *context, GLuint id)
3149{
3150 if (context->getClientMajorVersion() < 3)
3151 {
3152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3153 return false;
3154 }
3155
3156 return true;
3157}
3158
3159bool ValidatePauseTransformFeedback(Context *context)
3160{
3161 if (context->getClientMajorVersion() < 3)
3162 {
3163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3164 return false;
3165 }
3166
3167 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3168 ASSERT(transformFeedback != nullptr);
3169
3170 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3171 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3172 {
3173 context->handleError(InvalidOperation());
3174 return false;
3175 }
3176
3177 return true;
3178}
3179
3180bool ValidateResumeTransformFeedback(Context *context)
3181{
3182 if (context->getClientMajorVersion() < 3)
3183 {
3184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3185 return false;
3186 }
3187
3188 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3189 ASSERT(transformFeedback != nullptr);
3190
3191 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3192 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3193 {
3194 context->handleError(InvalidOperation());
3195 return false;
3196 }
3197
3198 return true;
3199}
3200
Jamie Madill12e957f2017-08-26 21:42:26 -04003201bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3202{
3203 if (context->getClientMajorVersion() < 3)
3204 {
3205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3206 return false;
3207 }
3208
3209 return ValidateVertexAttribIndex(context, index);
3210}
3211
3212bool ValidateVertexAttribI4ui(Context *context,
3213 GLuint index,
3214 GLuint x,
3215 GLuint y,
3216 GLuint z,
3217 GLuint w)
3218{
3219 if (context->getClientMajorVersion() < 3)
3220 {
3221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3222 return false;
3223 }
3224
3225 return ValidateVertexAttribIndex(context, index);
3226}
3227
3228bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3229{
3230 if (context->getClientMajorVersion() < 3)
3231 {
3232 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3233 return false;
3234 }
3235
3236 return ValidateVertexAttribIndex(context, index);
3237}
3238
3239bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3240{
3241 if (context->getClientMajorVersion() < 3)
3242 {
3243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3244 return false;
3245 }
3246
3247 return ValidateVertexAttribIndex(context, index);
3248}
3249
3250bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3251{
3252 if (context->getClientMajorVersion() < 3)
3253 {
3254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3255 return false;
3256 }
3257
3258 Program *programObject = GetValidProgram(context, program);
3259 if (!programObject)
3260 {
3261 return false;
3262 }
3263
3264 if (!programObject->isLinked())
3265 {
3266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3267 return false;
3268 }
3269
3270 return true;
3271}
3272
3273bool ValidateGetUniformIndices(Context *context,
3274 GLuint program,
3275 GLsizei uniformCount,
3276 const GLchar *const *uniformNames,
3277 GLuint *uniformIndices)
3278{
3279 if (context->getClientMajorVersion() < 3)
3280 {
3281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3282 return false;
3283 }
3284
3285 if (uniformCount < 0)
3286 {
3287 context->handleError(InvalidValue());
3288 return false;
3289 }
3290
3291 Program *programObject = GetValidProgram(context, program);
3292 if (!programObject)
3293 {
3294 return false;
3295 }
3296
3297 return true;
3298}
3299
3300bool ValidateGetActiveUniformsiv(Context *context,
3301 GLuint program,
3302 GLsizei uniformCount,
3303 const GLuint *uniformIndices,
3304 GLenum pname,
3305 GLint *params)
3306{
3307 if (context->getClientMajorVersion() < 3)
3308 {
3309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3310 return false;
3311 }
3312
3313 if (uniformCount < 0)
3314 {
3315 context->handleError(InvalidValue());
3316 return false;
3317 }
3318
3319 Program *programObject = GetValidProgram(context, program);
3320 if (!programObject)
3321 {
3322 return false;
3323 }
3324
3325 switch (pname)
3326 {
3327 case GL_UNIFORM_TYPE:
3328 case GL_UNIFORM_SIZE:
3329 case GL_UNIFORM_NAME_LENGTH:
3330 case GL_UNIFORM_BLOCK_INDEX:
3331 case GL_UNIFORM_OFFSET:
3332 case GL_UNIFORM_ARRAY_STRIDE:
3333 case GL_UNIFORM_MATRIX_STRIDE:
3334 case GL_UNIFORM_IS_ROW_MAJOR:
3335 break;
3336
3337 default:
3338 context->handleError(InvalidEnum());
3339 return false;
3340 }
3341
3342 if (uniformCount > programObject->getActiveUniformCount())
3343 {
3344 context->handleError(InvalidValue());
3345 return false;
3346 }
3347
3348 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3349 {
3350 const GLuint index = uniformIndices[uniformId];
3351
3352 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3353 {
3354 context->handleError(InvalidValue());
3355 return false;
3356 }
3357 }
3358
3359 return true;
3360}
3361
3362bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3363{
3364 if (context->getClientMajorVersion() < 3)
3365 {
3366 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3367 return false;
3368 }
3369
3370 Program *programObject = GetValidProgram(context, program);
3371 if (!programObject)
3372 {
3373 return false;
3374 }
3375
3376 return true;
3377}
3378
3379bool ValidateGetActiveUniformBlockiv(Context *context,
3380 GLuint program,
3381 GLuint uniformBlockIndex,
3382 GLenum pname,
3383 GLint *params)
3384{
3385 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3386}
3387
3388bool ValidateGetActiveUniformBlockName(Context *context,
3389 GLuint program,
3390 GLuint uniformBlockIndex,
3391 GLsizei bufSize,
3392 GLsizei *length,
3393 GLchar *uniformBlockName)
3394{
3395 if (context->getClientMajorVersion() < 3)
3396 {
3397 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3398 return false;
3399 }
3400
3401 Program *programObject = GetValidProgram(context, program);
3402 if (!programObject)
3403 {
3404 return false;
3405 }
3406
3407 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3408 {
3409 context->handleError(InvalidValue());
3410 return false;
3411 }
3412
3413 return true;
3414}
3415
3416bool ValidateUniformBlockBinding(Context *context,
3417 GLuint program,
3418 GLuint uniformBlockIndex,
3419 GLuint uniformBlockBinding)
3420{
3421 if (context->getClientMajorVersion() < 3)
3422 {
3423 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3424 return false;
3425 }
3426
3427 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3428 {
3429 context->handleError(InvalidValue());
3430 return false;
3431 }
3432
3433 Program *programObject = GetValidProgram(context, program);
3434 if (!programObject)
3435 {
3436 return false;
3437 }
3438
3439 // if never linked, there won't be any uniform blocks
3440 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3441 {
3442 context->handleError(InvalidValue());
3443 return false;
3444 }
3445
3446 return true;
3447}
3448
3449bool ValidateDrawArraysInstanced(Context *context,
3450 GLenum mode,
3451 GLint first,
3452 GLsizei count,
3453 GLsizei primcount)
3454{
3455 if (context->getClientMajorVersion() < 3)
3456 {
3457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3458 return false;
3459 }
3460
3461 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3462}
3463
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003464bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3465{
3466 if (context->getClientMajorVersion() < 3)
3467 {
3468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3469 return false;
3470 }
3471
3472 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3473 {
3474 context->handleError(InvalidEnum());
3475 return false;
3476 }
3477
3478 if (flags != 0)
3479 {
3480 context->handleError(InvalidValue());
3481 return false;
3482 }
3483
3484 return true;
3485}
3486
3487bool ValidateIsSync(Context *context, GLsync sync)
3488{
3489 if (context->getClientMajorVersion() < 3)
3490 {
3491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3492 return false;
3493 }
3494
3495 return true;
3496}
3497
3498bool ValidateDeleteSync(Context *context, GLsync sync)
3499{
3500 if (context->getClientMajorVersion() < 3)
3501 {
3502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3503 return false;
3504 }
3505
Jamie Madill70b5bb02017-08-28 13:32:37 -04003506 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003507 {
3508 context->handleError(InvalidValue());
3509 return false;
3510 }
3511
3512 return true;
3513}
3514
3515bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3516{
3517 if (context->getClientMajorVersion() < 3)
3518 {
3519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3520 return false;
3521 }
3522
3523 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3524 {
3525 context->handleError(InvalidValue());
3526 return false;
3527 }
3528
Jamie Madill70b5bb02017-08-28 13:32:37 -04003529 Sync *clientWaitSync = context->getSync(sync);
3530 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003531 {
3532 context->handleError(InvalidValue());
3533 return false;
3534 }
3535
3536 return true;
3537}
3538
3539bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3540{
3541 if (context->getClientMajorVersion() < 3)
3542 {
3543 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3544 return false;
3545 }
3546
3547 if (flags != 0)
3548 {
3549 context->handleError(InvalidValue());
3550 return false;
3551 }
3552
3553 if (timeout != GL_TIMEOUT_IGNORED)
3554 {
3555 context->handleError(InvalidValue());
3556 return false;
3557 }
3558
Jamie Madill70b5bb02017-08-28 13:32:37 -04003559 Sync *waitSync = context->getSync(sync);
3560 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003561 {
3562 context->handleError(InvalidValue());
3563 return false;
3564 }
3565
3566 return true;
3567}
3568
3569bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3570{
3571 if (context->getClientMajorVersion() < 3)
3572 {
3573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3574 return false;
3575 }
3576
3577 GLenum nativeType = GL_NONE;
3578 unsigned int numParams = 0;
3579 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3580 {
3581 return false;
3582 }
3583
3584 return true;
3585}
3586
Jamie Madill3ef140a2017-08-26 23:11:21 -04003587bool ValidateIsSampler(Context *context, GLuint sampler)
3588{
3589 if (context->getClientMajorVersion() < 3)
3590 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003592 return false;
3593 }
3594
3595 return true;
3596}
3597
3598bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3599{
3600 if (context->getClientMajorVersion() < 3)
3601 {
3602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3603 return false;
3604 }
3605
3606 if (sampler != 0 && !context->isSampler(sampler))
3607 {
3608 context->handleError(InvalidOperation());
3609 return false;
3610 }
3611
3612 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3613 {
3614 context->handleError(InvalidValue());
3615 return false;
3616 }
3617
3618 return true;
3619}
3620
3621bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3622{
3623 if (context->getClientMajorVersion() < 3)
3624 {
3625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3626 return false;
3627 }
3628
3629 return ValidateVertexAttribIndex(context, index);
3630}
3631
3632bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003633 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003634 GLsizei levels,
3635 GLenum internalformat,
3636 GLsizei width,
3637 GLsizei height)
3638{
3639 if (context->getClientMajorVersion() < 3)
3640 {
3641 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3642 return false;
3643 }
3644
3645 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3646 1))
3647 {
3648 return false;
3649 }
3650
3651 return true;
3652}
3653
3654bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003655 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003656 GLsizei levels,
3657 GLenum internalformat,
3658 GLsizei width,
3659 GLsizei height,
3660 GLsizei depth)
3661{
3662 if (context->getClientMajorVersion() < 3)
3663 {
3664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3665 return false;
3666 }
3667
3668 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3669 depth))
3670 {
3671 return false;
3672 }
3673
3674 return true;
3675}
3676
Jamie Madill5b772312018-03-08 20:28:32 -05003677bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003678 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003679 GLenum pname,
3680 GLint64 *params)
3681{
3682 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3683}
3684
3685bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3686{
3687 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3688}
3689
3690bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3691{
3692 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3693}
3694
3695bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3696{
3697 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3698}
3699
3700bool ValidateSamplerParameterfv(Context *context,
3701 GLuint sampler,
3702 GLenum pname,
3703 const GLfloat *params)
3704{
3705 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3706}
3707
3708bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3709{
3710 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3711}
3712
3713bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3714{
3715 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3716}
3717
3718bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3719{
3720 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3721}
3722
3723bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3724{
3725 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3726}
3727
3728bool ValidateGetInternalformativ(Context *context,
3729 GLenum target,
3730 GLenum internalformat,
3731 GLenum pname,
3732 GLsizei bufSize,
3733 GLint *params)
3734{
3735 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3736 nullptr);
3737}
3738
Jamie Madillc29968b2016-01-20 11:17:23 -05003739} // namespace gl