blob: a7f522cd4a5e508e2b491dc06b3f1e4c778b6019 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
Corentin Wallezf0e89be2017-11-08 14:00:32 -080069 TextureType type = texture->getType();
70 if (!ValidMipLevel(context, type, level))
Martin Radev137032d2017-07-13 10:11:12 +030071 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
Corentin Wallezf0e89be2017-11-08 14:00:32 -080076 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
Martin Radev137032d2017-07-13 10:11:12 +030077 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800140 TextureType target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800174 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
Geoff Langca271392017-04-05 12:30:00 -0400175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800201 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800218 TextureType texType = TextureTargetToType(target);
219
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 // Validate image size
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800221 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500223 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 }
226
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 // Verify zero border
228 if (border != 0)
229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
Jamie Madill6f38f822014-06-06 17:12:20 -0400234 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
235 std::numeric_limits<GLsizei>::max() - xoffset < width ||
236 std::numeric_limits<GLsizei>::max() - yoffset < height ||
237 std::numeric_limits<GLsizei>::max() - zoffset < depth)
238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500239 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400240 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400241 }
242
Geoff Langaae65a42014-05-26 12:43:44 -0400243 const gl::Caps &caps = context->getCaps();
244
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800245 switch (texType)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800247 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800248 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
249 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500251 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800252 return false;
253 }
254 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800256 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257 ASSERT(level == 0);
258 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
259 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
260 {
261 context->handleError(InvalidValue());
262 return false;
263 }
264 if (isCompressed)
265 {
266 context->handleError(InvalidEnum()
267 << "Rectangle texture cannot have a compressed format.");
268 return false;
269 }
270 break;
271
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800272 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800273 if (!isSubImage && width != height)
274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500275 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800276 return false;
277 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400278
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500281 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 return false;
283 }
284 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800286 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800287 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
288 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
289 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500291 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800292 return false;
293 }
294 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800296 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800297 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
298 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
299 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500301 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800302 return false;
303 }
304 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305
He Yunchaoced53ae2016-11-29 15:00:51 +0800306 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500307 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800308 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 }
310
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800311 gl::Texture *texture = context->getTargetTexture(texType);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 if (!texture)
313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 }
317
Geoff Lang69cce582015-09-17 13:20:36 -0400318 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
324 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400325 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400326 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500327 if (isSubImage && actualInternalFormat == GL_NONE)
328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500330 return false;
331 }
332
Geoff Langc4e93662017-05-01 10:45:59 -0400333 const gl::InternalFormat &actualFormatInfo = isSubImage
334 ? *texture->getFormat(target, level).info
335 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 if (isCompressed)
337 {
tmartino7c102692015-10-02 16:43:40 -0400338 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500340 context->handleError(
341 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400342 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 }
344
Geoff Lang966c9402017-04-18 12:38:27 -0400345 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 {
Geoff Lang966c9402017-04-18 12:38:27 -0400347 if (!ValidCompressedSubImageSize(
348 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
349 texture->getWidth(target, level), texture->getHeight(target, level)))
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400352 return false;
353 }
354
355 if (format != actualInternalFormat)
356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500357 context->handleError(InvalidOperation()
358 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400359 return false;
360 }
Geoff Lang86f81162017-10-30 15:10:45 -0400361
362 if (actualInternalFormat == GL_ETC1_RGB8_OES)
363 {
364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
365 return false;
366 }
Geoff Lang966c9402017-04-18 12:38:27 -0400367 }
368 else
369 {
370 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500372 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400373 return false;
374 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 }
376
Geoff Langeb66a6e2016-10-31 13:06:12 -0400377 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500379 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400380 return false;
381 }
382
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800383 if (texType == TextureType::_3D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 }
388 }
389 else
390 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800391 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
392 type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 {
Geoff Lang5d601382014-07-22 15:14:06 -0400394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 }
397
398 // Validate sub image parameters
399 if (isSubImage)
400 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500401 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500403 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 }
406
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500409 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 }
412
413 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
414 std::numeric_limits<GLsizei>::max() - yoffset < height ||
415 std::numeric_limits<GLsizei>::max() - zoffset < depth)
416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420
Geoff Langa9be0dc2014-12-17 12:34:40 -0500421 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
422 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
423 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500425 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 }
Geoff Langfb052642017-10-24 13:42:09 -0400428
429 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400430 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400431 {
432 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
433 return false;
434 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 }
436
Geoff Langdbcced82017-06-06 15:55:54 -0400437 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800438 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
Geoff Langdbcced82017-06-06 15:55:54 -0400439 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400440 {
441 return false;
442 }
443
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400444 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400445 gl::Buffer *pixelUnpackBuffer =
446 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400447 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400448 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 // ...data is not evenly divisible into the number of bytes needed to store in memory a
450 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400451 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400452 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400453 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400454 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400455 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
456
Geoff Langff5b2d52016-09-07 11:32:23 -0400457 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500459 context->handleError(InvalidOperation()
460 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 return false;
462 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400463 }
464
Jamie Madill7a5f7382014-03-05 15:01:24 -0500465 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700466 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500468 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400469 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500470 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400471 }
472
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400473 return true;
474}
475
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500476bool ValidateES3TexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800477 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500478 GLint level,
479 GLenum internalformat,
480 bool isCompressed,
481 bool isSubImage,
482 GLint xoffset,
483 GLint yoffset,
484 GLint zoffset,
485 GLsizei width,
486 GLsizei height,
487 GLsizei depth,
488 GLint border,
489 GLenum format,
490 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400491 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400492 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500493{
494 if (!ValidTexture2DDestinationTarget(context, target))
495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500496 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500497 return false;
498 }
499
500 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
501 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400502 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500503}
504
505bool ValidateES3TexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800506 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500507 GLint level,
508 GLenum internalformat,
509 bool isCompressed,
510 bool isSubImage,
511 GLint xoffset,
512 GLint yoffset,
513 GLint zoffset,
514 GLsizei width,
515 GLsizei height,
516 GLsizei depth,
517 GLint border,
518 GLenum format,
519 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400520 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400521 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522{
523 if (!ValidTexture3DDestinationTarget(context, target))
524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500525 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526 return false;
527 }
528
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 if (IsETC2EACFormat(format) && target != TextureType::_2DArray)
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500530 {
531 // ES 3.1, Section 8.7, page 169.
532 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
533 return false;
534 }
535
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800536 return ValidateES3TexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
537 internalformat, isCompressed, isSubImage, xoffset,
538 yoffset, zoffset, width, height, depth, border, format,
539 type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500540}
541
Geoff Lang5d601382014-07-22 15:14:06 -0400542struct EffectiveInternalFormatInfo
543{
Jamie Madill76648fe2016-10-05 17:01:41 -0400544 GLenum effectiveFormat;
545 GLenum destFormat;
546 GLuint minRedBits;
547 GLuint maxRedBits;
548 GLuint minGreenBits;
549 GLuint maxGreenBits;
550 GLuint minBlueBits;
551 GLuint maxBlueBits;
552 GLuint minAlphaBits;
553 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400554};
555
Jamie Madill76648fe2016-10-05 17:01:41 -0400556static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
557 GLenum targetFormat,
558 const EffectiveInternalFormatInfo *list,
559 size_t size,
560 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400561{
Jamie Madill76648fe2016-10-05 17:01:41 -0400562 for (size_t curFormat = 0; curFormat < size; ++curFormat)
563 {
564 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
565 if ((formatInfo.destFormat == targetFormat) &&
566 (formatInfo.minRedBits <= srcFormat.redBits &&
567 formatInfo.maxRedBits >= srcFormat.redBits) &&
568 (formatInfo.minGreenBits <= srcFormat.greenBits &&
569 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
570 (formatInfo.minBlueBits <= srcFormat.blueBits &&
571 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
572 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
573 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
574 {
575 *outEffectiveFormat = formatInfo.effectiveFormat;
576 return true;
577 }
578 }
Geoff Lang5d601382014-07-22 15:14:06 -0400579
Jamie Madill76648fe2016-10-05 17:01:41 -0400580 *outEffectiveFormat = GL_NONE;
581 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400582}
583
Jamie Madill76648fe2016-10-05 17:01:41 -0400584bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
585 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400586{
Jamie Madill76648fe2016-10-05 17:01:41 -0400587 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
588 // Effective internal format coresponding to destination internal format and linear source
589 // buffer component sizes.
590 // | Source channel min/max sizes |
591 // Effective Internal Format | N/A | R | G | B | A |
592 // clang-format off
593 constexpr EffectiveInternalFormatInfo list[] = {
594 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
595 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
596 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
597 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
598 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
599 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
600 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
601 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
602 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
603 };
604 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400605
Jamie Madill76648fe2016-10-05 17:01:41 -0400606 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
607}
Geoff Lang5d601382014-07-22 15:14:06 -0400608
Jamie Madill76648fe2016-10-05 17:01:41 -0400609bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
610 const InternalFormat &destFormat,
611 GLenum *outEffectiveFormat)
612{
613 constexpr GLuint umax = UINT_MAX;
614
615 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
616 // Effective internal format coresponding to destination internal format andlinear source buffer
617 // component sizes.
618 // | Source channel min/max sizes |
619 // Effective Internal Format | Dest Format | R | G | B | A |
620 // clang-format off
621 constexpr EffectiveInternalFormatInfo list[] = {
622 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
623 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
624 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
625 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
626 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
627 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
628 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
629 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
630 };
631 // clang-format on
632
633 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
634 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400635}
636
He Yunchaoced53ae2016-11-29 15:00:51 +0800637static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
638 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400639 GLenum *outEffectiveFormat)
640{
Geoff Langca271392017-04-05 12:30:00 -0400641 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400642 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400643 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400644 }
645 else
646 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400647 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400648 }
Geoff Lang5d601382014-07-22 15:14:06 -0400649}
650
Corentin Wallez76287682016-04-25 09:23:38 -0400651static bool EqualOrFirstZero(GLuint first, GLuint second)
652{
653 return first == 0 || first == second;
654}
655
Geoff Langca271392017-04-05 12:30:00 -0400656static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
657 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400658 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400659{
Jamie Madill21b786b2016-11-01 17:41:31 -0400660 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400661 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400662 return false;
663 }
Geoff Lang5d601382014-07-22 15:14:06 -0400664
Jamie Madill21b786b2016-11-01 17:41:31 -0400665 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
666 // must both be signed, unsigned, or fixed point and both source and destinations
667 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
668 // conversion between fixed and floating point.
669
670 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
671 (framebufferFormatInfo.colorEncoding == GL_SRGB))
672 {
673 return false;
674 }
675
676 if (((textureFormatInfo.componentType == GL_INT) !=
677 (framebufferFormatInfo.componentType == GL_INT)) ||
678 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
679 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
680 {
681 return false;
682 }
683
684 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
685 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
686 textureFormatInfo.componentType == GL_FLOAT) &&
687 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
688 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
689 framebufferFormatInfo.componentType == GL_FLOAT))
690 {
691 return false;
692 }
693
694 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
695 // The effective internal format of the source buffer is determined with the following rules
696 // applied in order:
697 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
698 // format then the effective internal format is the source buffer's sized internal format.
699 // * If the source buffer is a texture that was created with an unsized base internal format,
700 // then the effective internal format is the source image array's effective internal
701 // format, as specified by table 3.12, which is determined from the <format> and <type>
702 // that were used when the source image array was specified by TexImage*.
703 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
704 // where Destination Internal Format matches internalformat and where the [source channel
705 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
706 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
707 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800708 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400709 if (readBufferHandle != 0)
710 {
711 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
712 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400713 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400714 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400715 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400716 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 else
Geoff Lang5d601382014-07-22 15:14:06 -0400718 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 // Renderbuffers cannot be created with an unsized internal format, so this must be an
720 // unsized-format texture. We can use the same table we use when creating textures to
721 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400722 sourceEffectiveFormat =
723 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400724 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400725 }
726 else
727 {
728 // The effective internal format must be derived from the source framebuffer's channel
729 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
730 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400731 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400732 GLenum effectiveFormat;
733 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
734 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400735 {
Geoff Langca271392017-04-05 12:30:00 -0400736 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400737 }
738 else
739 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400740 return false;
741 }
742 }
743 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
744 {
745 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400746 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400747 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
748 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
749 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
750 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
751 {
Geoff Langca271392017-04-05 12:30:00 -0400752 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400753 }
754 else
755 {
756 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400757 }
758 }
759 else
760 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400761 UNREACHABLE();
762 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400763 }
Geoff Lang5d601382014-07-22 15:14:06 -0400764 }
765
Geoff Langca271392017-04-05 12:30:00 -0400766 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400767 {
768 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
769 // sized, component sizes of the source and destination formats must exactly match if the
770 // destination format exists.
771 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
772 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
773 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
774 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
775 {
776 return false;
777 }
778 }
779
780 return true; // A conversion function exists, and no rule in the specification has precluded
781 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400782}
783
Jamie Madill5b772312018-03-08 20:28:32 -0500784bool ValidateES3CopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800785 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786 GLint level,
787 GLenum internalformat,
788 bool isSubImage,
789 GLint xoffset,
790 GLint yoffset,
791 GLint zoffset,
792 GLint x,
793 GLint y,
794 GLsizei width,
795 GLsizei height,
796 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400798 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400799 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 xoffset, yoffset, zoffset, x, y, width, height, border,
801 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400802 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400803 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400805 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806
Jamie Madill51f40ec2016-06-15 14:06:00 -0400807 const auto &state = context->getGLState();
808 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
809 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400810
Jamie Madill427064d2018-04-13 16:20:34 -0400811 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400814 }
815
Jamie Madille98b1b52018-03-08 09:47:23 -0500816 if (readFramebufferID != 0 && !ValidateFramebufferNotMultisampled(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400817 {
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400819 }
820
Jamie Madill0c8abca2016-07-22 20:21:26 -0400821 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822
823 if (isSubImage)
824 {
Geoff Langca271392017-04-05 12:30:00 -0400825 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500826 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 }
831 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400832 else
833 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400834 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400835 const InternalFormat &framebufferFormat = *source->getFormat().info;
836 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400837 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500839 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400841 }
842 }
843
Geoff Lang784a8fd2013-09-24 12:33:16 -0400844 // If width or height is zero, it is a no-op. Return false without setting an error.
845 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846}
847
Jamie Madill5b772312018-03-08 20:28:32 -0500848bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800849 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500850 GLint level,
851 GLenum internalformat,
852 bool isSubImage,
853 GLint xoffset,
854 GLint yoffset,
855 GLint zoffset,
856 GLint x,
857 GLint y,
858 GLsizei width,
859 GLsizei height,
860 GLint border)
861{
862 if (!ValidTexture2DDestinationTarget(context, target))
863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500864 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500865 return false;
866 }
867
868 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
869 xoffset, yoffset, zoffset, x, y, width, height,
870 border);
871}
872
Jamie Madill5b772312018-03-08 20:28:32 -0500873bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800874 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500875 GLint level,
876 GLenum internalformat,
877 bool isSubImage,
878 GLint xoffset,
879 GLint yoffset,
880 GLint zoffset,
881 GLint x,
882 GLint y,
883 GLsizei width,
884 GLsizei height,
885 GLint border)
886{
887 if (!ValidTexture3DDestinationTarget(context, target))
888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500889 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500890 return false;
891 }
892
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800893 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
894 internalformat, isSubImage, xoffset, yoffset,
895 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500896}
897
898bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800899 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500900 GLsizei levels,
901 GLenum internalformat,
902 GLsizei width,
903 GLsizei height,
904 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905{
906 if (width < 1 || height < 1 || depth < 1 || levels < 1)
907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500908 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400909 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 }
911
Geoff Langb92c1332015-09-04 12:54:55 -0400912 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800913 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400914 {
915 maxDim = std::max(maxDim, depth);
916 }
917
918 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500920 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400921 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 }
923
Geoff Langaae65a42014-05-26 12:43:44 -0400924 const gl::Caps &caps = context->getCaps();
925
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 switch (target)
927 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800928 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929 {
Geoff Langaae65a42014-05-26 12:43:44 -0400930 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
931 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500933 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936 }
937 break;
938
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800939 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400940 {
941 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
942 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
943 {
944 context->handleError(InvalidValue());
945 return false;
946 }
947 }
948 break;
949
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800950 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 if (width != height)
953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500954 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 }
957
Geoff Langaae65a42014-05-26 12:43:44 -0400958 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400961 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962 }
963 }
964 break;
965
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800966 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 {
Geoff Langaae65a42014-05-26 12:43:44 -0400968 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
969 static_cast<GLuint>(height) > caps.max3DTextureSize ||
970 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500972 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400973 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 }
975 }
976 break;
977
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800978 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 {
Geoff Langaae65a42014-05-26 12:43:44 -0400980 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
981 static_cast<GLuint>(height) > caps.max2DTextureSize ||
982 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500984 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400985 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400986 }
987 }
988 break;
989
He Yunchaoced53ae2016-11-29 15:00:51 +0800990 default:
991 UNREACHABLE();
992 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 }
994
Geoff Lang691e58c2014-12-19 17:03:25 -0500995 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 if (!texture || texture->id() == 0)
997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500998 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400999 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 }
1001
Geoff Lang69cce582015-09-17 13:20:36 -04001002 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001004 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001005 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 }
1007
Geoff Langca271392017-04-05 12:30:00 -04001008 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001009 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001011 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 }
1014
Geoff Langca271392017-04-05 12:30:00 -04001015 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001021 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001022 {
1023 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1024 return false;
1025 }
1026
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 return true;
1028}
1029
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001030bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001031 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001032 GLsizei levels,
1033 GLenum internalformat,
1034 GLsizei width,
1035 GLsizei height,
1036 GLsizei depth)
1037{
1038 if (!ValidTexture2DTarget(context, target))
1039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001040 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001041 return false;
1042 }
1043
1044 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1045 height, depth);
1046}
1047
1048bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001049 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001050 GLsizei levels,
1051 GLenum internalformat,
1052 GLsizei width,
1053 GLsizei height,
1054 GLsizei depth)
1055{
1056 if (!ValidTexture3DTarget(context, target))
1057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001058 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001059 return false;
1060 }
1061
1062 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1063 height, depth);
1064}
1065
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001066bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1067{
Martin Radev1be913c2016-07-11 17:59:16 +03001068 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001069 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001071 return false;
1072 }
1073
1074 return ValidateBeginQueryBase(context, target, id);
1075}
1076
1077bool ValidateEndQuery(gl::Context *context, GLenum target)
1078{
Martin Radev1be913c2016-07-11 17:59:16 +03001079 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001080 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001082 return false;
1083 }
1084
1085 return ValidateEndQueryBase(context, target);
1086}
1087
1088bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1089{
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001091 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093 return false;
1094 }
1095
Geoff Lang2186c382016-10-14 10:54:54 -04001096 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097}
1098
1099bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1100{
Martin Radev1be913c2016-07-11 17:59:16 +03001101 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001102 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001104 return false;
1105 }
1106
Geoff Lang2186c382016-10-14 10:54:54 -04001107 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001108}
1109
He Yunchaoced53ae2016-11-29 15:00:51 +08001110bool ValidateFramebufferTextureLayer(Context *context,
1111 GLenum target,
1112 GLenum attachment,
1113 GLuint texture,
1114 GLint level,
1115 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001116{
Martin Radev1be913c2016-07-11 17:59:16 +03001117 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001118 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001120 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001121 }
1122
Jamie Madill55ec3b12014-07-03 10:38:57 -04001123 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1124 {
1125 return false;
1126 }
1127
1128 const gl::Caps &caps = context->getCaps();
1129 if (texture != 0)
1130 {
Geoff Lang23e02842017-10-17 13:24:09 -04001131 if (layer < 0)
1132 {
1133 context->handleError(InvalidValue());
1134 return false;
1135 }
1136
Jamie Madill55ec3b12014-07-03 10:38:57 -04001137 gl::Texture *tex = context->getTexture(texture);
1138 ASSERT(tex);
1139
Corentin Wallez99d492c2018-02-27 15:17:10 -05001140 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001141 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001142 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001143 {
1144 if (level > gl::log2(caps.max2DTextureSize))
1145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001146 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001148 }
1149
1150 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001152 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001153 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001154 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001155 }
1156 break;
1157
Corentin Wallez99d492c2018-02-27 15:17:10 -05001158 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001159 {
1160 if (level > gl::log2(caps.max3DTextureSize))
1161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001162 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001163 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001164 }
1165
1166 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001168 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001170 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001171 }
1172 break;
1173
He Yunchaoced53ae2016-11-29 15:00:51 +08001174 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001175 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001177 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001178
Corentin Wallez99d492c2018-02-27 15:17:10 -05001179 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001180 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001182 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001183 return false;
1184 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001185 }
1186
1187 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001188}
1189
He Yunchaoced53ae2016-11-29 15:00:51 +08001190bool ValidateInvalidateFramebuffer(Context *context,
1191 GLenum target,
1192 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001193 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194{
Martin Radev1be913c2016-07-11 17:59:16 +03001195 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001196 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001198 return false;
1199 }
1200
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201 bool defaultFramebuffer = false;
1202
1203 switch (target)
1204 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001205 case GL_DRAW_FRAMEBUFFER:
1206 case GL_FRAMEBUFFER:
1207 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1208 break;
1209 case GL_READ_FRAMEBUFFER:
1210 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1211 break;
1212 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215 }
1216
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1218 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219}
1220
Jamie Madill3ef140a2017-08-26 23:11:21 -04001221bool ValidateInvalidateSubFramebuffer(Context *context,
1222 GLenum target,
1223 GLsizei numAttachments,
1224 const GLenum *attachments,
1225 GLint x,
1226 GLint y,
1227 GLsizei width,
1228 GLsizei height)
1229{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001230 if (width < 0 || height < 0)
1231 {
1232 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1233 return false;
1234 }
1235
Jamie Madill3ef140a2017-08-26 23:11:21 -04001236 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1237}
1238
Jamie Madill5b772312018-03-08 20:28:32 -05001239bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001240{
Martin Radev1be913c2016-07-11 17:59:16 +03001241 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001242 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001245 }
1246
Jamie Madill427064d2018-04-13 16:20:34 -04001247 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001248 {
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 }
1251
1252 return true;
1253}
1254
Olli Etuaho71dfb362016-03-10 14:04:27 +02001255bool ValidateDrawRangeElements(Context *context,
1256 GLenum mode,
1257 GLuint start,
1258 GLuint end,
1259 GLsizei count,
1260 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001261 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001262{
Martin Radev1be913c2016-07-11 17:59:16 +03001263 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001264 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001266 return false;
1267 }
1268
1269 if (end < start)
1270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001271 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001272 return false;
1273 }
1274
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001275 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001276 {
1277 return false;
1278 }
1279
Jamie Madill9fdaa492018-02-16 10:52:11 -05001280 // Skip range checks for no-op calls.
1281 if (count <= 0)
1282 {
1283 return true;
1284 }
1285
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001286 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04001287 const DrawCallParams &params = context->getParams<DrawCallParams>();
1288 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001289
Jamie Madill6f5444d2018-03-14 10:08:11 -04001290 const IndexRange &indexRange = params.getIndexRange();
1291
1292 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001293 {
1294 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001295 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001296 return false;
1297 }
1298 return true;
1299}
1300
He Yunchaoced53ae2016-11-29 15:00:51 +08001301bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001302{
Martin Radev1be913c2016-07-11 17:59:16 +03001303 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001304 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001306 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001307 }
1308
Jamie Madill78f41802014-08-25 15:47:55 -04001309 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001310}
1311
Jamie Madillb885e572015-02-03 16:16:04 -05001312bool ValidateReadBuffer(Context *context, GLenum src)
1313{
Martin Radev1be913c2016-07-11 17:59:16 +03001314 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001315 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001317 return false;
1318 }
1319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001320 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001321
1322 if (readFBO == nullptr)
1323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001325 return false;
1326 }
1327
1328 if (src == GL_NONE)
1329 {
1330 return true;
1331 }
1332
Olli Etuaho84c9f592016-03-09 14:37:25 +02001333 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001335 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001336 return false;
1337 }
1338
1339 if (readFBO->id() == 0)
1340 {
1341 if (src != GL_BACK)
1342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(
1344 InvalidOperation()
1345 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001346 return false;
1347 }
1348 }
1349 else
1350 {
1351 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1352
1353 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001356 return false;
1357 }
1358 }
1359
1360 return true;
1361}
1362
Jamie Madill86af3d22015-07-21 15:14:07 -04001363bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001364 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001365 GLint level,
1366 GLenum internalformat,
1367 GLsizei width,
1368 GLsizei height,
1369 GLsizei depth,
1370 GLint border,
1371 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001372 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001373{
Martin Radev1be913c2016-07-11 17:59:16 +03001374 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001375 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001376 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001377 return false;
1378 }
1379
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001380 if (!ValidTextureTarget(context, target))
1381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001383 return false;
1384 }
1385
Jamie Madille2e406c2016-06-02 13:04:10 -04001386 // Validate image size
1387 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001389 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001390 return false;
1391 }
1392
Geoff Langca271392017-04-05 12:30:00 -04001393 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001394 if (!formatInfo.compressed)
1395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001397 return false;
1398 }
1399
Jeff Gilbert48590352017-11-07 16:03:38 -08001400 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001401 if (blockSizeOrErr.isError())
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001404 return false;
1405 }
1406 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001408 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001409 return false;
1410 }
1411
1412 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001413 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001416 return false;
1417 }
1418
1419 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001420 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001421 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1422 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001423 {
1424 return false;
1425 }
1426
1427 return true;
1428}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001429
Corentin Wallezb2931602017-04-11 15:58:57 -04001430bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001431 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001432 GLint level,
1433 GLenum internalformat,
1434 GLsizei width,
1435 GLsizei height,
1436 GLsizei depth,
1437 GLint border,
1438 GLsizei imageSize,
1439 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001440 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001441{
1442 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1443 {
1444 return false;
1445 }
1446
1447 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1448 depth, border, imageSize, data);
1449}
1450
Austin Kinrossbc781f32015-10-26 09:27:38 -07001451bool ValidateBindVertexArray(Context *context, GLuint array)
1452{
Martin Radev1be913c2016-07-11 17:59:16 +03001453 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001454 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001456 return false;
1457 }
1458
1459 return ValidateBindVertexArrayBase(context, array);
1460}
1461
Jamie Madilld7576732017-08-26 18:49:50 -04001462bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001463{
Martin Radev1be913c2016-07-11 17:59:16 +03001464 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001465 {
Jamie Madilld7576732017-08-26 18:49:50 -04001466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001467 return false;
1468 }
1469
1470 return true;
1471}
Geoff Langc5629752015-12-07 16:29:04 -05001472
Jiajia Qin6eafb042016-12-27 17:04:07 +08001473static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001474 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001475 GLuint index,
1476 GLuint buffer,
1477 GLintptr offset,
1478 GLsizeiptr size)
1479{
1480 if (context->getClientMajorVersion() < 3)
1481 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001483 return false;
1484 }
1485
1486 if (buffer != 0 && offset < 0)
1487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001488 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001489 return false;
1490 }
1491
1492 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1493 !context->isBufferGenerated(buffer))
1494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001495 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001496 return false;
1497 }
1498
1499 const Caps &caps = context->getCaps();
1500 switch (target)
1501 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001502 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001503 {
1504 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidValue() << "index is greater than or equal to the "
1507 "number of TRANSFORM_FEEDBACK_BUFFER "
1508 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001509 return false;
1510 }
1511 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001514 return false;
1515 }
1516
1517 TransformFeedback *curTransformFeedback =
1518 context->getGLState().getCurrentTransformFeedback();
1519 if (curTransformFeedback && curTransformFeedback->isActive())
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidOperation()
1522 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1523 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001524 return false;
1525 }
1526 break;
1527 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001528 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001529 {
1530 if (index >= caps.maxUniformBufferBindings)
1531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001532 context->handleError(InvalidValue() << "index is greater than or equal to the "
1533 "number of UNIFORM_BUFFER indexed "
1534 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001535 return false;
1536 }
1537
1538 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1539 {
1540 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 InvalidValue()
1542 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001543 return false;
1544 }
1545 break;
1546 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001547 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001548 {
1549 if (context->getClientVersion() < ES_3_1)
1550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidEnum()
1552 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001553 return false;
1554 }
1555 if (index >= caps.maxAtomicCounterBufferBindings)
1556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001557 context->handleError(InvalidValue() << "index is greater than or equal to the "
1558 "number of ATOMIC_COUNTER_BUFFER "
1559 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001560 return false;
1561 }
1562 if (buffer != 0 && (offset % 4) != 0)
1563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001564 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001565 return false;
1566 }
1567 break;
1568 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001569 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001570 {
1571 if (context->getClientVersion() < ES_3_1)
1572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001573 context->handleError(InvalidEnum()
1574 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001575 return false;
1576 }
1577 if (index >= caps.maxShaderStorageBufferBindings)
1578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001579 context->handleError(InvalidValue() << "index is greater than or equal to the "
1580 "number of SHADER_STORAGE_BUFFER "
1581 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001582 return false;
1583 }
1584 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001586 context->handleError(InvalidValue() << "offset must be multiple of value of "
1587 "SHADER_STORAGE_BUFFER_OFFSET_"
1588 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001589 return false;
1590 }
1591 break;
1592 }
1593 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001595 return false;
1596 }
1597
1598 return true;
1599}
1600
Corentin Wallez336129f2017-10-17 15:55:40 -04001601bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001602{
1603 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1604}
1605
1606bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001607 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001608 GLuint index,
1609 GLuint buffer,
1610 GLintptr offset,
1611 GLsizeiptr size)
1612{
1613 if (buffer != 0 && size <= 0)
1614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidValue()
1616 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001617 return false;
1618 }
1619 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1620}
1621
Geoff Langc5629752015-12-07 16:29:04 -05001622bool ValidateProgramBinary(Context *context,
1623 GLuint program,
1624 GLenum binaryFormat,
1625 const void *binary,
1626 GLint length)
1627{
Martin Radev1be913c2016-07-11 17:59:16 +03001628 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001629 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001631 return false;
1632 }
1633
1634 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1635}
1636
1637bool ValidateGetProgramBinary(Context *context,
1638 GLuint program,
1639 GLsizei bufSize,
1640 GLsizei *length,
1641 GLenum *binaryFormat,
1642 void *binary)
1643{
Martin Radev1be913c2016-07-11 17:59:16 +03001644 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001645 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001647 return false;
1648 }
1649
1650 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1651}
1652
Olli Etuahof0fee072016-03-30 15:11:58 +03001653bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001654{
Martin Radev1be913c2016-07-11 17:59:16 +03001655 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001656 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001658 return false;
1659 }
1660
1661 if (GetValidProgram(context, program) == nullptr)
1662 {
1663 return false;
1664 }
1665
1666 switch (pname)
1667 {
1668 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001669 if (value != GL_FALSE && value != GL_TRUE)
1670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001671 context->handleError(InvalidValue()
1672 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001673 return false;
1674 }
Geoff Langc5629752015-12-07 16:29:04 -05001675 break;
1676
Yunchao He61afff12017-03-14 15:34:03 +08001677 case GL_PROGRAM_SEPARABLE:
1678 if (context->getClientVersion() < ES_3_1)
1679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001680 context->handleError(InvalidEnum()
1681 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001682 return false;
1683 }
1684
1685 if (value != GL_FALSE && value != GL_TRUE)
1686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001687 context->handleError(InvalidValue()
1688 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001689 return false;
1690 }
1691 break;
1692
Geoff Langc5629752015-12-07 16:29:04 -05001693 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001694 context->handleError(InvalidEnum()
1695 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001696 return false;
1697 }
1698
1699 return true;
1700}
Jamie Madillc29968b2016-01-20 11:17:23 -05001701
1702bool ValidateBlitFramebuffer(Context *context,
1703 GLint srcX0,
1704 GLint srcY0,
1705 GLint srcX1,
1706 GLint srcY1,
1707 GLint dstX0,
1708 GLint dstY0,
1709 GLint dstX1,
1710 GLint dstY1,
1711 GLbitfield mask,
1712 GLenum filter)
1713{
Martin Radev1be913c2016-07-11 17:59:16 +03001714 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001715 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001716 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001717 return false;
1718 }
1719
1720 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1721 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722}
Jamie Madillc29968b2016-01-20 11:17:23 -05001723
Jamie Madill5b772312018-03-08 20:28:32 -05001724bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001725{
1726 switch (buffer)
1727 {
1728 case GL_COLOR:
1729 if (drawbuffer < 0 ||
1730 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001732 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001733 return false;
1734 }
Geoff Lang76e65652017-03-27 14:58:02 -04001735 if (context->getExtensions().webglCompatibility)
1736 {
1737 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001738 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001739 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1740 {
1741 return false;
1742 }
1743 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001744 break;
1745
1746 case GL_STENCIL:
1747 if (drawbuffer != 0)
1748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001749 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 return false;
1751 }
1752 break;
1753
1754 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001756 return false;
1757 }
1758
1759 return ValidateClearBuffer(context);
1760}
1761
Jamie Madill5b772312018-03-08 20:28:32 -05001762bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001763{
1764 switch (buffer)
1765 {
1766 case GL_COLOR:
1767 if (drawbuffer < 0 ||
1768 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001770 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001771 return false;
1772 }
Geoff Lang76e65652017-03-27 14:58:02 -04001773 if (context->getExtensions().webglCompatibility)
1774 {
1775 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001776 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001777 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1778 {
1779 return false;
1780 }
1781 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001782 break;
1783
1784 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001785 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001786 return false;
1787 }
1788
1789 return ValidateClearBuffer(context);
1790}
1791
Jamie Madill5b772312018-03-08 20:28:32 -05001792bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001793{
1794 switch (buffer)
1795 {
1796 case GL_COLOR:
1797 if (drawbuffer < 0 ||
1798 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001800 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001801 return false;
1802 }
Geoff Lang76e65652017-03-27 14:58:02 -04001803 if (context->getExtensions().webglCompatibility)
1804 {
1805 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1806 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001807 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001808 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1809 {
1810 return false;
1811 }
1812 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 break;
1814
1815 case GL_DEPTH:
1816 if (drawbuffer != 0)
1817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001818 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001819 return false;
1820 }
1821 break;
1822
1823 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001824 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001825 return false;
1826 }
1827
1828 return ValidateClearBuffer(context);
1829}
1830
Jamie Madill5b772312018-03-08 20:28:32 -05001831bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001832 GLenum buffer,
1833 GLint drawbuffer,
1834 GLfloat depth,
1835 GLint stencil)
1836{
1837 switch (buffer)
1838 {
1839 case GL_DEPTH_STENCIL:
1840 if (drawbuffer != 0)
1841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001842 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001843 return false;
1844 }
1845 break;
1846
1847 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001848 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 return false;
1850 }
1851
1852 return ValidateClearBuffer(context);
1853}
1854
Jamie Madill5b772312018-03-08 20:28:32 -05001855bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05001856{
Martin Radev1be913c2016-07-11 17:59:16 +03001857 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001860 return false;
1861 }
1862
1863 return ValidateDrawBuffersBase(context, n, bufs);
1864}
1865
1866bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001867 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001868 GLint level,
1869 GLint xoffset,
1870 GLint yoffset,
1871 GLint zoffset,
1872 GLint x,
1873 GLint y,
1874 GLsizei width,
1875 GLsizei height)
1876{
Martin Radev1be913c2016-07-11 17:59:16 +03001877 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001883 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1884 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001885}
1886
Jamie Madill73a84962016-02-12 09:27:23 -05001887bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001888 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001889 GLint level,
1890 GLint internalformat,
1891 GLsizei width,
1892 GLsizei height,
1893 GLsizei depth,
1894 GLint border,
1895 GLenum format,
1896 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001897 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001898{
Martin Radev1be913c2016-07-11 17:59:16 +03001899 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001900 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001902 return false;
1903 }
1904
1905 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001906 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001907 pixels);
1908}
1909
Geoff Langc52f6f12016-10-14 10:18:00 -04001910bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001911 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001912 GLint level,
1913 GLint internalformat,
1914 GLsizei width,
1915 GLsizei height,
1916 GLsizei depth,
1917 GLint border,
1918 GLenum format,
1919 GLenum type,
1920 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001921 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001922{
1923 if (context->getClientMajorVersion() < 3)
1924 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001926 return false;
1927 }
1928
1929 if (!ValidateRobustEntryPoint(context, bufSize))
1930 {
1931 return false;
1932 }
1933
1934 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1935 0, 0, width, height, depth, border, format, type,
1936 bufSize, pixels);
1937}
1938
Jamie Madill73a84962016-02-12 09:27:23 -05001939bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001940 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001941 GLint level,
1942 GLint xoffset,
1943 GLint yoffset,
1944 GLint zoffset,
1945 GLsizei width,
1946 GLsizei height,
1947 GLsizei depth,
1948 GLenum format,
1949 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001950 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001951{
Martin Radev1be913c2016-07-11 17:59:16 +03001952 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001953 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001955 return false;
1956 }
1957
1958 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1959 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001960 -1, pixels);
1961}
1962
1963bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001964 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001965 GLint level,
1966 GLint xoffset,
1967 GLint yoffset,
1968 GLint zoffset,
1969 GLsizei width,
1970 GLsizei height,
1971 GLsizei depth,
1972 GLenum format,
1973 GLenum type,
1974 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001975 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001976{
1977 if (context->getClientMajorVersion() < 3)
1978 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001980 return false;
1981 }
1982
1983 if (!ValidateRobustEntryPoint(context, bufSize))
1984 {
1985 return false;
1986 }
1987
1988 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1989 yoffset, zoffset, width, height, depth, 0, format, type,
1990 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001991}
1992
1993bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001994 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001995 GLint level,
1996 GLint xoffset,
1997 GLint yoffset,
1998 GLint zoffset,
1999 GLsizei width,
2000 GLsizei height,
2001 GLsizei depth,
2002 GLenum format,
2003 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002004 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002005{
Martin Radev1be913c2016-07-11 17:59:16 +03002006 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002007 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002009 return false;
2010 }
2011
Geoff Langca271392017-04-05 12:30:00 -04002012 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002013 if (!formatInfo.compressed)
2014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002015 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002016 return false;
2017 }
2018
Jeff Gilbert48590352017-11-07 16:03:38 -08002019 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002020 if (blockSizeOrErr.isError())
2021 {
2022 context->handleError(blockSizeOrErr.getError());
2023 return false;
2024 }
2025 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002027 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002028 return false;
2029 }
2030
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002031 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2032 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2033 -1, data))
2034 {
2035 return false;
2036 }
2037
Jamie Madill73a84962016-02-12 09:27:23 -05002038 if (!data)
2039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002040 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002041 return false;
2042 }
2043
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002044 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002045}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002046
Corentin Wallezb2931602017-04-11 15:58:57 -04002047bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002048 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002049 GLint level,
2050 GLint xoffset,
2051 GLint yoffset,
2052 GLint zoffset,
2053 GLsizei width,
2054 GLsizei height,
2055 GLsizei depth,
2056 GLenum format,
2057 GLsizei imageSize,
2058 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002059 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002060{
2061 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2062 {
2063 return false;
2064 }
2065
2066 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2067 height, depth, format, imageSize, data);
2068}
Jamie Madill73a84962016-02-12 09:27:23 -05002069
Olli Etuaho41997e72016-03-10 13:38:39 +02002070bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2071{
2072 return ValidateGenOrDeleteES3(context, n);
2073}
2074
2075bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2076{
2077 return ValidateGenOrDeleteES3(context, n);
2078}
2079
2080bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2081{
2082 return ValidateGenOrDeleteCountES3(context, count);
2083}
2084
2085bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2086{
2087 return ValidateGenOrDeleteCountES3(context, count);
2088}
2089
2090bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2091{
2092 return ValidateGenOrDeleteES3(context, n);
2093}
2094
2095bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2096{
2097 if (!ValidateGenOrDeleteES3(context, n))
2098 {
2099 return false;
2100 }
2101 for (GLint i = 0; i < n; ++i)
2102 {
2103 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2104 if (transformFeedback != nullptr && transformFeedback->isActive())
2105 {
2106 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002107 context->handleError(InvalidOperation()
2108 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002109 return false;
2110 }
2111 }
2112 return true;
2113}
2114
2115bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2116{
2117 return ValidateGenOrDeleteES3(context, n);
2118}
2119
2120bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2121{
2122 return ValidateGenOrDeleteES3(context, n);
2123}
2124
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002125bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2126{
Martin Radev1be913c2016-07-11 17:59:16 +03002127 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002128 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002130 return false;
2131 }
2132 switch (primitiveMode)
2133 {
2134 case GL_TRIANGLES:
2135 case GL_LINES:
2136 case GL_POINTS:
2137 break;
2138
2139 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002140 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002141 return false;
2142 }
2143
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002144 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002145 ASSERT(transformFeedback != nullptr);
2146
2147 if (transformFeedback->isActive())
2148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002149 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002150 return false;
2151 }
Geoff Lang79f71042017-08-14 16:43:43 -04002152
2153 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2154 {
2155 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2156 if (buffer.get() && buffer->isMapped())
2157 {
2158 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2159 return false;
2160 }
2161 }
2162
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002163 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002164
2165 if (!program)
2166 {
2167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2168 return false;
2169 }
2170
2171 if (program->getTransformFeedbackVaryingCount() == 0)
2172 {
2173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2174 return false;
2175 }
2176
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002177 return true;
2178}
2179
Corentin Wallez336129f2017-10-17 15:55:40 -04002180bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002181{
Geoff Lang496c02d2016-10-20 11:38:11 -07002182 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2183}
2184
2185bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002186 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002187 GLenum pname,
2188 GLsizei bufSize,
2189 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002190 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002191{
2192 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002193 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002194 return false;
2195 }
2196
Brandon Jonesd1049182018-03-28 10:02:20 -07002197 GLsizei numParams = 0;
2198
2199 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002200 {
2201 return false;
2202 }
2203
Brandon Jonesd1049182018-03-28 10:02:20 -07002204 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002205 {
2206 return false;
2207 }
2208
Brandon Jonesd1049182018-03-28 10:02:20 -07002209 SetRobustLengthParam(length, numParams);
2210
Geoff Lang496c02d2016-10-20 11:38:11 -07002211 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002212}
2213
Corentin Wallez336129f2017-10-17 15:55:40 -04002214bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002215{
Martin Radev1be913c2016-07-11 17:59:16 +03002216 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002217 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002219 return false;
2220 }
2221
2222 return ValidateUnmapBufferBase(context, target);
2223}
2224
2225bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002226 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002227 GLintptr offset,
2228 GLsizeiptr length,
2229 GLbitfield access)
2230{
Martin Radev1be913c2016-07-11 17:59:16 +03002231 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002232 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002233 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002234 return false;
2235 }
2236
2237 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2238}
2239
2240bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002241 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002242 GLintptr offset,
2243 GLsizeiptr length)
2244{
Martin Radev1be913c2016-07-11 17:59:16 +03002245 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002246 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002248 return false;
2249 }
2250
2251 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2252}
2253
Jamie Madill5b772312018-03-08 20:28:32 -05002254bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002255{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002256 if (length)
2257 {
2258 *length = 0;
2259 }
2260
Martin Radev66fb8202016-07-28 11:45:20 +03002261 GLenum nativeType;
2262 unsigned int numParams;
2263 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002265 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002266 return false;
2267 }
2268
2269 const Caps &caps = context->getCaps();
2270 switch (pname)
2271 {
2272 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2273 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2274 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2275 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002277 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002278 return false;
2279 }
2280 break;
2281
2282 case GL_UNIFORM_BUFFER_START:
2283 case GL_UNIFORM_BUFFER_SIZE:
2284 case GL_UNIFORM_BUFFER_BINDING:
2285 if (index >= caps.maxUniformBufferBindings)
2286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002287 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002288 return false;
2289 }
2290 break;
Shao80957d92017-02-20 21:25:59 +08002291
Martin Radev66fb8202016-07-28 11:45:20 +03002292 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2293 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2294 if (index >= 3u)
2295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002296 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002297 return false;
2298 }
2299 break;
Shao80957d92017-02-20 21:25:59 +08002300
Jiajia Qin6eafb042016-12-27 17:04:07 +08002301 case GL_ATOMIC_COUNTER_BUFFER_START:
2302 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2303 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2304 if (context->getClientVersion() < ES_3_1)
2305 {
2306 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002307 InvalidEnum()
2308 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002309 return false;
2310 }
2311 if (index >= caps.maxAtomicCounterBufferBindings)
2312 {
2313 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002314 InvalidValue()
2315 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002316 return false;
2317 }
2318 break;
Shao80957d92017-02-20 21:25:59 +08002319
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002320 case GL_SHADER_STORAGE_BUFFER_START:
2321 case GL_SHADER_STORAGE_BUFFER_SIZE:
2322 case GL_SHADER_STORAGE_BUFFER_BINDING:
2323 if (context->getClientVersion() < ES_3_1)
2324 {
2325 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002326 InvalidEnum()
2327 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002328 return false;
2329 }
2330 if (index >= caps.maxShaderStorageBufferBindings)
2331 {
2332 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002333 InvalidValue()
2334 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002335 return false;
2336 }
2337 break;
2338
Shao80957d92017-02-20 21:25:59 +08002339 case GL_VERTEX_BINDING_BUFFER:
2340 case GL_VERTEX_BINDING_DIVISOR:
2341 case GL_VERTEX_BINDING_OFFSET:
2342 case GL_VERTEX_BINDING_STRIDE:
2343 if (context->getClientVersion() < ES_3_1)
2344 {
2345 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002346 InvalidEnum()
2347 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002348 return false;
2349 }
2350 if (index >= caps.maxVertexAttribBindings)
2351 {
2352 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002353 InvalidValue()
2354 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002355 return false;
2356 }
2357 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002358 case GL_SAMPLE_MASK_VALUE:
2359 if (context->getClientVersion() < ES_3_1)
2360 {
2361 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2362 return false;
2363 }
2364 if (index >= caps.maxSampleMaskWords)
2365 {
2366 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2367 return false;
2368 }
2369 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002370 case GL_IMAGE_BINDING_NAME:
2371 case GL_IMAGE_BINDING_LEVEL:
2372 case GL_IMAGE_BINDING_LAYERED:
2373 case GL_IMAGE_BINDING_LAYER:
2374 case GL_IMAGE_BINDING_ACCESS:
2375 case GL_IMAGE_BINDING_FORMAT:
2376 if (context->getClientVersion() < ES_3_1)
2377 {
2378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2379 return false;
2380 }
2381 if (index >= caps.maxImageUnits)
2382 {
2383 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2384 return false;
2385 }
2386 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002387 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002388 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002389 return false;
2390 }
2391
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002392 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002393 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002394 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002395 }
2396
2397 return true;
2398}
2399
Jamie Madill5b772312018-03-08 20:28:32 -05002400bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002401{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002402 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002403 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002405 return false;
2406 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002407 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002408}
2409
Jamie Madill5b772312018-03-08 20:28:32 -05002410bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002411 GLenum target,
2412 GLuint index,
2413 GLsizei bufSize,
2414 GLsizei *length,
2415 GLint *data)
2416{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002417 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002418 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002419 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002420 return false;
2421 }
2422
2423 if (!ValidateRobustEntryPoint(context, bufSize))
2424 {
2425 return false;
2426 }
2427
Brandon Jonesd1049182018-03-28 10:02:20 -07002428 GLsizei numParams = 0;
2429
2430 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002431 {
2432 return false;
2433 }
2434
Brandon Jonesd1049182018-03-28 10:02:20 -07002435 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002436 {
2437 return false;
2438 }
2439
Brandon Jonesd1049182018-03-28 10:02:20 -07002440 SetRobustLengthParam(length, numParams);
2441
Geoff Langcf255ea2016-10-20 11:39:09 -07002442 return true;
2443}
2444
Jamie Madill5b772312018-03-08 20:28:32 -05002445bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002446{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002447 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002448 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002449 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002450 return false;
2451 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002452 return ValidateIndexedStateQuery(context, target, index, nullptr);
2453}
2454
Jamie Madill5b772312018-03-08 20:28:32 -05002455bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002456 GLenum target,
2457 GLuint index,
2458 GLsizei bufSize,
2459 GLsizei *length,
2460 GLint64 *data)
2461{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002462 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002463 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002465 return false;
2466 }
2467
2468 if (!ValidateRobustEntryPoint(context, bufSize))
2469 {
2470 return false;
2471 }
2472
Brandon Jonesd1049182018-03-28 10:02:20 -07002473 GLsizei numParams = 0;
2474
2475 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002476 {
2477 return false;
2478 }
2479
Brandon Jonesd1049182018-03-28 10:02:20 -07002480 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002481 {
2482 return false;
2483 }
2484
Brandon Jonesd1049182018-03-28 10:02:20 -07002485 SetRobustLengthParam(length, numParams);
2486
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002487 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002488}
2489
Jamie Madill5b772312018-03-08 20:28:32 -05002490bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002491 BufferBinding readTarget,
2492 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002493 GLintptr readOffset,
2494 GLintptr writeOffset,
2495 GLsizeiptr size)
2496{
2497 if (context->getClientMajorVersion() < 3)
2498 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002500 return false;
2501 }
2502
Corentin Walleze4477002017-12-01 14:39:58 -05002503 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002505 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002506 return false;
2507 }
2508
2509 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2510 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2511
2512 if (!readBuffer || !writeBuffer)
2513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002514 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002515 return false;
2516 }
2517
2518 // Verify that readBuffer and writeBuffer are not currently mapped
2519 if (readBuffer->isMapped() || writeBuffer->isMapped())
2520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002521 context->handleError(InvalidOperation()
2522 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002523 return false;
2524 }
2525
James Darpiniane8a93c62018-01-04 18:02:24 -08002526 if (context->getExtensions().webglCompatibility &&
2527 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2528 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2529 {
2530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2531 return false;
2532 }
2533
Jamie Madilld2f0c742016-11-02 10:34:41 -04002534 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2535 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2536 CheckedNumeric<GLintptr> checkedSize(size);
2537
2538 auto checkedReadSum = checkedReadOffset + checkedSize;
2539 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2540
2541 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2542 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2543 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002546 return false;
2547 }
2548
Jamie Madilld2f0c742016-11-02 10:34:41 -04002549 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002551 context->handleError(InvalidValue()
2552 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002553 return false;
2554 }
2555
Jamie Madilld2f0c742016-11-02 10:34:41 -04002556 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2557 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002560 return false;
2561 }
2562
2563 if (readBuffer == writeBuffer)
2564 {
2565 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2566 if (!checkedOffsetDiff.IsValid())
2567 {
2568 // This shold not be possible.
2569 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002570 context->handleError(InvalidValue()
2571 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002572 return false;
2573 }
2574
2575 if (checkedOffsetDiff.ValueOrDie() < size)
2576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002577 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002578 return false;
2579 }
2580 }
2581
Jamie Madillb0817d12016-11-01 15:48:31 -04002582 return true;
2583}
2584
Geoff Langc339c4e2016-11-29 10:37:36 -05002585bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2586{
2587 if (context->getClientMajorVersion() < 3)
2588 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002590 return false;
2591 }
2592
2593 switch (name)
2594 {
2595 case GL_EXTENSIONS:
2596 if (index >= context->getExtensionStringCount())
2597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidValue()
2599 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002600 return false;
2601 }
2602 break;
2603
2604 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2605 if (!context->getExtensions().requestExtension)
2606 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002607 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002608 return false;
2609 }
2610 if (index >= context->getRequestableExtensionStringCount())
2611 {
2612 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002613 InvalidValue()
2614 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002615 return false;
2616 }
2617 break;
2618
2619 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002620 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002621 return false;
2622 }
2623
2624 return true;
2625}
2626
Jamie Madill5b772312018-03-08 20:28:32 -05002627bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002628 GLenum target,
2629 GLsizei samples,
2630 GLenum internalformat,
2631 GLsizei width,
2632 GLsizei height)
2633{
2634 if (context->getClientMajorVersion() < 3)
2635 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002637 return false;
2638 }
2639
2640 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2641 height))
2642 {
2643 return false;
2644 }
2645
2646 // 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 +08002647 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2648 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002649 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002650 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002651 {
Yunchao Hec0810202018-01-22 09:48:48 +08002652 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2653 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2654 {
2655 context->handleError(InvalidOperation());
2656 return false;
2657 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002658 }
2659
2660 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2661 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2662 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2663 {
2664 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002665 InvalidOperation()
2666 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002667 return false;
2668 }
2669
2670 return true;
2671}
2672
Jamie Madill5b772312018-03-08 20:28:32 -05002673bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002674 GLuint index,
2675 GLint size,
2676 GLenum type,
2677 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002678 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002679{
2680 if (context->getClientMajorVersion() < 3)
2681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002683 return false;
2684 }
2685
Shao80957d92017-02-20 21:25:59 +08002686 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002687 {
Geoff Langaa086d62017-03-23 16:47:21 -04002688 return false;
2689 }
2690
Geoff Langaa086d62017-03-23 16:47:21 -04002691 if (stride < 0)
2692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002693 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002694 return false;
2695 }
2696
Shao80957d92017-02-20 21:25:59 +08002697 const Caps &caps = context->getCaps();
2698 if (context->getClientVersion() >= ES_3_1)
2699 {
2700 if (stride > caps.maxVertexAttribStride)
2701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002702 context->handleError(InvalidValue()
2703 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002704 return false;
2705 }
2706
2707 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2708 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2709 // validation should be inherited.
2710 if (index >= caps.maxVertexAttribBindings)
2711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002712 context->handleError(InvalidValue()
2713 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002714 return false;
2715 }
2716 }
2717
Geoff Langaa086d62017-03-23 16:47:21 -04002718 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2719 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2720 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2721 // and the pointer argument is not NULL.
2722 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002723 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002725 context
2726 ->handleError(InvalidOperation()
2727 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002728 return false;
2729 }
2730
Geoff Lang2d62ab72017-03-23 16:54:40 -04002731 if (context->getExtensions().webglCompatibility)
2732 {
2733 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2734 {
2735 return false;
2736 }
2737 }
2738
Geoff Langaa086d62017-03-23 16:47:21 -04002739 return true;
2740}
2741
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002742bool ValidateGetSynciv(Context *context,
2743 GLsync sync,
2744 GLenum pname,
2745 GLsizei bufSize,
2746 GLsizei *length,
2747 GLint *values)
2748{
2749 if (context->getClientMajorVersion() < 3)
2750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002751 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002752 return false;
2753 }
2754
2755 if (bufSize < 0)
2756 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002757 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002758 return false;
2759 }
2760
Jamie Madill70b5bb02017-08-28 13:32:37 -04002761 Sync *syncObject = context->getSync(sync);
2762 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002764 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002765 return false;
2766 }
2767
2768 switch (pname)
2769 {
2770 case GL_OBJECT_TYPE:
2771 case GL_SYNC_CONDITION:
2772 case GL_SYNC_FLAGS:
2773 case GL_SYNC_STATUS:
2774 break;
2775
2776 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002777 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002778 return false;
2779 }
2780
2781 return true;
2782}
2783
Jamie Madill5b772312018-03-08 20:28:32 -05002784bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002785 GLenum mode,
2786 GLsizei count,
2787 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002788 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002789 GLsizei instanceCount)
2790{
2791 if (context->getClientMajorVersion() < 3)
2792 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002794 return false;
2795 }
2796
2797 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2798}
2799
Martin Radev137032d2017-07-13 10:11:12 +03002800bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2801 GLenum target,
2802 GLenum attachment,
2803 GLuint texture,
2804 GLint level,
2805 GLint baseViewIndex,
2806 GLsizei numViews)
2807{
2808
2809 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2810 numViews))
2811 {
2812 return false;
2813 }
2814
Martin Radev137032d2017-07-13 10:11:12 +03002815 if (texture != 0)
2816 {
Martin Radev14b21262017-08-25 13:54:37 +03002817 if (baseViewIndex < 0)
2818 {
2819 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2820 return false;
2821 }
2822
Martin Radev137032d2017-07-13 10:11:12 +03002823 Texture *tex = context->getTexture(texture);
2824 ASSERT(tex);
2825
Corentin Wallez99d492c2018-02-27 15:17:10 -05002826 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002827 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002828 case TextureType::_2DArray:
Martin Radev137032d2017-07-13 10:11:12 +03002829 {
2830 const Caps &caps = context->getCaps();
2831 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2832 {
2833 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2834 "greater than "
2835 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2836 return false;
2837 }
2838 }
2839 break;
2840 default:
2841 context->handleError(InvalidOperation()
2842 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2843 return false;
2844 }
2845
2846 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2847 {
2848 return false;
2849 }
2850 }
2851
2852 return true;
2853}
2854
2855bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2856 GLenum target,
2857 GLenum attachment,
2858 GLuint texture,
2859 GLint level,
2860 GLsizei numViews,
2861 const GLint *viewportOffsets)
2862{
2863 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2864 numViews))
2865 {
2866 return false;
2867 }
2868
Martin Radev137032d2017-07-13 10:11:12 +03002869 if (texture != 0)
2870 {
Martin Radev14b21262017-08-25 13:54:37 +03002871 const GLsizei numViewportOffsetValues = numViews * 2;
2872 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2873 {
2874 if (viewportOffsets[i] < 0)
2875 {
2876 context->handleError(InvalidValue()
2877 << "viewportOffsets cannot contain negative values.");
2878 return false;
2879 }
2880 }
2881
Martin Radev137032d2017-07-13 10:11:12 +03002882 Texture *tex = context->getTexture(texture);
2883 ASSERT(tex);
2884
Corentin Wallez99d492c2018-02-27 15:17:10 -05002885 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03002886 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05002887 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03002888 break;
2889 default:
2890 context->handleError(InvalidOperation()
2891 << "Texture's target must be GL_TEXTURE_2D.");
2892 return false;
2893 }
2894
2895 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2896 {
2897 return false;
2898 }
2899 }
2900
2901 return true;
2902}
2903
Jamie Madillff325f12017-08-26 15:06:05 -04002904bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2905{
2906 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2907}
2908
2909bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2910{
2911 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2912}
2913
2914bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2915{
2916 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2917}
2918
2919bool ValidateUniform4ui(Context *context,
2920 GLint location,
2921 GLuint v0,
2922 GLuint v1,
2923 GLuint v2,
2924 GLuint v3)
2925{
2926 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2927}
2928
2929bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2930{
2931 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2932}
2933
2934bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2935{
2936 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2937}
2938
2939bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2940{
2941 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2942}
2943
2944bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2945{
2946 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2947}
2948
Jamie Madillf0e04492017-08-26 15:28:42 -04002949bool ValidateIsQuery(Context *context, GLuint id)
2950{
2951 if (context->getClientMajorVersion() < 3)
2952 {
2953 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2954 return false;
2955 }
2956
2957 return true;
2958}
2959
Jamie Madillc8c95812017-08-26 18:40:09 -04002960bool ValidateUniformMatrix2x3fv(Context *context,
2961 GLint location,
2962 GLsizei count,
2963 GLboolean transpose,
2964 const GLfloat *value)
2965{
2966 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2967}
2968
2969bool ValidateUniformMatrix3x2fv(Context *context,
2970 GLint location,
2971 GLsizei count,
2972 GLboolean transpose,
2973 const GLfloat *value)
2974{
2975 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2976}
2977
2978bool ValidateUniformMatrix2x4fv(Context *context,
2979 GLint location,
2980 GLsizei count,
2981 GLboolean transpose,
2982 const GLfloat *value)
2983{
2984 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2985}
2986
2987bool ValidateUniformMatrix4x2fv(Context *context,
2988 GLint location,
2989 GLsizei count,
2990 GLboolean transpose,
2991 const GLfloat *value)
2992{
2993 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2994}
2995
2996bool ValidateUniformMatrix3x4fv(Context *context,
2997 GLint location,
2998 GLsizei count,
2999 GLboolean transpose,
3000 const GLfloat *value)
3001{
3002 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3003}
3004
3005bool ValidateUniformMatrix4x3fv(Context *context,
3006 GLint location,
3007 GLsizei count,
3008 GLboolean transpose,
3009 const GLfloat *value)
3010{
3011 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3012}
3013
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003014bool ValidateEndTransformFeedback(Context *context)
3015{
3016 if (context->getClientMajorVersion() < 3)
3017 {
3018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3019 return false;
3020 }
3021
3022 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3023 ASSERT(transformFeedback != nullptr);
3024
3025 if (!transformFeedback->isActive())
3026 {
3027 context->handleError(InvalidOperation());
3028 return false;
3029 }
3030
3031 return true;
3032}
3033
3034bool ValidateTransformFeedbackVaryings(Context *context,
3035 GLuint program,
3036 GLsizei count,
3037 const GLchar *const *varyings,
3038 GLenum bufferMode)
3039{
3040 if (context->getClientMajorVersion() < 3)
3041 {
3042 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3043 return false;
3044 }
3045
3046 if (count < 0)
3047 {
3048 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3049 return false;
3050 }
3051
3052 switch (bufferMode)
3053 {
3054 case GL_INTERLEAVED_ATTRIBS:
3055 break;
3056 case GL_SEPARATE_ATTRIBS:
3057 {
3058 const Caps &caps = context->getCaps();
3059 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3060 {
3061 context->handleError(InvalidValue());
3062 return false;
3063 }
3064 break;
3065 }
3066 default:
3067 context->handleError(InvalidEnum());
3068 return false;
3069 }
3070
3071 Program *programObject = GetValidProgram(context, program);
3072 if (!programObject)
3073 {
3074 return false;
3075 }
3076
3077 return true;
3078}
3079
3080bool ValidateGetTransformFeedbackVarying(Context *context,
3081 GLuint program,
3082 GLuint index,
3083 GLsizei bufSize,
3084 GLsizei *length,
3085 GLsizei *size,
3086 GLenum *type,
3087 GLchar *name)
3088{
3089 if (context->getClientMajorVersion() < 3)
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3092 return false;
3093 }
3094
3095 if (bufSize < 0)
3096 {
3097 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3098 return false;
3099 }
3100
3101 Program *programObject = GetValidProgram(context, program);
3102 if (!programObject)
3103 {
3104 return false;
3105 }
3106
3107 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3108 {
3109 context->handleError(InvalidValue());
3110 return false;
3111 }
3112
3113 return true;
3114}
3115
3116bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3117{
3118 if (context->getClientMajorVersion() < 3)
3119 {
3120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3121 return false;
3122 }
3123
3124 switch (target)
3125 {
3126 case GL_TRANSFORM_FEEDBACK:
3127 {
3128 // Cannot bind a transform feedback object if the current one is started and not
3129 // paused (3.0.2 pg 85 section 2.14.1)
3130 TransformFeedback *curTransformFeedback =
3131 context->getGLState().getCurrentTransformFeedback();
3132 if (curTransformFeedback && curTransformFeedback->isActive() &&
3133 !curTransformFeedback->isPaused())
3134 {
3135 context->handleError(InvalidOperation());
3136 return false;
3137 }
3138
3139 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3140 // 2.14.1)
3141 if (!context->isTransformFeedbackGenerated(id))
3142 {
3143 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3144 return false;
3145 }
3146 }
3147 break;
3148
3149 default:
3150 context->handleError(InvalidEnum());
3151 return false;
3152 }
3153
3154 return true;
3155}
3156
3157bool ValidateIsTransformFeedback(Context *context, GLuint id)
3158{
3159 if (context->getClientMajorVersion() < 3)
3160 {
3161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3162 return false;
3163 }
3164
3165 return true;
3166}
3167
3168bool ValidatePauseTransformFeedback(Context *context)
3169{
3170 if (context->getClientMajorVersion() < 3)
3171 {
3172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3173 return false;
3174 }
3175
3176 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3177 ASSERT(transformFeedback != nullptr);
3178
3179 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3180 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3181 {
3182 context->handleError(InvalidOperation());
3183 return false;
3184 }
3185
3186 return true;
3187}
3188
3189bool ValidateResumeTransformFeedback(Context *context)
3190{
3191 if (context->getClientMajorVersion() < 3)
3192 {
3193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3194 return false;
3195 }
3196
3197 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3198 ASSERT(transformFeedback != nullptr);
3199
3200 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3201 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3202 {
3203 context->handleError(InvalidOperation());
3204 return false;
3205 }
3206
3207 return true;
3208}
3209
Jamie Madill12e957f2017-08-26 21:42:26 -04003210bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3211{
3212 if (context->getClientMajorVersion() < 3)
3213 {
3214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3215 return false;
3216 }
3217
3218 return ValidateVertexAttribIndex(context, index);
3219}
3220
3221bool ValidateVertexAttribI4ui(Context *context,
3222 GLuint index,
3223 GLuint x,
3224 GLuint y,
3225 GLuint z,
3226 GLuint w)
3227{
3228 if (context->getClientMajorVersion() < 3)
3229 {
3230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3231 return false;
3232 }
3233
3234 return ValidateVertexAttribIndex(context, index);
3235}
3236
3237bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3238{
3239 if (context->getClientMajorVersion() < 3)
3240 {
3241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3242 return false;
3243 }
3244
3245 return ValidateVertexAttribIndex(context, index);
3246}
3247
3248bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3249{
3250 if (context->getClientMajorVersion() < 3)
3251 {
3252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3253 return false;
3254 }
3255
3256 return ValidateVertexAttribIndex(context, index);
3257}
3258
3259bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3260{
3261 if (context->getClientMajorVersion() < 3)
3262 {
3263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3264 return false;
3265 }
3266
3267 Program *programObject = GetValidProgram(context, program);
3268 if (!programObject)
3269 {
3270 return false;
3271 }
3272
3273 if (!programObject->isLinked())
3274 {
3275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3276 return false;
3277 }
3278
3279 return true;
3280}
3281
3282bool ValidateGetUniformIndices(Context *context,
3283 GLuint program,
3284 GLsizei uniformCount,
3285 const GLchar *const *uniformNames,
3286 GLuint *uniformIndices)
3287{
3288 if (context->getClientMajorVersion() < 3)
3289 {
3290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3291 return false;
3292 }
3293
3294 if (uniformCount < 0)
3295 {
3296 context->handleError(InvalidValue());
3297 return false;
3298 }
3299
3300 Program *programObject = GetValidProgram(context, program);
3301 if (!programObject)
3302 {
3303 return false;
3304 }
3305
3306 return true;
3307}
3308
3309bool ValidateGetActiveUniformsiv(Context *context,
3310 GLuint program,
3311 GLsizei uniformCount,
3312 const GLuint *uniformIndices,
3313 GLenum pname,
3314 GLint *params)
3315{
3316 if (context->getClientMajorVersion() < 3)
3317 {
3318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3319 return false;
3320 }
3321
3322 if (uniformCount < 0)
3323 {
3324 context->handleError(InvalidValue());
3325 return false;
3326 }
3327
3328 Program *programObject = GetValidProgram(context, program);
3329 if (!programObject)
3330 {
3331 return false;
3332 }
3333
3334 switch (pname)
3335 {
3336 case GL_UNIFORM_TYPE:
3337 case GL_UNIFORM_SIZE:
3338 case GL_UNIFORM_NAME_LENGTH:
3339 case GL_UNIFORM_BLOCK_INDEX:
3340 case GL_UNIFORM_OFFSET:
3341 case GL_UNIFORM_ARRAY_STRIDE:
3342 case GL_UNIFORM_MATRIX_STRIDE:
3343 case GL_UNIFORM_IS_ROW_MAJOR:
3344 break;
3345
3346 default:
3347 context->handleError(InvalidEnum());
3348 return false;
3349 }
3350
3351 if (uniformCount > programObject->getActiveUniformCount())
3352 {
3353 context->handleError(InvalidValue());
3354 return false;
3355 }
3356
3357 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3358 {
3359 const GLuint index = uniformIndices[uniformId];
3360
3361 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3362 {
3363 context->handleError(InvalidValue());
3364 return false;
3365 }
3366 }
3367
3368 return true;
3369}
3370
3371bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3372{
3373 if (context->getClientMajorVersion() < 3)
3374 {
3375 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3376 return false;
3377 }
3378
3379 Program *programObject = GetValidProgram(context, program);
3380 if (!programObject)
3381 {
3382 return false;
3383 }
3384
3385 return true;
3386}
3387
3388bool ValidateGetActiveUniformBlockiv(Context *context,
3389 GLuint program,
3390 GLuint uniformBlockIndex,
3391 GLenum pname,
3392 GLint *params)
3393{
3394 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3395}
3396
3397bool ValidateGetActiveUniformBlockName(Context *context,
3398 GLuint program,
3399 GLuint uniformBlockIndex,
3400 GLsizei bufSize,
3401 GLsizei *length,
3402 GLchar *uniformBlockName)
3403{
3404 if (context->getClientMajorVersion() < 3)
3405 {
3406 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3407 return false;
3408 }
3409
3410 Program *programObject = GetValidProgram(context, program);
3411 if (!programObject)
3412 {
3413 return false;
3414 }
3415
3416 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3417 {
3418 context->handleError(InvalidValue());
3419 return false;
3420 }
3421
3422 return true;
3423}
3424
3425bool ValidateUniformBlockBinding(Context *context,
3426 GLuint program,
3427 GLuint uniformBlockIndex,
3428 GLuint uniformBlockBinding)
3429{
3430 if (context->getClientMajorVersion() < 3)
3431 {
3432 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3433 return false;
3434 }
3435
3436 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3437 {
3438 context->handleError(InvalidValue());
3439 return false;
3440 }
3441
3442 Program *programObject = GetValidProgram(context, program);
3443 if (!programObject)
3444 {
3445 return false;
3446 }
3447
3448 // if never linked, there won't be any uniform blocks
3449 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3450 {
3451 context->handleError(InvalidValue());
3452 return false;
3453 }
3454
3455 return true;
3456}
3457
3458bool ValidateDrawArraysInstanced(Context *context,
3459 GLenum mode,
3460 GLint first,
3461 GLsizei count,
3462 GLsizei primcount)
3463{
3464 if (context->getClientMajorVersion() < 3)
3465 {
3466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3467 return false;
3468 }
3469
3470 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3471}
3472
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003473bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3474{
3475 if (context->getClientMajorVersion() < 3)
3476 {
3477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3478 return false;
3479 }
3480
3481 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3482 {
3483 context->handleError(InvalidEnum());
3484 return false;
3485 }
3486
3487 if (flags != 0)
3488 {
3489 context->handleError(InvalidValue());
3490 return false;
3491 }
3492
3493 return true;
3494}
3495
3496bool ValidateIsSync(Context *context, GLsync sync)
3497{
3498 if (context->getClientMajorVersion() < 3)
3499 {
3500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3501 return false;
3502 }
3503
3504 return true;
3505}
3506
3507bool ValidateDeleteSync(Context *context, GLsync sync)
3508{
3509 if (context->getClientMajorVersion() < 3)
3510 {
3511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3512 return false;
3513 }
3514
Jamie Madill70b5bb02017-08-28 13:32:37 -04003515 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003516 {
3517 context->handleError(InvalidValue());
3518 return false;
3519 }
3520
3521 return true;
3522}
3523
3524bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3525{
3526 if (context->getClientMajorVersion() < 3)
3527 {
3528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3529 return false;
3530 }
3531
3532 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3533 {
3534 context->handleError(InvalidValue());
3535 return false;
3536 }
3537
Jamie Madill70b5bb02017-08-28 13:32:37 -04003538 Sync *clientWaitSync = context->getSync(sync);
3539 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003540 {
3541 context->handleError(InvalidValue());
3542 return false;
3543 }
3544
3545 return true;
3546}
3547
3548bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3549{
3550 if (context->getClientMajorVersion() < 3)
3551 {
3552 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3553 return false;
3554 }
3555
3556 if (flags != 0)
3557 {
3558 context->handleError(InvalidValue());
3559 return false;
3560 }
3561
3562 if (timeout != GL_TIMEOUT_IGNORED)
3563 {
3564 context->handleError(InvalidValue());
3565 return false;
3566 }
3567
Jamie Madill70b5bb02017-08-28 13:32:37 -04003568 Sync *waitSync = context->getSync(sync);
3569 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003570 {
3571 context->handleError(InvalidValue());
3572 return false;
3573 }
3574
3575 return true;
3576}
3577
3578bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3579{
3580 if (context->getClientMajorVersion() < 3)
3581 {
3582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3583 return false;
3584 }
3585
3586 GLenum nativeType = GL_NONE;
3587 unsigned int numParams = 0;
3588 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3589 {
3590 return false;
3591 }
3592
3593 return true;
3594}
3595
Jamie Madill3ef140a2017-08-26 23:11:21 -04003596bool ValidateIsSampler(Context *context, GLuint sampler)
3597{
3598 if (context->getClientMajorVersion() < 3)
3599 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003600 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003601 return false;
3602 }
3603
3604 return true;
3605}
3606
3607bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3608{
3609 if (context->getClientMajorVersion() < 3)
3610 {
3611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3612 return false;
3613 }
3614
3615 if (sampler != 0 && !context->isSampler(sampler))
3616 {
3617 context->handleError(InvalidOperation());
3618 return false;
3619 }
3620
3621 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3622 {
3623 context->handleError(InvalidValue());
3624 return false;
3625 }
3626
3627 return true;
3628}
3629
3630bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3631{
3632 if (context->getClientMajorVersion() < 3)
3633 {
3634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3635 return false;
3636 }
3637
3638 return ValidateVertexAttribIndex(context, index);
3639}
3640
3641bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003642 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003643 GLsizei levels,
3644 GLenum internalformat,
3645 GLsizei width,
3646 GLsizei height)
3647{
3648 if (context->getClientMajorVersion() < 3)
3649 {
3650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3651 return false;
3652 }
3653
3654 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3655 1))
3656 {
3657 return false;
3658 }
3659
3660 return true;
3661}
3662
3663bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003664 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003665 GLsizei levels,
3666 GLenum internalformat,
3667 GLsizei width,
3668 GLsizei height,
3669 GLsizei depth)
3670{
3671 if (context->getClientMajorVersion() < 3)
3672 {
3673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3674 return false;
3675 }
3676
3677 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3678 depth))
3679 {
3680 return false;
3681 }
3682
3683 return true;
3684}
3685
Jamie Madill5b772312018-03-08 20:28:32 -05003686bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003687 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003688 GLenum pname,
3689 GLint64 *params)
3690{
3691 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3692}
3693
3694bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3695{
3696 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3697}
3698
3699bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3700{
3701 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3702}
3703
3704bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3705{
3706 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3707}
3708
3709bool ValidateSamplerParameterfv(Context *context,
3710 GLuint sampler,
3711 GLenum pname,
3712 const GLfloat *params)
3713{
3714 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3715}
3716
3717bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3718{
3719 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3720}
3721
3722bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3723{
3724 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3725}
3726
3727bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3728{
3729 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3730}
3731
3732bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3733{
3734 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3735}
3736
3737bool ValidateGetInternalformativ(Context *context,
3738 GLenum target,
3739 GLenum internalformat,
3740 GLenum pname,
3741 GLsizei bufSize,
3742 GLint *params)
3743{
3744 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3745 nullptr);
3746}
3747
Jamie Madillc29968b2016-01-20 11:17:23 -05003748} // namespace gl