blob: 284048297cf22625d1d58f87ac1eddfb035a8188 [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 Madilldd43e6c2017-03-24 14:18:49 -0400811 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500813 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400815 }
816
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400817 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500819 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400821 }
822
Jamie Madill0c8abca2016-07-22 20:21:26 -0400823 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824
825 if (isSubImage)
826 {
Geoff Langca271392017-04-05 12:30:00 -0400827 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500828 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500830 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400831 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 }
833 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400834 else
835 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400836 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400837 const InternalFormat &framebufferFormat = *source->getFormat().info;
838 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400839 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500841 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400843 }
844 }
845
Geoff Lang784a8fd2013-09-24 12:33:16 -0400846 // If width or height is zero, it is a no-op. Return false without setting an error.
847 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848}
849
Jamie Madill5b772312018-03-08 20:28:32 -0500850bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800851 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500852 GLint level,
853 GLenum internalformat,
854 bool isSubImage,
855 GLint xoffset,
856 GLint yoffset,
857 GLint zoffset,
858 GLint x,
859 GLint y,
860 GLsizei width,
861 GLsizei height,
862 GLint border)
863{
864 if (!ValidTexture2DDestinationTarget(context, target))
865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500866 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500867 return false;
868 }
869
870 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
871 xoffset, yoffset, zoffset, x, y, width, height,
872 border);
873}
874
Jamie Madill5b772312018-03-08 20:28:32 -0500875bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800876 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500877 GLint level,
878 GLenum internalformat,
879 bool isSubImage,
880 GLint xoffset,
881 GLint yoffset,
882 GLint zoffset,
883 GLint x,
884 GLint y,
885 GLsizei width,
886 GLsizei height,
887 GLint border)
888{
889 if (!ValidTexture3DDestinationTarget(context, target))
890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500892 return false;
893 }
894
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800895 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
896 internalformat, isSubImage, xoffset, yoffset,
897 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898}
899
900bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500902 GLsizei levels,
903 GLenum internalformat,
904 GLsizei width,
905 GLsizei height,
906 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907{
908 if (width < 1 || height < 1 || depth < 1 || levels < 1)
909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500910 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 }
913
Geoff Langb92c1332015-09-04 12:54:55 -0400914 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800915 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400916 {
917 maxDim = std::max(maxDim, depth);
918 }
919
920 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500922 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925
Geoff Langaae65a42014-05-26 12:43:44 -0400926 const gl::Caps &caps = context->getCaps();
927
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 switch (target)
929 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800930 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931 {
Geoff Langaae65a42014-05-26 12:43:44 -0400932 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
933 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500935 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 }
938 }
939 break;
940
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800941 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400942 {
943 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
944 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
945 {
946 context->handleError(InvalidValue());
947 return false;
948 }
949 }
950 break;
951
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800952 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 if (width != height)
955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959
Geoff Langaae65a42014-05-26 12:43:44 -0400960 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965 }
966 break;
967
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800968 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 {
Geoff Langaae65a42014-05-26 12:43:44 -0400970 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
971 static_cast<GLuint>(height) > caps.max3DTextureSize ||
972 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500974 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400975 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976 }
977 }
978 break;
979
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800980 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400981 {
Geoff Langaae65a42014-05-26 12:43:44 -0400982 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
983 static_cast<GLuint>(height) > caps.max2DTextureSize ||
984 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500986 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400988 }
989 }
990 break;
991
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 default:
993 UNREACHABLE();
994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400995 }
996
Geoff Lang691e58c2014-12-19 17:03:25 -0500997 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 if (!texture || texture->id() == 0)
999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Geoff Lang69cce582015-09-17 13:20:36 -04001004 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Geoff Langca271392017-04-05 12:30:00 -04001010 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001011 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016
Geoff Langca271392017-04-05 12:30:00 -04001017 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001023 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001024 {
1025 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1026 return false;
1027 }
1028
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 return true;
1030}
1031
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001032bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001033 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001034 GLsizei levels,
1035 GLenum internalformat,
1036 GLsizei width,
1037 GLsizei height,
1038 GLsizei depth)
1039{
1040 if (!ValidTexture2DTarget(context, target))
1041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001042 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001043 return false;
1044 }
1045
1046 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1047 height, depth);
1048}
1049
1050bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001051 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001052 GLsizei levels,
1053 GLenum internalformat,
1054 GLsizei width,
1055 GLsizei height,
1056 GLsizei depth)
1057{
1058 if (!ValidTexture3DTarget(context, target))
1059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001060 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001061 return false;
1062 }
1063
1064 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1065 height, depth);
1066}
1067
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001068bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1069{
Martin Radev1be913c2016-07-11 17:59:16 +03001070 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001071 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001073 return false;
1074 }
1075
1076 return ValidateBeginQueryBase(context, target, id);
1077}
1078
1079bool ValidateEndQuery(gl::Context *context, GLenum target)
1080{
Martin Radev1be913c2016-07-11 17:59:16 +03001081 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001082 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001084 return false;
1085 }
1086
1087 return ValidateEndQueryBase(context, target);
1088}
1089
1090bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1091{
Martin Radev1be913c2016-07-11 17:59:16 +03001092 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001095 return false;
1096 }
1097
Geoff Lang2186c382016-10-14 10:54:54 -04001098 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001099}
1100
1101bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1102{
Martin Radev1be913c2016-07-11 17:59:16 +03001103 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001104 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001106 return false;
1107 }
1108
Geoff Lang2186c382016-10-14 10:54:54 -04001109 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001110}
1111
He Yunchaoced53ae2016-11-29 15:00:51 +08001112bool ValidateFramebufferTextureLayer(Context *context,
1113 GLenum target,
1114 GLenum attachment,
1115 GLuint texture,
1116 GLint level,
1117 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001118{
Martin Radev1be913c2016-07-11 17:59:16 +03001119 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001120 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001122 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001123 }
1124
Jamie Madill55ec3b12014-07-03 10:38:57 -04001125 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1126 {
1127 return false;
1128 }
1129
1130 const gl::Caps &caps = context->getCaps();
1131 if (texture != 0)
1132 {
Geoff Lang23e02842017-10-17 13:24:09 -04001133 if (layer < 0)
1134 {
1135 context->handleError(InvalidValue());
1136 return false;
1137 }
1138
Jamie Madill55ec3b12014-07-03 10:38:57 -04001139 gl::Texture *tex = context->getTexture(texture);
1140 ASSERT(tex);
1141
Corentin Wallez99d492c2018-02-27 15:17:10 -05001142 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001143 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001144 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001145 {
1146 if (level > gl::log2(caps.max2DTextureSize))
1147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001150 }
1151
1152 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001156 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001157 }
1158 break;
1159
Corentin Wallez99d492c2018-02-27 15:17:10 -05001160 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001161 {
1162 if (level > gl::log2(caps.max3DTextureSize))
1163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001166 }
1167
1168 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001172 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001173 }
1174 break;
1175
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001177 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001179 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001180
Corentin Wallez99d492c2018-02-27 15:17:10 -05001181 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001182 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001184 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001185 return false;
1186 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001187 }
1188
1189 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001190}
1191
He Yunchaoced53ae2016-11-29 15:00:51 +08001192bool ValidateInvalidateFramebuffer(Context *context,
1193 GLenum target,
1194 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001195 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001196{
Martin Radev1be913c2016-07-11 17:59:16 +03001197 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001198 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001200 return false;
1201 }
1202
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 bool defaultFramebuffer = false;
1204
1205 switch (target)
1206 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001207 case GL_DRAW_FRAMEBUFFER:
1208 case GL_FRAMEBUFFER:
1209 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1210 break;
1211 case GL_READ_FRAMEBUFFER:
1212 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1213 break;
1214 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
He Yunchaoced53ae2016-11-29 15:00:51 +08001219 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1220 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001221}
1222
Jamie Madill3ef140a2017-08-26 23:11:21 -04001223bool ValidateInvalidateSubFramebuffer(Context *context,
1224 GLenum target,
1225 GLsizei numAttachments,
1226 const GLenum *attachments,
1227 GLint x,
1228 GLint y,
1229 GLsizei width,
1230 GLsizei height)
1231{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001232 if (width < 0 || height < 0)
1233 {
1234 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1235 return false;
1236 }
1237
Jamie Madill3ef140a2017-08-26 23:11:21 -04001238 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1239}
1240
Jamie Madill5b772312018-03-08 20:28:32 -05001241bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001242{
Martin Radev1be913c2016-07-11 17:59:16 +03001243 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001244 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001246 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001247 }
1248
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001249 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001251 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001253 }
1254
1255 return true;
1256}
1257
Olli Etuaho71dfb362016-03-10 14:04:27 +02001258bool ValidateDrawRangeElements(Context *context,
1259 GLenum mode,
1260 GLuint start,
1261 GLuint end,
1262 GLsizei count,
1263 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001264 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001265{
Martin Radev1be913c2016-07-11 17:59:16 +03001266 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001267 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001269 return false;
1270 }
1271
1272 if (end < start)
1273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001275 return false;
1276 }
1277
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001278 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001279 {
1280 return false;
1281 }
1282
Jamie Madill9fdaa492018-02-16 10:52:11 -05001283 // Skip range checks for no-op calls.
1284 if (count <= 0)
1285 {
1286 return true;
1287 }
1288
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001289 // Use the parameter buffer to retrieve and cache the index range.
1290 const auto &params = context->getParams<HasIndexRange>();
1291 const auto &indexRangeOpt = params.getIndexRange();
1292 if (!indexRangeOpt.valid())
1293 {
1294 // Unexpected error.
1295 return false;
1296 }
1297
1298 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001299 {
1300 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001301 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001302 return false;
1303 }
1304 return true;
1305}
1306
He Yunchaoced53ae2016-11-29 15:00:51 +08001307bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001308{
Martin Radev1be913c2016-07-11 17:59:16 +03001309 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001310 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001312 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001313 }
1314
Jamie Madill78f41802014-08-25 15:47:55 -04001315 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001316}
1317
Jamie Madillb885e572015-02-03 16:16:04 -05001318bool ValidateReadBuffer(Context *context, GLenum src)
1319{
Martin Radev1be913c2016-07-11 17:59:16 +03001320 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001321 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001323 return false;
1324 }
1325
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001326 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001327
1328 if (readFBO == nullptr)
1329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001330 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001331 return false;
1332 }
1333
1334 if (src == GL_NONE)
1335 {
1336 return true;
1337 }
1338
Olli Etuaho84c9f592016-03-09 14:37:25 +02001339 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001341 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001342 return false;
1343 }
1344
1345 if (readFBO->id() == 0)
1346 {
1347 if (src != GL_BACK)
1348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(
1350 InvalidOperation()
1351 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001352 return false;
1353 }
1354 }
1355 else
1356 {
1357 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1358
1359 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001362 return false;
1363 }
1364 }
1365
1366 return true;
1367}
1368
Jamie Madill86af3d22015-07-21 15:14:07 -04001369bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001370 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001371 GLint level,
1372 GLenum internalformat,
1373 GLsizei width,
1374 GLsizei height,
1375 GLsizei depth,
1376 GLint border,
1377 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001378 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001379{
Martin Radev1be913c2016-07-11 17:59:16 +03001380 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001381 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001382 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 return false;
1384 }
1385
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001386 if (!ValidTextureTarget(context, target))
1387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001388 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001389 return false;
1390 }
1391
Jamie Madille2e406c2016-06-02 13:04:10 -04001392 // Validate image size
1393 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001396 return false;
1397 }
1398
Geoff Langca271392017-04-05 12:30:00 -04001399 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001400 if (!formatInfo.compressed)
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001403 return false;
1404 }
1405
Jeff Gilbert48590352017-11-07 16:03:38 -08001406 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001407 if (blockSizeOrErr.isError())
1408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001409 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001410 return false;
1411 }
1412 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001414 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001415 return false;
1416 }
1417
1418 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001419 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001422 return false;
1423 }
1424
1425 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001426 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001427 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1428 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001429 {
1430 return false;
1431 }
1432
1433 return true;
1434}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001435
Corentin Wallezb2931602017-04-11 15:58:57 -04001436bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001437 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001438 GLint level,
1439 GLenum internalformat,
1440 GLsizei width,
1441 GLsizei height,
1442 GLsizei depth,
1443 GLint border,
1444 GLsizei imageSize,
1445 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001446 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001447{
1448 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1449 {
1450 return false;
1451 }
1452
1453 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1454 depth, border, imageSize, data);
1455}
1456
Austin Kinrossbc781f32015-10-26 09:27:38 -07001457bool ValidateBindVertexArray(Context *context, GLuint array)
1458{
Martin Radev1be913c2016-07-11 17:59:16 +03001459 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001460 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001461 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001462 return false;
1463 }
1464
1465 return ValidateBindVertexArrayBase(context, array);
1466}
1467
Jamie Madilld7576732017-08-26 18:49:50 -04001468bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001469{
Martin Radev1be913c2016-07-11 17:59:16 +03001470 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001471 {
Jamie Madilld7576732017-08-26 18:49:50 -04001472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001473 return false;
1474 }
1475
1476 return true;
1477}
Geoff Langc5629752015-12-07 16:29:04 -05001478
Jiajia Qin6eafb042016-12-27 17:04:07 +08001479static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001480 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001481 GLuint index,
1482 GLuint buffer,
1483 GLintptr offset,
1484 GLsizeiptr size)
1485{
1486 if (context->getClientMajorVersion() < 3)
1487 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001489 return false;
1490 }
1491
1492 if (buffer != 0 && offset < 0)
1493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001494 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001495 return false;
1496 }
1497
1498 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1499 !context->isBufferGenerated(buffer))
1500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001501 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001502 return false;
1503 }
1504
1505 const Caps &caps = context->getCaps();
1506 switch (target)
1507 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001508 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001509 {
1510 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001512 context->handleError(InvalidValue() << "index is greater than or equal to the "
1513 "number of TRANSFORM_FEEDBACK_BUFFER "
1514 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001515 return false;
1516 }
1517 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001520 return false;
1521 }
1522
1523 TransformFeedback *curTransformFeedback =
1524 context->getGLState().getCurrentTransformFeedback();
1525 if (curTransformFeedback && curTransformFeedback->isActive())
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidOperation()
1528 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1529 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001530 return false;
1531 }
1532 break;
1533 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001534 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001535 {
1536 if (index >= caps.maxUniformBufferBindings)
1537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidValue() << "index is greater than or equal to the "
1539 "number of UNIFORM_BUFFER indexed "
1540 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001541 return false;
1542 }
1543
1544 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1545 {
1546 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 InvalidValue()
1548 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001549 return false;
1550 }
1551 break;
1552 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001553 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001554 {
1555 if (context->getClientVersion() < ES_3_1)
1556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001557 context->handleError(InvalidEnum()
1558 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001559 return false;
1560 }
1561 if (index >= caps.maxAtomicCounterBufferBindings)
1562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidValue() << "index is greater than or equal to the "
1564 "number of ATOMIC_COUNTER_BUFFER "
1565 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001566 return false;
1567 }
1568 if (buffer != 0 && (offset % 4) != 0)
1569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001571 return false;
1572 }
1573 break;
1574 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001575 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001576 {
1577 if (context->getClientVersion() < ES_3_1)
1578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001579 context->handleError(InvalidEnum()
1580 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001581 return false;
1582 }
1583 if (index >= caps.maxShaderStorageBufferBindings)
1584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001585 context->handleError(InvalidValue() << "index is greater than or equal to the "
1586 "number of SHADER_STORAGE_BUFFER "
1587 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001588 return false;
1589 }
1590 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001592 context->handleError(InvalidValue() << "offset must be multiple of value of "
1593 "SHADER_STORAGE_BUFFER_OFFSET_"
1594 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001595 return false;
1596 }
1597 break;
1598 }
1599 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001600 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001601 return false;
1602 }
1603
1604 return true;
1605}
1606
Corentin Wallez336129f2017-10-17 15:55:40 -04001607bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001608{
1609 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1610}
1611
1612bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001613 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001614 GLuint index,
1615 GLuint buffer,
1616 GLintptr offset,
1617 GLsizeiptr size)
1618{
1619 if (buffer != 0 && size <= 0)
1620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001621 context->handleError(InvalidValue()
1622 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001623 return false;
1624 }
1625 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1626}
1627
Geoff Langc5629752015-12-07 16:29:04 -05001628bool ValidateProgramBinary(Context *context,
1629 GLuint program,
1630 GLenum binaryFormat,
1631 const void *binary,
1632 GLint length)
1633{
Martin Radev1be913c2016-07-11 17:59:16 +03001634 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001635 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001637 return false;
1638 }
1639
1640 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1641}
1642
1643bool ValidateGetProgramBinary(Context *context,
1644 GLuint program,
1645 GLsizei bufSize,
1646 GLsizei *length,
1647 GLenum *binaryFormat,
1648 void *binary)
1649{
Martin Radev1be913c2016-07-11 17:59:16 +03001650 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001651 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001653 return false;
1654 }
1655
1656 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1657}
1658
Olli Etuahof0fee072016-03-30 15:11:58 +03001659bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001660{
Martin Radev1be913c2016-07-11 17:59:16 +03001661 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001662 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001664 return false;
1665 }
1666
1667 if (GetValidProgram(context, program) == nullptr)
1668 {
1669 return false;
1670 }
1671
1672 switch (pname)
1673 {
1674 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001675 if (value != GL_FALSE && value != GL_TRUE)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidValue()
1678 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001679 return false;
1680 }
Geoff Langc5629752015-12-07 16:29:04 -05001681 break;
1682
Yunchao He61afff12017-03-14 15:34:03 +08001683 case GL_PROGRAM_SEPARABLE:
1684 if (context->getClientVersion() < ES_3_1)
1685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001686 context->handleError(InvalidEnum()
1687 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001688 return false;
1689 }
1690
1691 if (value != GL_FALSE && value != GL_TRUE)
1692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001693 context->handleError(InvalidValue()
1694 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001695 return false;
1696 }
1697 break;
1698
Geoff Langc5629752015-12-07 16:29:04 -05001699 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001700 context->handleError(InvalidEnum()
1701 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001702 return false;
1703 }
1704
1705 return true;
1706}
Jamie Madillc29968b2016-01-20 11:17:23 -05001707
1708bool ValidateBlitFramebuffer(Context *context,
1709 GLint srcX0,
1710 GLint srcY0,
1711 GLint srcX1,
1712 GLint srcY1,
1713 GLint dstX0,
1714 GLint dstY0,
1715 GLint dstX1,
1716 GLint dstY1,
1717 GLbitfield mask,
1718 GLenum filter)
1719{
Martin Radev1be913c2016-07-11 17:59:16 +03001720 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001721 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 return false;
1724 }
1725
1726 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1727 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728}
Jamie Madillc29968b2016-01-20 11:17:23 -05001729
Jamie Madill5b772312018-03-08 20:28:32 -05001730bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001731{
1732 switch (buffer)
1733 {
1734 case GL_COLOR:
1735 if (drawbuffer < 0 ||
1736 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001738 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001739 return false;
1740 }
Geoff Lang76e65652017-03-27 14:58:02 -04001741 if (context->getExtensions().webglCompatibility)
1742 {
1743 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001744 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001745 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1746 {
1747 return false;
1748 }
1749 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 break;
1751
1752 case GL_STENCIL:
1753 if (drawbuffer != 0)
1754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001756 return false;
1757 }
1758 break;
1759
1760 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001762 return false;
1763 }
1764
1765 return ValidateClearBuffer(context);
1766}
1767
Jamie Madill5b772312018-03-08 20:28:32 -05001768bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001769{
1770 switch (buffer)
1771 {
1772 case GL_COLOR:
1773 if (drawbuffer < 0 ||
1774 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001776 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001777 return false;
1778 }
Geoff Lang76e65652017-03-27 14:58:02 -04001779 if (context->getExtensions().webglCompatibility)
1780 {
1781 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001782 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001783 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1784 {
1785 return false;
1786 }
1787 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001788 break;
1789
1790 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001791 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 return false;
1793 }
1794
1795 return ValidateClearBuffer(context);
1796}
1797
Jamie Madill5b772312018-03-08 20:28:32 -05001798bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001799{
1800 switch (buffer)
1801 {
1802 case GL_COLOR:
1803 if (drawbuffer < 0 ||
1804 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001806 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001807 return false;
1808 }
Geoff Lang76e65652017-03-27 14:58:02 -04001809 if (context->getExtensions().webglCompatibility)
1810 {
1811 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1812 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001813 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001814 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1815 {
1816 return false;
1817 }
1818 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001819 break;
1820
1821 case GL_DEPTH:
1822 if (drawbuffer != 0)
1823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001824 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001825 return false;
1826 }
1827 break;
1828
1829 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001830 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001831 return false;
1832 }
1833
1834 return ValidateClearBuffer(context);
1835}
1836
Jamie Madill5b772312018-03-08 20:28:32 -05001837bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001838 GLenum buffer,
1839 GLint drawbuffer,
1840 GLfloat depth,
1841 GLint stencil)
1842{
1843 switch (buffer)
1844 {
1845 case GL_DEPTH_STENCIL:
1846 if (drawbuffer != 0)
1847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001848 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 return false;
1850 }
1851 break;
1852
1853 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001854 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001855 return false;
1856 }
1857
1858 return ValidateClearBuffer(context);
1859}
1860
Jamie Madill5b772312018-03-08 20:28:32 -05001861bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001862{
Martin Radev1be913c2016-07-11 17:59:16 +03001863 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001866 return false;
1867 }
1868
1869 return ValidateDrawBuffersBase(context, n, bufs);
1870}
1871
1872bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001873 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001874 GLint level,
1875 GLint xoffset,
1876 GLint yoffset,
1877 GLint zoffset,
1878 GLint x,
1879 GLint y,
1880 GLsizei width,
1881 GLsizei height)
1882{
Martin Radev1be913c2016-07-11 17:59:16 +03001883 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001884 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001885 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 return false;
1887 }
1888
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001889 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1890 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001891}
1892
Jamie Madill73a84962016-02-12 09:27:23 -05001893bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001894 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001895 GLint level,
1896 GLint internalformat,
1897 GLsizei width,
1898 GLsizei height,
1899 GLsizei depth,
1900 GLint border,
1901 GLenum format,
1902 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001903 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001904{
Martin Radev1be913c2016-07-11 17:59:16 +03001905 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001906 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001908 return false;
1909 }
1910
1911 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001912 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001913 pixels);
1914}
1915
Geoff Langc52f6f12016-10-14 10:18:00 -04001916bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001917 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001918 GLint level,
1919 GLint internalformat,
1920 GLsizei width,
1921 GLsizei height,
1922 GLsizei depth,
1923 GLint border,
1924 GLenum format,
1925 GLenum type,
1926 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001927 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001928{
1929 if (context->getClientMajorVersion() < 3)
1930 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001932 return false;
1933 }
1934
1935 if (!ValidateRobustEntryPoint(context, bufSize))
1936 {
1937 return false;
1938 }
1939
1940 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1941 0, 0, width, height, depth, border, format, type,
1942 bufSize, pixels);
1943}
1944
Jamie Madill73a84962016-02-12 09:27:23 -05001945bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001946 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001947 GLint level,
1948 GLint xoffset,
1949 GLint yoffset,
1950 GLint zoffset,
1951 GLsizei width,
1952 GLsizei height,
1953 GLsizei depth,
1954 GLenum format,
1955 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001956 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001957{
Martin Radev1be913c2016-07-11 17:59:16 +03001958 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001959 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001961 return false;
1962 }
1963
1964 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1965 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001966 -1, pixels);
1967}
1968
1969bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001970 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001971 GLint level,
1972 GLint xoffset,
1973 GLint yoffset,
1974 GLint zoffset,
1975 GLsizei width,
1976 GLsizei height,
1977 GLsizei depth,
1978 GLenum format,
1979 GLenum type,
1980 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001981 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001982{
1983 if (context->getClientMajorVersion() < 3)
1984 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001986 return false;
1987 }
1988
1989 if (!ValidateRobustEntryPoint(context, bufSize))
1990 {
1991 return false;
1992 }
1993
1994 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1995 yoffset, zoffset, width, height, depth, 0, format, type,
1996 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001997}
1998
1999bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002000 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002001 GLint level,
2002 GLint xoffset,
2003 GLint yoffset,
2004 GLint zoffset,
2005 GLsizei width,
2006 GLsizei height,
2007 GLsizei depth,
2008 GLenum format,
2009 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002010 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002011{
Martin Radev1be913c2016-07-11 17:59:16 +03002012 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002013 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002014 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002015 return false;
2016 }
2017
Geoff Langca271392017-04-05 12:30:00 -04002018 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002019 if (!formatInfo.compressed)
2020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002021 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002022 return false;
2023 }
2024
Jeff Gilbert48590352017-11-07 16:03:38 -08002025 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002026 if (blockSizeOrErr.isError())
2027 {
2028 context->handleError(blockSizeOrErr.getError());
2029 return false;
2030 }
2031 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002033 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002034 return false;
2035 }
2036
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002037 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2038 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2039 -1, data))
2040 {
2041 return false;
2042 }
2043
Jamie Madill73a84962016-02-12 09:27:23 -05002044 if (!data)
2045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002046 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002047 return false;
2048 }
2049
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002050 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002051}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002052
Corentin Wallezb2931602017-04-11 15:58:57 -04002053bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002054 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002055 GLint level,
2056 GLint xoffset,
2057 GLint yoffset,
2058 GLint zoffset,
2059 GLsizei width,
2060 GLsizei height,
2061 GLsizei depth,
2062 GLenum format,
2063 GLsizei imageSize,
2064 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002065 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002066{
2067 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2068 {
2069 return false;
2070 }
2071
2072 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2073 height, depth, format, imageSize, data);
2074}
Jamie Madill73a84962016-02-12 09:27:23 -05002075
Olli Etuaho41997e72016-03-10 13:38:39 +02002076bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2077{
2078 return ValidateGenOrDeleteES3(context, n);
2079}
2080
2081bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2082{
2083 return ValidateGenOrDeleteES3(context, n);
2084}
2085
2086bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2087{
2088 return ValidateGenOrDeleteCountES3(context, count);
2089}
2090
2091bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2092{
2093 return ValidateGenOrDeleteCountES3(context, count);
2094}
2095
2096bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2097{
2098 return ValidateGenOrDeleteES3(context, n);
2099}
2100
2101bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2102{
2103 if (!ValidateGenOrDeleteES3(context, n))
2104 {
2105 return false;
2106 }
2107 for (GLint i = 0; i < n; ++i)
2108 {
2109 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2110 if (transformFeedback != nullptr && transformFeedback->isActive())
2111 {
2112 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002113 context->handleError(InvalidOperation()
2114 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002115 return false;
2116 }
2117 }
2118 return true;
2119}
2120
2121bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2122{
2123 return ValidateGenOrDeleteES3(context, n);
2124}
2125
2126bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2127{
2128 return ValidateGenOrDeleteES3(context, n);
2129}
2130
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002131bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2132{
Martin Radev1be913c2016-07-11 17:59:16 +03002133 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002134 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002136 return false;
2137 }
2138 switch (primitiveMode)
2139 {
2140 case GL_TRIANGLES:
2141 case GL_LINES:
2142 case GL_POINTS:
2143 break;
2144
2145 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002147 return false;
2148 }
2149
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002150 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002151 ASSERT(transformFeedback != nullptr);
2152
2153 if (transformFeedback->isActive())
2154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002156 return false;
2157 }
Geoff Lang79f71042017-08-14 16:43:43 -04002158
2159 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2160 {
2161 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2162 if (buffer.get() && buffer->isMapped())
2163 {
2164 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2165 return false;
2166 }
2167 }
2168
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002169 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002170
2171 if (!program)
2172 {
2173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2174 return false;
2175 }
2176
2177 if (program->getTransformFeedbackVaryingCount() == 0)
2178 {
2179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2180 return false;
2181 }
2182
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002183 return true;
2184}
2185
Corentin Wallez336129f2017-10-17 15:55:40 -04002186bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002187{
Geoff Lang496c02d2016-10-20 11:38:11 -07002188 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2189}
2190
2191bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002192 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002193 GLenum pname,
2194 GLsizei bufSize,
2195 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002196 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002197{
2198 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002199 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002200 return false;
2201 }
2202
Geoff Lang496c02d2016-10-20 11:38:11 -07002203 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2204 {
2205 return false;
2206 }
2207
2208 if (!ValidateRobustBufferSize(context, bufSize, *length))
2209 {
2210 return false;
2211 }
2212
2213 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002214}
2215
Corentin Wallez336129f2017-10-17 15:55:40 -04002216bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002217{
Martin Radev1be913c2016-07-11 17:59:16 +03002218 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002219 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002220 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002221 return false;
2222 }
2223
2224 return ValidateUnmapBufferBase(context, target);
2225}
2226
2227bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002228 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002229 GLintptr offset,
2230 GLsizeiptr length,
2231 GLbitfield access)
2232{
Martin Radev1be913c2016-07-11 17:59:16 +03002233 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002234 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002236 return false;
2237 }
2238
2239 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2240}
2241
2242bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002243 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002244 GLintptr offset,
2245 GLsizeiptr length)
2246{
Martin Radev1be913c2016-07-11 17:59:16 +03002247 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002248 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002250 return false;
2251 }
2252
2253 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2254}
2255
Jamie Madill5b772312018-03-08 20:28:32 -05002256bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002257{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002258 if (length)
2259 {
2260 *length = 0;
2261 }
2262
Martin Radev66fb8202016-07-28 11:45:20 +03002263 GLenum nativeType;
2264 unsigned int numParams;
2265 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002267 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002268 return false;
2269 }
2270
2271 const Caps &caps = context->getCaps();
2272 switch (pname)
2273 {
2274 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2275 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2276 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2277 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002279 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002280 return false;
2281 }
2282 break;
2283
2284 case GL_UNIFORM_BUFFER_START:
2285 case GL_UNIFORM_BUFFER_SIZE:
2286 case GL_UNIFORM_BUFFER_BINDING:
2287 if (index >= caps.maxUniformBufferBindings)
2288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002289 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002290 return false;
2291 }
2292 break;
Shao80957d92017-02-20 21:25:59 +08002293
Martin Radev66fb8202016-07-28 11:45:20 +03002294 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2295 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2296 if (index >= 3u)
2297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002298 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002299 return false;
2300 }
2301 break;
Shao80957d92017-02-20 21:25:59 +08002302
Jiajia Qin6eafb042016-12-27 17:04:07 +08002303 case GL_ATOMIC_COUNTER_BUFFER_START:
2304 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2305 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2306 if (context->getClientVersion() < ES_3_1)
2307 {
2308 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002309 InvalidEnum()
2310 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002311 return false;
2312 }
2313 if (index >= caps.maxAtomicCounterBufferBindings)
2314 {
2315 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002316 InvalidValue()
2317 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002318 return false;
2319 }
2320 break;
Shao80957d92017-02-20 21:25:59 +08002321
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002322 case GL_SHADER_STORAGE_BUFFER_START:
2323 case GL_SHADER_STORAGE_BUFFER_SIZE:
2324 case GL_SHADER_STORAGE_BUFFER_BINDING:
2325 if (context->getClientVersion() < ES_3_1)
2326 {
2327 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002328 InvalidEnum()
2329 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002330 return false;
2331 }
2332 if (index >= caps.maxShaderStorageBufferBindings)
2333 {
2334 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002335 InvalidValue()
2336 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002337 return false;
2338 }
2339 break;
2340
Shao80957d92017-02-20 21:25:59 +08002341 case GL_VERTEX_BINDING_BUFFER:
2342 case GL_VERTEX_BINDING_DIVISOR:
2343 case GL_VERTEX_BINDING_OFFSET:
2344 case GL_VERTEX_BINDING_STRIDE:
2345 if (context->getClientVersion() < ES_3_1)
2346 {
2347 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002348 InvalidEnum()
2349 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002350 return false;
2351 }
2352 if (index >= caps.maxVertexAttribBindings)
2353 {
2354 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002355 InvalidValue()
2356 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002357 return false;
2358 }
2359 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002360 case GL_SAMPLE_MASK_VALUE:
2361 if (context->getClientVersion() < ES_3_1)
2362 {
2363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2364 return false;
2365 }
2366 if (index >= caps.maxSampleMaskWords)
2367 {
2368 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2369 return false;
2370 }
2371 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002372 case GL_IMAGE_BINDING_NAME:
2373 case GL_IMAGE_BINDING_LEVEL:
2374 case GL_IMAGE_BINDING_LAYERED:
2375 case GL_IMAGE_BINDING_LAYER:
2376 case GL_IMAGE_BINDING_ACCESS:
2377 case GL_IMAGE_BINDING_FORMAT:
2378 if (context->getClientVersion() < ES_3_1)
2379 {
2380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2381 return false;
2382 }
2383 if (index >= caps.maxImageUnits)
2384 {
2385 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2386 return false;
2387 }
2388 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002389 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002390 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002391 return false;
2392 }
2393
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002394 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002395 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002396 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002397 }
2398
2399 return true;
2400}
2401
Jamie Madill5b772312018-03-08 20:28:32 -05002402bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002403{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002404 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002405 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002406 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002407 return false;
2408 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002409 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002410}
2411
Jamie Madill5b772312018-03-08 20:28:32 -05002412bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002413 GLenum target,
2414 GLuint index,
2415 GLsizei bufSize,
2416 GLsizei *length,
2417 GLint *data)
2418{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002419 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002420 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002421 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002422 return false;
2423 }
2424
2425 if (!ValidateRobustEntryPoint(context, bufSize))
2426 {
2427 return false;
2428 }
2429
2430 if (!ValidateIndexedStateQuery(context, target, index, length))
2431 {
2432 return false;
2433 }
2434
2435 if (!ValidateRobustBufferSize(context, bufSize, *length))
2436 {
2437 return false;
2438 }
2439
2440 return true;
2441}
2442
Jamie Madill5b772312018-03-08 20:28:32 -05002443bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002444{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002445 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002446 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002447 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002448 return false;
2449 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002450 return ValidateIndexedStateQuery(context, target, index, nullptr);
2451}
2452
Jamie Madill5b772312018-03-08 20:28:32 -05002453bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002454 GLenum target,
2455 GLuint index,
2456 GLsizei bufSize,
2457 GLsizei *length,
2458 GLint64 *data)
2459{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002460 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002461 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002463 return false;
2464 }
2465
2466 if (!ValidateRobustEntryPoint(context, bufSize))
2467 {
2468 return false;
2469 }
2470
2471 if (!ValidateIndexedStateQuery(context, target, index, length))
2472 {
2473 return false;
2474 }
2475
2476 if (!ValidateRobustBufferSize(context, bufSize, *length))
2477 {
2478 return false;
2479 }
2480
2481 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002482}
2483
Jamie Madill5b772312018-03-08 20:28:32 -05002484bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002485 BufferBinding readTarget,
2486 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002487 GLintptr readOffset,
2488 GLintptr writeOffset,
2489 GLsizeiptr size)
2490{
2491 if (context->getClientMajorVersion() < 3)
2492 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002493 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002494 return false;
2495 }
2496
Corentin Walleze4477002017-12-01 14:39:58 -05002497 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002499 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002500 return false;
2501 }
2502
2503 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2504 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2505
2506 if (!readBuffer || !writeBuffer)
2507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002509 return false;
2510 }
2511
2512 // Verify that readBuffer and writeBuffer are not currently mapped
2513 if (readBuffer->isMapped() || writeBuffer->isMapped())
2514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002515 context->handleError(InvalidOperation()
2516 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002517 return false;
2518 }
2519
James Darpiniane8a93c62018-01-04 18:02:24 -08002520 if (context->getExtensions().webglCompatibility &&
2521 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2522 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2523 {
2524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2525 return false;
2526 }
2527
Jamie Madilld2f0c742016-11-02 10:34:41 -04002528 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2529 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2530 CheckedNumeric<GLintptr> checkedSize(size);
2531
2532 auto checkedReadSum = checkedReadOffset + checkedSize;
2533 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2534
2535 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2536 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2537 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002540 return false;
2541 }
2542
Jamie Madilld2f0c742016-11-02 10:34:41 -04002543 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue()
2546 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002547 return false;
2548 }
2549
Jamie Madilld2f0c742016-11-02 10:34:41 -04002550 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2551 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002553 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002554 return false;
2555 }
2556
2557 if (readBuffer == writeBuffer)
2558 {
2559 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2560 if (!checkedOffsetDiff.IsValid())
2561 {
2562 // This shold not be possible.
2563 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002564 context->handleError(InvalidValue()
2565 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002566 return false;
2567 }
2568
2569 if (checkedOffsetDiff.ValueOrDie() < size)
2570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002571 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002572 return false;
2573 }
2574 }
2575
Jamie Madillb0817d12016-11-01 15:48:31 -04002576 return true;
2577}
2578
Geoff Langc339c4e2016-11-29 10:37:36 -05002579bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2580{
2581 if (context->getClientMajorVersion() < 3)
2582 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002584 return false;
2585 }
2586
2587 switch (name)
2588 {
2589 case GL_EXTENSIONS:
2590 if (index >= context->getExtensionStringCount())
2591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002592 context->handleError(InvalidValue()
2593 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002594 return false;
2595 }
2596 break;
2597
2598 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2599 if (!context->getExtensions().requestExtension)
2600 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002601 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002602 return false;
2603 }
2604 if (index >= context->getRequestableExtensionStringCount())
2605 {
2606 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002607 InvalidValue()
2608 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002609 return false;
2610 }
2611 break;
2612
2613 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002614 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002615 return false;
2616 }
2617
2618 return true;
2619}
2620
Jamie Madill5b772312018-03-08 20:28:32 -05002621bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002622 GLenum target,
2623 GLsizei samples,
2624 GLenum internalformat,
2625 GLsizei width,
2626 GLsizei height)
2627{
2628 if (context->getClientMajorVersion() < 3)
2629 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002631 return false;
2632 }
2633
2634 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2635 height))
2636 {
2637 return false;
2638 }
2639
2640 // 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 +08002641 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2642 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002643 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002644 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002645 {
Yunchao Hec0810202018-01-22 09:48:48 +08002646 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2647 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2648 {
2649 context->handleError(InvalidOperation());
2650 return false;
2651 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002652 }
2653
2654 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2655 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2656 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2657 {
2658 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002659 InvalidOperation()
2660 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002661 return false;
2662 }
2663
2664 return true;
2665}
2666
Jamie Madill5b772312018-03-08 20:28:32 -05002667bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002668 GLuint index,
2669 GLint size,
2670 GLenum type,
2671 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002672 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002673{
2674 if (context->getClientMajorVersion() < 3)
2675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002676 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002677 return false;
2678 }
2679
Shao80957d92017-02-20 21:25:59 +08002680 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002681 {
Geoff Langaa086d62017-03-23 16:47:21 -04002682 return false;
2683 }
2684
Geoff Langaa086d62017-03-23 16:47:21 -04002685 if (stride < 0)
2686 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002687 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002688 return false;
2689 }
2690
Shao80957d92017-02-20 21:25:59 +08002691 const Caps &caps = context->getCaps();
2692 if (context->getClientVersion() >= ES_3_1)
2693 {
2694 if (stride > caps.maxVertexAttribStride)
2695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002696 context->handleError(InvalidValue()
2697 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002698 return false;
2699 }
2700
2701 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2702 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2703 // validation should be inherited.
2704 if (index >= caps.maxVertexAttribBindings)
2705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002706 context->handleError(InvalidValue()
2707 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002708 return false;
2709 }
2710 }
2711
Geoff Langaa086d62017-03-23 16:47:21 -04002712 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2713 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2714 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2715 // and the pointer argument is not NULL.
2716 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002717 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002719 context
2720 ->handleError(InvalidOperation()
2721 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002722 return false;
2723 }
2724
Geoff Lang2d62ab72017-03-23 16:54:40 -04002725 if (context->getExtensions().webglCompatibility)
2726 {
2727 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2728 {
2729 return false;
2730 }
2731 }
2732
Geoff Langaa086d62017-03-23 16:47:21 -04002733 return true;
2734}
2735
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002736bool ValidateGetSynciv(Context *context,
2737 GLsync sync,
2738 GLenum pname,
2739 GLsizei bufSize,
2740 GLsizei *length,
2741 GLint *values)
2742{
2743 if (context->getClientMajorVersion() < 3)
2744 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002746 return false;
2747 }
2748
2749 if (bufSize < 0)
2750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002751 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002752 return false;
2753 }
2754
Jamie Madill70b5bb02017-08-28 13:32:37 -04002755 Sync *syncObject = context->getSync(sync);
2756 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002758 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002759 return false;
2760 }
2761
2762 switch (pname)
2763 {
2764 case GL_OBJECT_TYPE:
2765 case GL_SYNC_CONDITION:
2766 case GL_SYNC_FLAGS:
2767 case GL_SYNC_STATUS:
2768 break;
2769
2770 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002772 return false;
2773 }
2774
2775 return true;
2776}
2777
Jamie Madill5b772312018-03-08 20:28:32 -05002778bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002779 GLenum mode,
2780 GLsizei count,
2781 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002782 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002783 GLsizei instanceCount)
2784{
2785 if (context->getClientMajorVersion() < 3)
2786 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002788 return false;
2789 }
2790
2791 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2792}
2793
Martin Radev137032d2017-07-13 10:11:12 +03002794bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2795 GLenum target,
2796 GLenum attachment,
2797 GLuint texture,
2798 GLint level,
2799 GLint baseViewIndex,
2800 GLsizei numViews)
2801{
2802
2803 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2804 numViews))
2805 {
2806 return false;
2807 }
2808
Martin Radev137032d2017-07-13 10:11:12 +03002809 if (texture != 0)
2810 {
Martin Radev14b21262017-08-25 13:54:37 +03002811 if (baseViewIndex < 0)
2812 {
2813 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2814 return false;
2815 }
2816
Martin Radev137032d2017-07-13 10:11:12 +03002817 Texture *tex = context->getTexture(texture);
2818 ASSERT(tex);
2819
Corentin Wallez99d492c2018-02-27 15:17:10 -05002820 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002821 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002822 case TextureType::_2DArray:
Martin Radev137032d2017-07-13 10:11:12 +03002823 {
2824 const Caps &caps = context->getCaps();
2825 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2826 {
2827 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2828 "greater than "
2829 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2830 return false;
2831 }
2832 }
2833 break;
2834 default:
2835 context->handleError(InvalidOperation()
2836 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2837 return false;
2838 }
2839
2840 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2841 {
2842 return false;
2843 }
2844 }
2845
2846 return true;
2847}
2848
2849bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2850 GLenum target,
2851 GLenum attachment,
2852 GLuint texture,
2853 GLint level,
2854 GLsizei numViews,
2855 const GLint *viewportOffsets)
2856{
2857 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2858 numViews))
2859 {
2860 return false;
2861 }
2862
Martin Radev137032d2017-07-13 10:11:12 +03002863 if (texture != 0)
2864 {
Martin Radev14b21262017-08-25 13:54:37 +03002865 const GLsizei numViewportOffsetValues = numViews * 2;
2866 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2867 {
2868 if (viewportOffsets[i] < 0)
2869 {
2870 context->handleError(InvalidValue()
2871 << "viewportOffsets cannot contain negative values.");
2872 return false;
2873 }
2874 }
2875
Martin Radev137032d2017-07-13 10:11:12 +03002876 Texture *tex = context->getTexture(texture);
2877 ASSERT(tex);
2878
Corentin Wallez99d492c2018-02-27 15:17:10 -05002879 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002880 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002881 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002882 break;
2883 default:
2884 context->handleError(InvalidOperation()
2885 << "Texture's target must be GL_TEXTURE_2D.");
2886 return false;
2887 }
2888
2889 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2890 {
2891 return false;
2892 }
2893 }
2894
2895 return true;
2896}
2897
Jamie Madillff325f12017-08-26 15:06:05 -04002898bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2899{
2900 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2901}
2902
2903bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2904{
2905 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2906}
2907
2908bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2909{
2910 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2911}
2912
2913bool ValidateUniform4ui(Context *context,
2914 GLint location,
2915 GLuint v0,
2916 GLuint v1,
2917 GLuint v2,
2918 GLuint v3)
2919{
2920 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2921}
2922
2923bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2924{
2925 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2926}
2927
2928bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2929{
2930 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2931}
2932
2933bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2934{
2935 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2936}
2937
2938bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2939{
2940 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2941}
2942
Jamie Madillf0e04492017-08-26 15:28:42 -04002943bool ValidateIsQuery(Context *context, GLuint id)
2944{
2945 if (context->getClientMajorVersion() < 3)
2946 {
2947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2948 return false;
2949 }
2950
2951 return true;
2952}
2953
Jamie Madillc8c95812017-08-26 18:40:09 -04002954bool ValidateUniformMatrix2x3fv(Context *context,
2955 GLint location,
2956 GLsizei count,
2957 GLboolean transpose,
2958 const GLfloat *value)
2959{
2960 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2961}
2962
2963bool ValidateUniformMatrix3x2fv(Context *context,
2964 GLint location,
2965 GLsizei count,
2966 GLboolean transpose,
2967 const GLfloat *value)
2968{
2969 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2970}
2971
2972bool ValidateUniformMatrix2x4fv(Context *context,
2973 GLint location,
2974 GLsizei count,
2975 GLboolean transpose,
2976 const GLfloat *value)
2977{
2978 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2979}
2980
2981bool ValidateUniformMatrix4x2fv(Context *context,
2982 GLint location,
2983 GLsizei count,
2984 GLboolean transpose,
2985 const GLfloat *value)
2986{
2987 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2988}
2989
2990bool ValidateUniformMatrix3x4fv(Context *context,
2991 GLint location,
2992 GLsizei count,
2993 GLboolean transpose,
2994 const GLfloat *value)
2995{
2996 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2997}
2998
2999bool ValidateUniformMatrix4x3fv(Context *context,
3000 GLint location,
3001 GLsizei count,
3002 GLboolean transpose,
3003 const GLfloat *value)
3004{
3005 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3006}
3007
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003008bool ValidateEndTransformFeedback(Context *context)
3009{
3010 if (context->getClientMajorVersion() < 3)
3011 {
3012 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3013 return false;
3014 }
3015
3016 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3017 ASSERT(transformFeedback != nullptr);
3018
3019 if (!transformFeedback->isActive())
3020 {
3021 context->handleError(InvalidOperation());
3022 return false;
3023 }
3024
3025 return true;
3026}
3027
3028bool ValidateTransformFeedbackVaryings(Context *context,
3029 GLuint program,
3030 GLsizei count,
3031 const GLchar *const *varyings,
3032 GLenum bufferMode)
3033{
3034 if (context->getClientMajorVersion() < 3)
3035 {
3036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3037 return false;
3038 }
3039
3040 if (count < 0)
3041 {
3042 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3043 return false;
3044 }
3045
3046 switch (bufferMode)
3047 {
3048 case GL_INTERLEAVED_ATTRIBS:
3049 break;
3050 case GL_SEPARATE_ATTRIBS:
3051 {
3052 const Caps &caps = context->getCaps();
3053 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3054 {
3055 context->handleError(InvalidValue());
3056 return false;
3057 }
3058 break;
3059 }
3060 default:
3061 context->handleError(InvalidEnum());
3062 return false;
3063 }
3064
3065 Program *programObject = GetValidProgram(context, program);
3066 if (!programObject)
3067 {
3068 return false;
3069 }
3070
3071 return true;
3072}
3073
3074bool ValidateGetTransformFeedbackVarying(Context *context,
3075 GLuint program,
3076 GLuint index,
3077 GLsizei bufSize,
3078 GLsizei *length,
3079 GLsizei *size,
3080 GLenum *type,
3081 GLchar *name)
3082{
3083 if (context->getClientMajorVersion() < 3)
3084 {
3085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3086 return false;
3087 }
3088
3089 if (bufSize < 0)
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3092 return false;
3093 }
3094
3095 Program *programObject = GetValidProgram(context, program);
3096 if (!programObject)
3097 {
3098 return false;
3099 }
3100
3101 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3102 {
3103 context->handleError(InvalidValue());
3104 return false;
3105 }
3106
3107 return true;
3108}
3109
3110bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3111{
3112 if (context->getClientMajorVersion() < 3)
3113 {
3114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3115 return false;
3116 }
3117
3118 switch (target)
3119 {
3120 case GL_TRANSFORM_FEEDBACK:
3121 {
3122 // Cannot bind a transform feedback object if the current one is started and not
3123 // paused (3.0.2 pg 85 section 2.14.1)
3124 TransformFeedback *curTransformFeedback =
3125 context->getGLState().getCurrentTransformFeedback();
3126 if (curTransformFeedback && curTransformFeedback->isActive() &&
3127 !curTransformFeedback->isPaused())
3128 {
3129 context->handleError(InvalidOperation());
3130 return false;
3131 }
3132
3133 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3134 // 2.14.1)
3135 if (!context->isTransformFeedbackGenerated(id))
3136 {
3137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3138 return false;
3139 }
3140 }
3141 break;
3142
3143 default:
3144 context->handleError(InvalidEnum());
3145 return false;
3146 }
3147
3148 return true;
3149}
3150
3151bool ValidateIsTransformFeedback(Context *context, GLuint id)
3152{
3153 if (context->getClientMajorVersion() < 3)
3154 {
3155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3156 return false;
3157 }
3158
3159 return true;
3160}
3161
3162bool ValidatePauseTransformFeedback(Context *context)
3163{
3164 if (context->getClientMajorVersion() < 3)
3165 {
3166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3167 return false;
3168 }
3169
3170 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3171 ASSERT(transformFeedback != nullptr);
3172
3173 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3174 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3175 {
3176 context->handleError(InvalidOperation());
3177 return false;
3178 }
3179
3180 return true;
3181}
3182
3183bool ValidateResumeTransformFeedback(Context *context)
3184{
3185 if (context->getClientMajorVersion() < 3)
3186 {
3187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3188 return false;
3189 }
3190
3191 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3192 ASSERT(transformFeedback != nullptr);
3193
3194 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3195 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3196 {
3197 context->handleError(InvalidOperation());
3198 return false;
3199 }
3200
3201 return true;
3202}
3203
Jamie Madill12e957f2017-08-26 21:42:26 -04003204bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3205{
3206 if (context->getClientMajorVersion() < 3)
3207 {
3208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3209 return false;
3210 }
3211
3212 return ValidateVertexAttribIndex(context, index);
3213}
3214
3215bool ValidateVertexAttribI4ui(Context *context,
3216 GLuint index,
3217 GLuint x,
3218 GLuint y,
3219 GLuint z,
3220 GLuint w)
3221{
3222 if (context->getClientMajorVersion() < 3)
3223 {
3224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3225 return false;
3226 }
3227
3228 return ValidateVertexAttribIndex(context, index);
3229}
3230
3231bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3232{
3233 if (context->getClientMajorVersion() < 3)
3234 {
3235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3236 return false;
3237 }
3238
3239 return ValidateVertexAttribIndex(context, index);
3240}
3241
3242bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3243{
3244 if (context->getClientMajorVersion() < 3)
3245 {
3246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3247 return false;
3248 }
3249
3250 return ValidateVertexAttribIndex(context, index);
3251}
3252
3253bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3254{
3255 if (context->getClientMajorVersion() < 3)
3256 {
3257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3258 return false;
3259 }
3260
3261 Program *programObject = GetValidProgram(context, program);
3262 if (!programObject)
3263 {
3264 return false;
3265 }
3266
3267 if (!programObject->isLinked())
3268 {
3269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3270 return false;
3271 }
3272
3273 return true;
3274}
3275
3276bool ValidateGetUniformIndices(Context *context,
3277 GLuint program,
3278 GLsizei uniformCount,
3279 const GLchar *const *uniformNames,
3280 GLuint *uniformIndices)
3281{
3282 if (context->getClientMajorVersion() < 3)
3283 {
3284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3285 return false;
3286 }
3287
3288 if (uniformCount < 0)
3289 {
3290 context->handleError(InvalidValue());
3291 return false;
3292 }
3293
3294 Program *programObject = GetValidProgram(context, program);
3295 if (!programObject)
3296 {
3297 return false;
3298 }
3299
3300 return true;
3301}
3302
3303bool ValidateGetActiveUniformsiv(Context *context,
3304 GLuint program,
3305 GLsizei uniformCount,
3306 const GLuint *uniformIndices,
3307 GLenum pname,
3308 GLint *params)
3309{
3310 if (context->getClientMajorVersion() < 3)
3311 {
3312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3313 return false;
3314 }
3315
3316 if (uniformCount < 0)
3317 {
3318 context->handleError(InvalidValue());
3319 return false;
3320 }
3321
3322 Program *programObject = GetValidProgram(context, program);
3323 if (!programObject)
3324 {
3325 return false;
3326 }
3327
3328 switch (pname)
3329 {
3330 case GL_UNIFORM_TYPE:
3331 case GL_UNIFORM_SIZE:
3332 case GL_UNIFORM_NAME_LENGTH:
3333 case GL_UNIFORM_BLOCK_INDEX:
3334 case GL_UNIFORM_OFFSET:
3335 case GL_UNIFORM_ARRAY_STRIDE:
3336 case GL_UNIFORM_MATRIX_STRIDE:
3337 case GL_UNIFORM_IS_ROW_MAJOR:
3338 break;
3339
3340 default:
3341 context->handleError(InvalidEnum());
3342 return false;
3343 }
3344
3345 if (uniformCount > programObject->getActiveUniformCount())
3346 {
3347 context->handleError(InvalidValue());
3348 return false;
3349 }
3350
3351 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3352 {
3353 const GLuint index = uniformIndices[uniformId];
3354
3355 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3356 {
3357 context->handleError(InvalidValue());
3358 return false;
3359 }
3360 }
3361
3362 return true;
3363}
3364
3365bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3366{
3367 if (context->getClientMajorVersion() < 3)
3368 {
3369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3370 return false;
3371 }
3372
3373 Program *programObject = GetValidProgram(context, program);
3374 if (!programObject)
3375 {
3376 return false;
3377 }
3378
3379 return true;
3380}
3381
3382bool ValidateGetActiveUniformBlockiv(Context *context,
3383 GLuint program,
3384 GLuint uniformBlockIndex,
3385 GLenum pname,
3386 GLint *params)
3387{
3388 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3389}
3390
3391bool ValidateGetActiveUniformBlockName(Context *context,
3392 GLuint program,
3393 GLuint uniformBlockIndex,
3394 GLsizei bufSize,
3395 GLsizei *length,
3396 GLchar *uniformBlockName)
3397{
3398 if (context->getClientMajorVersion() < 3)
3399 {
3400 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3401 return false;
3402 }
3403
3404 Program *programObject = GetValidProgram(context, program);
3405 if (!programObject)
3406 {
3407 return false;
3408 }
3409
3410 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3411 {
3412 context->handleError(InvalidValue());
3413 return false;
3414 }
3415
3416 return true;
3417}
3418
3419bool ValidateUniformBlockBinding(Context *context,
3420 GLuint program,
3421 GLuint uniformBlockIndex,
3422 GLuint uniformBlockBinding)
3423{
3424 if (context->getClientMajorVersion() < 3)
3425 {
3426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3427 return false;
3428 }
3429
3430 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3431 {
3432 context->handleError(InvalidValue());
3433 return false;
3434 }
3435
3436 Program *programObject = GetValidProgram(context, program);
3437 if (!programObject)
3438 {
3439 return false;
3440 }
3441
3442 // if never linked, there won't be any uniform blocks
3443 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3444 {
3445 context->handleError(InvalidValue());
3446 return false;
3447 }
3448
3449 return true;
3450}
3451
3452bool ValidateDrawArraysInstanced(Context *context,
3453 GLenum mode,
3454 GLint first,
3455 GLsizei count,
3456 GLsizei primcount)
3457{
3458 if (context->getClientMajorVersion() < 3)
3459 {
3460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3461 return false;
3462 }
3463
3464 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3465}
3466
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003467bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3468{
3469 if (context->getClientMajorVersion() < 3)
3470 {
3471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3472 return false;
3473 }
3474
3475 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3476 {
3477 context->handleError(InvalidEnum());
3478 return false;
3479 }
3480
3481 if (flags != 0)
3482 {
3483 context->handleError(InvalidValue());
3484 return false;
3485 }
3486
3487 return true;
3488}
3489
3490bool ValidateIsSync(Context *context, GLsync sync)
3491{
3492 if (context->getClientMajorVersion() < 3)
3493 {
3494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3495 return false;
3496 }
3497
3498 return true;
3499}
3500
3501bool ValidateDeleteSync(Context *context, GLsync sync)
3502{
3503 if (context->getClientMajorVersion() < 3)
3504 {
3505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3506 return false;
3507 }
3508
Jamie Madill70b5bb02017-08-28 13:32:37 -04003509 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003510 {
3511 context->handleError(InvalidValue());
3512 return false;
3513 }
3514
3515 return true;
3516}
3517
3518bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3519{
3520 if (context->getClientMajorVersion() < 3)
3521 {
3522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3523 return false;
3524 }
3525
3526 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3527 {
3528 context->handleError(InvalidValue());
3529 return false;
3530 }
3531
Jamie Madill70b5bb02017-08-28 13:32:37 -04003532 Sync *clientWaitSync = context->getSync(sync);
3533 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003534 {
3535 context->handleError(InvalidValue());
3536 return false;
3537 }
3538
3539 return true;
3540}
3541
3542bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3543{
3544 if (context->getClientMajorVersion() < 3)
3545 {
3546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3547 return false;
3548 }
3549
3550 if (flags != 0)
3551 {
3552 context->handleError(InvalidValue());
3553 return false;
3554 }
3555
3556 if (timeout != GL_TIMEOUT_IGNORED)
3557 {
3558 context->handleError(InvalidValue());
3559 return false;
3560 }
3561
Jamie Madill70b5bb02017-08-28 13:32:37 -04003562 Sync *waitSync = context->getSync(sync);
3563 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003564 {
3565 context->handleError(InvalidValue());
3566 return false;
3567 }
3568
3569 return true;
3570}
3571
3572bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3573{
3574 if (context->getClientMajorVersion() < 3)
3575 {
3576 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3577 return false;
3578 }
3579
3580 GLenum nativeType = GL_NONE;
3581 unsigned int numParams = 0;
3582 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3583 {
3584 return false;
3585 }
3586
3587 return true;
3588}
3589
Jamie Madill3ef140a2017-08-26 23:11:21 -04003590bool ValidateIsSampler(Context *context, GLuint sampler)
3591{
3592 if (context->getClientMajorVersion() < 3)
3593 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003595 return false;
3596 }
3597
3598 return true;
3599}
3600
3601bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3602{
3603 if (context->getClientMajorVersion() < 3)
3604 {
3605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3606 return false;
3607 }
3608
3609 if (sampler != 0 && !context->isSampler(sampler))
3610 {
3611 context->handleError(InvalidOperation());
3612 return false;
3613 }
3614
3615 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3616 {
3617 context->handleError(InvalidValue());
3618 return false;
3619 }
3620
3621 return true;
3622}
3623
3624bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3625{
3626 if (context->getClientMajorVersion() < 3)
3627 {
3628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3629 return false;
3630 }
3631
3632 return ValidateVertexAttribIndex(context, index);
3633}
3634
3635bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003636 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003637 GLsizei levels,
3638 GLenum internalformat,
3639 GLsizei width,
3640 GLsizei height)
3641{
3642 if (context->getClientMajorVersion() < 3)
3643 {
3644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3645 return false;
3646 }
3647
3648 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3649 1))
3650 {
3651 return false;
3652 }
3653
3654 return true;
3655}
3656
3657bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003658 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003659 GLsizei levels,
3660 GLenum internalformat,
3661 GLsizei width,
3662 GLsizei height,
3663 GLsizei depth)
3664{
3665 if (context->getClientMajorVersion() < 3)
3666 {
3667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3668 return false;
3669 }
3670
3671 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3672 depth))
3673 {
3674 return false;
3675 }
3676
3677 return true;
3678}
3679
Jamie Madill5b772312018-03-08 20:28:32 -05003680bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003681 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003682 GLenum pname,
3683 GLint64 *params)
3684{
3685 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3686}
3687
3688bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3689{
3690 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3691}
3692
3693bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3694{
3695 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3696}
3697
3698bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3699{
3700 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3701}
3702
3703bool ValidateSamplerParameterfv(Context *context,
3704 GLuint sampler,
3705 GLenum pname,
3706 const GLfloat *params)
3707{
3708 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3709}
3710
3711bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3712{
3713 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3714}
3715
3716bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3717{
3718 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3719}
3720
3721bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3722{
3723 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3724}
3725
3726bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3727{
3728 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3729}
3730
3731bool ValidateGetInternalformativ(Context *context,
3732 GLenum target,
3733 GLenum internalformat,
3734 GLenum pname,
3735 GLsizei bufSize,
3736 GLint *params)
3737{
3738 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3739 nullptr);
3740}
3741
Jamie Madillc29968b2016-01-20 11:17:23 -05003742} // namespace gl