blob: 2c9c4f8122337e64a6a47e7d850d3686f9b2458f [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
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500784bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800785 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786 GLint level,
787 GLenum internalformat,
788 bool isSubImage,
789 GLint xoffset,
790 GLint yoffset,
791 GLint zoffset,
792 GLint x,
793 GLint y,
794 GLsizei width,
795 GLsizei height,
796 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400798 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400799 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 xoffset, yoffset, zoffset, x, y, width, height, border,
801 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400802 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400803 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400805 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806
Jamie Madill51f40ec2016-06-15 14:06:00 -0400807 const auto &state = context->getGLState();
808 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
809 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400810
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400811 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500813 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400815 }
816
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400817 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500819 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400821 }
822
Jamie Madill0c8abca2016-07-22 20:21:26 -0400823 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824
825 if (isSubImage)
826 {
Geoff Langca271392017-04-05 12:30:00 -0400827 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500828 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500830 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400831 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 }
833 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400834 else
835 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400836 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400837 const InternalFormat &framebufferFormat = *source->getFormat().info;
838 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400839 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500841 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400843 }
844 }
845
Geoff Lang784a8fd2013-09-24 12:33:16 -0400846 // If width or height is zero, it is a no-op. Return false without setting an error.
847 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848}
849
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500850bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800851 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500852 GLint level,
853 GLenum internalformat,
854 bool isSubImage,
855 GLint xoffset,
856 GLint yoffset,
857 GLint zoffset,
858 GLint x,
859 GLint y,
860 GLsizei width,
861 GLsizei height,
862 GLint border)
863{
864 if (!ValidTexture2DDestinationTarget(context, target))
865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500866 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500867 return false;
868 }
869
870 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
871 xoffset, yoffset, zoffset, x, y, width, height,
872 border);
873}
874
875bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800876 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500877 GLint level,
878 GLenum internalformat,
879 bool isSubImage,
880 GLint xoffset,
881 GLint yoffset,
882 GLint zoffset,
883 GLint x,
884 GLint y,
885 GLsizei width,
886 GLsizei height,
887 GLint border)
888{
889 if (!ValidTexture3DDestinationTarget(context, target))
890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500892 return false;
893 }
894
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800895 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
896 internalformat, isSubImage, xoffset, yoffset,
897 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898}
899
900bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500902 GLsizei levels,
903 GLenum internalformat,
904 GLsizei width,
905 GLsizei height,
906 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907{
908 if (width < 1 || height < 1 || depth < 1 || levels < 1)
909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500910 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 }
913
Geoff Langb92c1332015-09-04 12:54:55 -0400914 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800915 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -0400916 {
917 maxDim = std::max(maxDim, depth);
918 }
919
920 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500922 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925
Geoff Langaae65a42014-05-26 12:43:44 -0400926 const gl::Caps &caps = context->getCaps();
927
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 switch (target)
929 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800930 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931 {
Geoff Langaae65a42014-05-26 12:43:44 -0400932 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
933 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500935 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 }
938 }
939 break;
940
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800941 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400942 {
943 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
944 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
945 {
946 context->handleError(InvalidValue());
947 return false;
948 }
949 }
950 break;
951
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800952 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 if (width != height)
955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959
Geoff Langaae65a42014-05-26 12:43:44 -0400960 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965 }
966 break;
967
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800968 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 {
Geoff Langaae65a42014-05-26 12:43:44 -0400970 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
971 static_cast<GLuint>(height) > caps.max3DTextureSize ||
972 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500974 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400975 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976 }
977 }
978 break;
979
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800980 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400981 {
Geoff Langaae65a42014-05-26 12:43:44 -0400982 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
983 static_cast<GLuint>(height) > caps.max2DTextureSize ||
984 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500986 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400988 }
989 }
990 break;
991
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 default:
993 UNREACHABLE();
994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400995 }
996
Geoff Lang691e58c2014-12-19 17:03:25 -0500997 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 if (!texture || texture->id() == 0)
999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Geoff Lang69cce582015-09-17 13:20:36 -04001004 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Geoff Langca271392017-04-05 12:30:00 -04001010 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001011 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016
Geoff Langca271392017-04-05 12:30:00 -04001017 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001023 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001024 {
1025 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1026 return false;
1027 }
1028
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 return true;
1030}
1031
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001032bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001033 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001034 GLsizei levels,
1035 GLenum internalformat,
1036 GLsizei width,
1037 GLsizei height,
1038 GLsizei depth)
1039{
1040 if (!ValidTexture2DTarget(context, target))
1041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001042 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001043 return false;
1044 }
1045
1046 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1047 height, depth);
1048}
1049
1050bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001051 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001052 GLsizei levels,
1053 GLenum internalformat,
1054 GLsizei width,
1055 GLsizei height,
1056 GLsizei depth)
1057{
1058 if (!ValidTexture3DTarget(context, target))
1059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001060 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001061 return false;
1062 }
1063
1064 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1065 height, depth);
1066}
1067
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001068bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1069{
Martin Radev1be913c2016-07-11 17:59:16 +03001070 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001071 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001073 return false;
1074 }
1075
1076 return ValidateBeginQueryBase(context, target, id);
1077}
1078
1079bool ValidateEndQuery(gl::Context *context, GLenum target)
1080{
Martin Radev1be913c2016-07-11 17:59:16 +03001081 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001082 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001084 return false;
1085 }
1086
1087 return ValidateEndQueryBase(context, target);
1088}
1089
1090bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1091{
Martin Radev1be913c2016-07-11 17:59:16 +03001092 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001095 return false;
1096 }
1097
Geoff Lang2186c382016-10-14 10:54:54 -04001098 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001099}
1100
1101bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1102{
Martin Radev1be913c2016-07-11 17:59:16 +03001103 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001104 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001106 return false;
1107 }
1108
Geoff Lang2186c382016-10-14 10:54:54 -04001109 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001110}
1111
He Yunchaoced53ae2016-11-29 15:00:51 +08001112bool ValidateFramebufferTextureLayer(Context *context,
1113 GLenum target,
1114 GLenum attachment,
1115 GLuint texture,
1116 GLint level,
1117 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001118{
Martin Radev1be913c2016-07-11 17:59:16 +03001119 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001120 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001122 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001123 }
1124
Jamie Madill55ec3b12014-07-03 10:38:57 -04001125 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1126 {
1127 return false;
1128 }
1129
1130 const gl::Caps &caps = context->getCaps();
1131 if (texture != 0)
1132 {
Geoff Lang23e02842017-10-17 13:24:09 -04001133 if (layer < 0)
1134 {
1135 context->handleError(InvalidValue());
1136 return false;
1137 }
1138
Jamie Madill55ec3b12014-07-03 10:38:57 -04001139 gl::Texture *tex = context->getTexture(texture);
1140 ASSERT(tex);
1141
1142 switch (tex->getTarget())
1143 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001144 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001145 {
1146 if (level > gl::log2(caps.max2DTextureSize))
1147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001150 }
1151
1152 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001156 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001157 }
1158 break;
1159
He Yunchaoced53ae2016-11-29 15:00:51 +08001160 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001161 {
1162 if (level > gl::log2(caps.max3DTextureSize))
1163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001166 }
1167
1168 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001172 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001173 }
1174 break;
1175
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001177 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001179 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001180
Jamie Madilla3944d42016-07-22 22:13:26 -04001181 const auto &format = tex->getFormat(tex->getTarget(), level);
1182 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001184 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001185 return false;
1186 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001187 }
1188
1189 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001190}
1191
He Yunchaoced53ae2016-11-29 15:00:51 +08001192bool ValidateInvalidateFramebuffer(Context *context,
1193 GLenum target,
1194 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001195 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001196{
Martin Radev1be913c2016-07-11 17:59:16 +03001197 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001198 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001200 return false;
1201 }
1202
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 bool defaultFramebuffer = false;
1204
1205 switch (target)
1206 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001207 case GL_DRAW_FRAMEBUFFER:
1208 case GL_FRAMEBUFFER:
1209 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1210 break;
1211 case GL_READ_FRAMEBUFFER:
1212 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1213 break;
1214 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
He Yunchaoced53ae2016-11-29 15:00:51 +08001219 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1220 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001221}
1222
Jamie Madill3ef140a2017-08-26 23:11:21 -04001223bool ValidateInvalidateSubFramebuffer(Context *context,
1224 GLenum target,
1225 GLsizei numAttachments,
1226 const GLenum *attachments,
1227 GLint x,
1228 GLint y,
1229 GLsizei width,
1230 GLsizei height)
1231{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001232 if (width < 0 || height < 0)
1233 {
1234 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1235 return false;
1236 }
1237
Jamie Madill3ef140a2017-08-26 23:11:21 -04001238 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1239}
1240
Jamie Madillc29968b2016-01-20 11:17:23 -05001241bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001242{
Martin Radev1be913c2016-07-11 17:59:16 +03001243 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001244 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001246 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001247 }
1248
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001249 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001251 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001253 }
1254
1255 return true;
1256}
1257
Olli Etuaho71dfb362016-03-10 14:04:27 +02001258bool ValidateDrawRangeElements(Context *context,
1259 GLenum mode,
1260 GLuint start,
1261 GLuint end,
1262 GLsizei count,
1263 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001264 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001265{
Martin Radev1be913c2016-07-11 17:59:16 +03001266 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001267 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001269 return false;
1270 }
1271
1272 if (end < start)
1273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001275 return false;
1276 }
1277
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001278 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001279 {
1280 return false;
1281 }
1282
Jamie Madill9fdaa492018-02-16 10:52:11 -05001283 // Skip range checks for no-op calls.
1284 if (count <= 0)
1285 {
1286 return true;
1287 }
1288
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001289 // Use the parameter buffer to retrieve and cache the index range.
1290 const auto &params = context->getParams<HasIndexRange>();
1291 const auto &indexRangeOpt = params.getIndexRange();
1292 if (!indexRangeOpt.valid())
1293 {
1294 // Unexpected error.
1295 return false;
1296 }
1297
1298 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001299 {
1300 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001301 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001302 return false;
1303 }
1304 return true;
1305}
1306
He Yunchaoced53ae2016-11-29 15:00:51 +08001307bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001308{
Martin Radev1be913c2016-07-11 17:59:16 +03001309 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001310 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001312 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001313 }
1314
Jamie Madill78f41802014-08-25 15:47:55 -04001315 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001316}
1317
Jamie Madillb885e572015-02-03 16:16:04 -05001318bool ValidateReadBuffer(Context *context, GLenum src)
1319{
Martin Radev1be913c2016-07-11 17:59:16 +03001320 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001321 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001323 return false;
1324 }
1325
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001326 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001327
1328 if (readFBO == nullptr)
1329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001330 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001331 return false;
1332 }
1333
1334 if (src == GL_NONE)
1335 {
1336 return true;
1337 }
1338
Olli Etuaho84c9f592016-03-09 14:37:25 +02001339 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001341 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001342 return false;
1343 }
1344
1345 if (readFBO->id() == 0)
1346 {
1347 if (src != GL_BACK)
1348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(
1350 InvalidOperation()
1351 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001352 return false;
1353 }
1354 }
1355 else
1356 {
1357 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1358
1359 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001362 return false;
1363 }
1364 }
1365
1366 return true;
1367}
1368
Jamie Madill86af3d22015-07-21 15:14:07 -04001369bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001370 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001371 GLint level,
1372 GLenum internalformat,
1373 GLsizei width,
1374 GLsizei height,
1375 GLsizei depth,
1376 GLint border,
1377 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001378 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001379{
Martin Radev1be913c2016-07-11 17:59:16 +03001380 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001381 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001382 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 return false;
1384 }
1385
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001386 if (!ValidTextureTarget(context, target))
1387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001388 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001389 return false;
1390 }
1391
Jamie Madille2e406c2016-06-02 13:04:10 -04001392 // Validate image size
1393 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001396 return false;
1397 }
1398
Geoff Langca271392017-04-05 12:30:00 -04001399 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001400 if (!formatInfo.compressed)
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001403 return false;
1404 }
1405
Jeff Gilbert48590352017-11-07 16:03:38 -08001406 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001407 if (blockSizeOrErr.isError())
1408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001409 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001410 return false;
1411 }
1412 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001414 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001415 return false;
1416 }
1417
1418 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001419 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001422 return false;
1423 }
1424
1425 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001426 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001427 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1428 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001429 {
1430 return false;
1431 }
1432
1433 return true;
1434}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001435
Corentin Wallezb2931602017-04-11 15:58:57 -04001436bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001437 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001438 GLint level,
1439 GLenum internalformat,
1440 GLsizei width,
1441 GLsizei height,
1442 GLsizei depth,
1443 GLint border,
1444 GLsizei imageSize,
1445 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001446 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001447{
1448 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1449 {
1450 return false;
1451 }
1452
1453 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1454 depth, border, imageSize, data);
1455}
1456
Austin Kinrossbc781f32015-10-26 09:27:38 -07001457bool ValidateBindVertexArray(Context *context, GLuint array)
1458{
Martin Radev1be913c2016-07-11 17:59:16 +03001459 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001460 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001461 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001462 return false;
1463 }
1464
1465 return ValidateBindVertexArrayBase(context, array);
1466}
1467
Jamie Madilld7576732017-08-26 18:49:50 -04001468bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001469{
Martin Radev1be913c2016-07-11 17:59:16 +03001470 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001471 {
Jamie Madilld7576732017-08-26 18:49:50 -04001472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001473 return false;
1474 }
1475
1476 return true;
1477}
Geoff Langc5629752015-12-07 16:29:04 -05001478
Jiajia Qin6eafb042016-12-27 17:04:07 +08001479static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001480 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001481 GLuint index,
1482 GLuint buffer,
1483 GLintptr offset,
1484 GLsizeiptr size)
1485{
1486 if (context->getClientMajorVersion() < 3)
1487 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001489 return false;
1490 }
1491
1492 if (buffer != 0 && offset < 0)
1493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001494 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001495 return false;
1496 }
1497
1498 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1499 !context->isBufferGenerated(buffer))
1500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001501 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001502 return false;
1503 }
1504
1505 const Caps &caps = context->getCaps();
1506 switch (target)
1507 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001508 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001509 {
1510 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001512 context->handleError(InvalidValue() << "index is greater than or equal to the "
1513 "number of TRANSFORM_FEEDBACK_BUFFER "
1514 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001515 return false;
1516 }
1517 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001520 return false;
1521 }
1522
1523 TransformFeedback *curTransformFeedback =
1524 context->getGLState().getCurrentTransformFeedback();
1525 if (curTransformFeedback && curTransformFeedback->isActive())
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidOperation()
1528 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1529 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001530 return false;
1531 }
1532 break;
1533 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001534 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001535 {
1536 if (index >= caps.maxUniformBufferBindings)
1537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidValue() << "index is greater than or equal to the "
1539 "number of UNIFORM_BUFFER indexed "
1540 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001541 return false;
1542 }
1543
1544 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1545 {
1546 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 InvalidValue()
1548 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001549 return false;
1550 }
1551 break;
1552 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001553 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001554 {
1555 if (context->getClientVersion() < ES_3_1)
1556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001557 context->handleError(InvalidEnum()
1558 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001559 return false;
1560 }
1561 if (index >= caps.maxAtomicCounterBufferBindings)
1562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidValue() << "index is greater than or equal to the "
1564 "number of ATOMIC_COUNTER_BUFFER "
1565 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001566 return false;
1567 }
1568 if (buffer != 0 && (offset % 4) != 0)
1569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001571 return false;
1572 }
1573 break;
1574 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001575 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001576 {
1577 if (context->getClientVersion() < ES_3_1)
1578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001579 context->handleError(InvalidEnum()
1580 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001581 return false;
1582 }
1583 if (index >= caps.maxShaderStorageBufferBindings)
1584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001585 context->handleError(InvalidValue() << "index is greater than or equal to the "
1586 "number of SHADER_STORAGE_BUFFER "
1587 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001588 return false;
1589 }
1590 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001592 context->handleError(InvalidValue() << "offset must be multiple of value of "
1593 "SHADER_STORAGE_BUFFER_OFFSET_"
1594 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001595 return false;
1596 }
1597 break;
1598 }
1599 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001600 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001601 return false;
1602 }
1603
1604 return true;
1605}
1606
Corentin Wallez336129f2017-10-17 15:55:40 -04001607bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001608{
1609 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1610}
1611
1612bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001613 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001614 GLuint index,
1615 GLuint buffer,
1616 GLintptr offset,
1617 GLsizeiptr size)
1618{
1619 if (buffer != 0 && size <= 0)
1620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001621 context->handleError(InvalidValue()
1622 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001623 return false;
1624 }
1625 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1626}
1627
Geoff Langc5629752015-12-07 16:29:04 -05001628bool ValidateProgramBinary(Context *context,
1629 GLuint program,
1630 GLenum binaryFormat,
1631 const void *binary,
1632 GLint length)
1633{
Martin Radev1be913c2016-07-11 17:59:16 +03001634 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001635 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001637 return false;
1638 }
1639
1640 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1641}
1642
1643bool ValidateGetProgramBinary(Context *context,
1644 GLuint program,
1645 GLsizei bufSize,
1646 GLsizei *length,
1647 GLenum *binaryFormat,
1648 void *binary)
1649{
Martin Radev1be913c2016-07-11 17:59:16 +03001650 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001651 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001653 return false;
1654 }
1655
1656 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1657}
1658
Olli Etuahof0fee072016-03-30 15:11:58 +03001659bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001660{
Martin Radev1be913c2016-07-11 17:59:16 +03001661 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001662 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001664 return false;
1665 }
1666
1667 if (GetValidProgram(context, program) == nullptr)
1668 {
1669 return false;
1670 }
1671
1672 switch (pname)
1673 {
1674 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001675 if (value != GL_FALSE && value != GL_TRUE)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidValue()
1678 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001679 return false;
1680 }
Geoff Langc5629752015-12-07 16:29:04 -05001681 break;
1682
Yunchao He61afff12017-03-14 15:34:03 +08001683 case GL_PROGRAM_SEPARABLE:
1684 if (context->getClientVersion() < ES_3_1)
1685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001686 context->handleError(InvalidEnum()
1687 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001688 return false;
1689 }
1690
1691 if (value != GL_FALSE && value != GL_TRUE)
1692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001693 context->handleError(InvalidValue()
1694 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001695 return false;
1696 }
1697 break;
1698
Geoff Langc5629752015-12-07 16:29:04 -05001699 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001700 context->handleError(InvalidEnum()
1701 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001702 return false;
1703 }
1704
1705 return true;
1706}
Jamie Madillc29968b2016-01-20 11:17:23 -05001707
1708bool ValidateBlitFramebuffer(Context *context,
1709 GLint srcX0,
1710 GLint srcY0,
1711 GLint srcX1,
1712 GLint srcY1,
1713 GLint dstX0,
1714 GLint dstY0,
1715 GLint dstX1,
1716 GLint dstY1,
1717 GLbitfield mask,
1718 GLenum filter)
1719{
Martin Radev1be913c2016-07-11 17:59:16 +03001720 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001721 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 return false;
1724 }
1725
1726 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1727 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728}
Jamie Madillc29968b2016-01-20 11:17:23 -05001729
1730bool ValidateClearBufferiv(ValidationContext *context,
1731 GLenum buffer,
1732 GLint drawbuffer,
1733 const GLint *value)
1734{
1735 switch (buffer)
1736 {
1737 case GL_COLOR:
1738 if (drawbuffer < 0 ||
1739 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001741 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 return false;
1743 }
Geoff Lang76e65652017-03-27 14:58:02 -04001744 if (context->getExtensions().webglCompatibility)
1745 {
1746 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001747 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001748 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1749 {
1750 return false;
1751 }
1752 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001753 break;
1754
1755 case GL_STENCIL:
1756 if (drawbuffer != 0)
1757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001759 return false;
1760 }
1761 break;
1762
1763 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001764 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001765 return false;
1766 }
1767
1768 return ValidateClearBuffer(context);
1769}
1770
1771bool ValidateClearBufferuiv(ValidationContext *context,
1772 GLenum buffer,
1773 GLint drawbuffer,
1774 const GLuint *value)
1775{
1776 switch (buffer)
1777 {
1778 case GL_COLOR:
1779 if (drawbuffer < 0 ||
1780 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001782 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001783 return false;
1784 }
Geoff Lang76e65652017-03-27 14:58:02 -04001785 if (context->getExtensions().webglCompatibility)
1786 {
1787 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001788 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001789 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1790 {
1791 return false;
1792 }
1793 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001794 break;
1795
1796 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001797 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 return false;
1799 }
1800
1801 return ValidateClearBuffer(context);
1802}
1803
1804bool ValidateClearBufferfv(ValidationContext *context,
1805 GLenum buffer,
1806 GLint drawbuffer,
1807 const GLfloat *value)
1808{
1809 switch (buffer)
1810 {
1811 case GL_COLOR:
1812 if (drawbuffer < 0 ||
1813 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001815 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 return false;
1817 }
Geoff Lang76e65652017-03-27 14:58:02 -04001818 if (context->getExtensions().webglCompatibility)
1819 {
1820 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1821 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001822 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001823 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1824 {
1825 return false;
1826 }
1827 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 break;
1829
1830 case GL_DEPTH:
1831 if (drawbuffer != 0)
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836 break;
1837
1838 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 return false;
1841 }
1842
1843 return ValidateClearBuffer(context);
1844}
1845
1846bool ValidateClearBufferfi(ValidationContext *context,
1847 GLenum buffer,
1848 GLint drawbuffer,
1849 GLfloat depth,
1850 GLint stencil)
1851{
1852 switch (buffer)
1853 {
1854 case GL_DEPTH_STENCIL:
1855 if (drawbuffer != 0)
1856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001857 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860 break;
1861
1862 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001863 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return false;
1865 }
1866
1867 return ValidateClearBuffer(context);
1868}
1869
1870bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1871{
Martin Radev1be913c2016-07-11 17:59:16 +03001872 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001873 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001875 return false;
1876 }
1877
1878 return ValidateDrawBuffersBase(context, n, bufs);
1879}
1880
1881bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001882 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05001883 GLint level,
1884 GLint xoffset,
1885 GLint yoffset,
1886 GLint zoffset,
1887 GLint x,
1888 GLint y,
1889 GLsizei width,
1890 GLsizei height)
1891{
Martin Radev1be913c2016-07-11 17:59:16 +03001892 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001893 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001895 return false;
1896 }
1897
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001898 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1899 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001900}
1901
Jamie Madill73a84962016-02-12 09:27:23 -05001902bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001903 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001904 GLint level,
1905 GLint internalformat,
1906 GLsizei width,
1907 GLsizei height,
1908 GLsizei depth,
1909 GLint border,
1910 GLenum format,
1911 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001912 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001913{
Martin Radev1be913c2016-07-11 17:59:16 +03001914 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001915 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001917 return false;
1918 }
1919
1920 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001921 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001922 pixels);
1923}
1924
Geoff Langc52f6f12016-10-14 10:18:00 -04001925bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001926 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001927 GLint level,
1928 GLint internalformat,
1929 GLsizei width,
1930 GLsizei height,
1931 GLsizei depth,
1932 GLint border,
1933 GLenum format,
1934 GLenum type,
1935 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001936 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001937{
1938 if (context->getClientMajorVersion() < 3)
1939 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001941 return false;
1942 }
1943
1944 if (!ValidateRobustEntryPoint(context, bufSize))
1945 {
1946 return false;
1947 }
1948
1949 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1950 0, 0, width, height, depth, border, format, type,
1951 bufSize, pixels);
1952}
1953
Jamie Madill73a84962016-02-12 09:27:23 -05001954bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001955 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05001956 GLint level,
1957 GLint xoffset,
1958 GLint yoffset,
1959 GLint zoffset,
1960 GLsizei width,
1961 GLsizei height,
1962 GLsizei depth,
1963 GLenum format,
1964 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001965 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001966{
Martin Radev1be913c2016-07-11 17:59:16 +03001967 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001968 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001969 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001970 return false;
1971 }
1972
1973 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1974 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001975 -1, pixels);
1976}
1977
1978bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001979 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04001980 GLint level,
1981 GLint xoffset,
1982 GLint yoffset,
1983 GLint zoffset,
1984 GLsizei width,
1985 GLsizei height,
1986 GLsizei depth,
1987 GLenum format,
1988 GLenum type,
1989 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001990 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001991{
1992 if (context->getClientMajorVersion() < 3)
1993 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001995 return false;
1996 }
1997
1998 if (!ValidateRobustEntryPoint(context, bufSize))
1999 {
2000 return false;
2001 }
2002
2003 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2004 yoffset, zoffset, width, height, depth, 0, format, type,
2005 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002006}
2007
2008bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002009 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002010 GLint level,
2011 GLint xoffset,
2012 GLint yoffset,
2013 GLint zoffset,
2014 GLsizei width,
2015 GLsizei height,
2016 GLsizei depth,
2017 GLenum format,
2018 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002019 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002020{
Martin Radev1be913c2016-07-11 17:59:16 +03002021 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002022 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002024 return false;
2025 }
2026
Geoff Langca271392017-04-05 12:30:00 -04002027 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002028 if (!formatInfo.compressed)
2029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002030 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002031 return false;
2032 }
2033
Jeff Gilbert48590352017-11-07 16:03:38 -08002034 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002035 if (blockSizeOrErr.isError())
2036 {
2037 context->handleError(blockSizeOrErr.getError());
2038 return false;
2039 }
2040 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002042 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002043 return false;
2044 }
2045
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002046 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2047 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2048 -1, data))
2049 {
2050 return false;
2051 }
2052
Jamie Madill73a84962016-02-12 09:27:23 -05002053 if (!data)
2054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002055 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002056 return false;
2057 }
2058
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002059 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002060}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002061
Corentin Wallezb2931602017-04-11 15:58:57 -04002062bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002063 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002064 GLint level,
2065 GLint xoffset,
2066 GLint yoffset,
2067 GLint zoffset,
2068 GLsizei width,
2069 GLsizei height,
2070 GLsizei depth,
2071 GLenum format,
2072 GLsizei imageSize,
2073 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002074 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002075{
2076 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2077 {
2078 return false;
2079 }
2080
2081 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2082 height, depth, format, imageSize, data);
2083}
Jamie Madill73a84962016-02-12 09:27:23 -05002084
Olli Etuaho41997e72016-03-10 13:38:39 +02002085bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2086{
2087 return ValidateGenOrDeleteES3(context, n);
2088}
2089
2090bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2091{
2092 return ValidateGenOrDeleteES3(context, n);
2093}
2094
2095bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2096{
2097 return ValidateGenOrDeleteCountES3(context, count);
2098}
2099
2100bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2101{
2102 return ValidateGenOrDeleteCountES3(context, count);
2103}
2104
2105bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2106{
2107 return ValidateGenOrDeleteES3(context, n);
2108}
2109
2110bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2111{
2112 if (!ValidateGenOrDeleteES3(context, n))
2113 {
2114 return false;
2115 }
2116 for (GLint i = 0; i < n; ++i)
2117 {
2118 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2119 if (transformFeedback != nullptr && transformFeedback->isActive())
2120 {
2121 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002122 context->handleError(InvalidOperation()
2123 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002124 return false;
2125 }
2126 }
2127 return true;
2128}
2129
2130bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2131{
2132 return ValidateGenOrDeleteES3(context, n);
2133}
2134
2135bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2136{
2137 return ValidateGenOrDeleteES3(context, n);
2138}
2139
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002140bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2141{
Martin Radev1be913c2016-07-11 17:59:16 +03002142 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002143 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002145 return false;
2146 }
2147 switch (primitiveMode)
2148 {
2149 case GL_TRIANGLES:
2150 case GL_LINES:
2151 case GL_POINTS:
2152 break;
2153
2154 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002156 return false;
2157 }
2158
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002159 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002160 ASSERT(transformFeedback != nullptr);
2161
2162 if (transformFeedback->isActive())
2163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002164 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002165 return false;
2166 }
Geoff Lang79f71042017-08-14 16:43:43 -04002167
2168 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2169 {
2170 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2171 if (buffer.get() && buffer->isMapped())
2172 {
2173 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2174 return false;
2175 }
2176 }
2177
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002178 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002179
2180 if (!program)
2181 {
2182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2183 return false;
2184 }
2185
2186 if (program->getTransformFeedbackVaryingCount() == 0)
2187 {
2188 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2189 return false;
2190 }
2191
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002192 return true;
2193}
2194
Corentin Wallez336129f2017-10-17 15:55:40 -04002195bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002196{
Geoff Lang496c02d2016-10-20 11:38:11 -07002197 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2198}
2199
2200bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002201 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002202 GLenum pname,
2203 GLsizei bufSize,
2204 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002205 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002206{
2207 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002208 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002209 return false;
2210 }
2211
Geoff Lang496c02d2016-10-20 11:38:11 -07002212 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2213 {
2214 return false;
2215 }
2216
2217 if (!ValidateRobustBufferSize(context, bufSize, *length))
2218 {
2219 return false;
2220 }
2221
2222 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002223}
2224
Corentin Wallez336129f2017-10-17 15:55:40 -04002225bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002226{
Martin Radev1be913c2016-07-11 17:59:16 +03002227 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002228 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002230 return false;
2231 }
2232
2233 return ValidateUnmapBufferBase(context, target);
2234}
2235
2236bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002237 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002238 GLintptr offset,
2239 GLsizeiptr length,
2240 GLbitfield access)
2241{
Martin Radev1be913c2016-07-11 17:59:16 +03002242 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002243 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002245 return false;
2246 }
2247
2248 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2249}
2250
2251bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002252 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002253 GLintptr offset,
2254 GLsizeiptr length)
2255{
Martin Radev1be913c2016-07-11 17:59:16 +03002256 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002257 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002259 return false;
2260 }
2261
2262 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2263}
2264
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002265bool ValidateIndexedStateQuery(ValidationContext *context,
2266 GLenum pname,
2267 GLuint index,
2268 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002269{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002270 if (length)
2271 {
2272 *length = 0;
2273 }
2274
Martin Radev66fb8202016-07-28 11:45:20 +03002275 GLenum nativeType;
2276 unsigned int numParams;
2277 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002279 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002280 return false;
2281 }
2282
2283 const Caps &caps = context->getCaps();
2284 switch (pname)
2285 {
2286 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2287 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2288 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2289 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002291 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002292 return false;
2293 }
2294 break;
2295
2296 case GL_UNIFORM_BUFFER_START:
2297 case GL_UNIFORM_BUFFER_SIZE:
2298 case GL_UNIFORM_BUFFER_BINDING:
2299 if (index >= caps.maxUniformBufferBindings)
2300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002301 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002302 return false;
2303 }
2304 break;
Shao80957d92017-02-20 21:25:59 +08002305
Martin Radev66fb8202016-07-28 11:45:20 +03002306 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2307 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2308 if (index >= 3u)
2309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002310 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002311 return false;
2312 }
2313 break;
Shao80957d92017-02-20 21:25:59 +08002314
Jiajia Qin6eafb042016-12-27 17:04:07 +08002315 case GL_ATOMIC_COUNTER_BUFFER_START:
2316 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2317 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2318 if (context->getClientVersion() < ES_3_1)
2319 {
2320 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002321 InvalidEnum()
2322 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002323 return false;
2324 }
2325 if (index >= caps.maxAtomicCounterBufferBindings)
2326 {
2327 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002328 InvalidValue()
2329 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002330 return false;
2331 }
2332 break;
Shao80957d92017-02-20 21:25:59 +08002333
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002334 case GL_SHADER_STORAGE_BUFFER_START:
2335 case GL_SHADER_STORAGE_BUFFER_SIZE:
2336 case GL_SHADER_STORAGE_BUFFER_BINDING:
2337 if (context->getClientVersion() < ES_3_1)
2338 {
2339 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002340 InvalidEnum()
2341 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002342 return false;
2343 }
2344 if (index >= caps.maxShaderStorageBufferBindings)
2345 {
2346 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002347 InvalidValue()
2348 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002349 return false;
2350 }
2351 break;
2352
Shao80957d92017-02-20 21:25:59 +08002353 case GL_VERTEX_BINDING_BUFFER:
2354 case GL_VERTEX_BINDING_DIVISOR:
2355 case GL_VERTEX_BINDING_OFFSET:
2356 case GL_VERTEX_BINDING_STRIDE:
2357 if (context->getClientVersion() < ES_3_1)
2358 {
2359 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002360 InvalidEnum()
2361 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002362 return false;
2363 }
2364 if (index >= caps.maxVertexAttribBindings)
2365 {
2366 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002367 InvalidValue()
2368 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002369 return false;
2370 }
2371 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002372 case GL_SAMPLE_MASK_VALUE:
2373 if (context->getClientVersion() < ES_3_1)
2374 {
2375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2376 return false;
2377 }
2378 if (index >= caps.maxSampleMaskWords)
2379 {
2380 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2381 return false;
2382 }
2383 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002384 case GL_IMAGE_BINDING_NAME:
2385 case GL_IMAGE_BINDING_LEVEL:
2386 case GL_IMAGE_BINDING_LAYERED:
2387 case GL_IMAGE_BINDING_LAYER:
2388 case GL_IMAGE_BINDING_ACCESS:
2389 case GL_IMAGE_BINDING_FORMAT:
2390 if (context->getClientVersion() < ES_3_1)
2391 {
2392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2393 return false;
2394 }
2395 if (index >= caps.maxImageUnits)
2396 {
2397 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2398 return false;
2399 }
2400 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002401 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002402 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002403 return false;
2404 }
2405
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002406 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002407 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002408 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002409 }
2410
2411 return true;
2412}
2413
2414bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2415{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002416 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002417 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002419 return false;
2420 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002421 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002422}
2423
Geoff Langcf255ea2016-10-20 11:39:09 -07002424bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2425 GLenum target,
2426 GLuint index,
2427 GLsizei bufSize,
2428 GLsizei *length,
2429 GLint *data)
2430{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002431 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002432 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002434 return false;
2435 }
2436
2437 if (!ValidateRobustEntryPoint(context, bufSize))
2438 {
2439 return false;
2440 }
2441
2442 if (!ValidateIndexedStateQuery(context, target, index, length))
2443 {
2444 return false;
2445 }
2446
2447 if (!ValidateRobustBufferSize(context, bufSize, *length))
2448 {
2449 return false;
2450 }
2451
2452 return true;
2453}
2454
Martin Radev66fb8202016-07-28 11:45:20 +03002455bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2456{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002457 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002460 return false;
2461 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002462 return ValidateIndexedStateQuery(context, target, index, nullptr);
2463}
2464
2465bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2466 GLenum target,
2467 GLuint index,
2468 GLsizei bufSize,
2469 GLsizei *length,
2470 GLint64 *data)
2471{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002472 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002473 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002475 return false;
2476 }
2477
2478 if (!ValidateRobustEntryPoint(context, bufSize))
2479 {
2480 return false;
2481 }
2482
2483 if (!ValidateIndexedStateQuery(context, target, index, length))
2484 {
2485 return false;
2486 }
2487
2488 if (!ValidateRobustBufferSize(context, bufSize, *length))
2489 {
2490 return false;
2491 }
2492
2493 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002494}
2495
Jamie Madillb0817d12016-11-01 15:48:31 -04002496bool ValidateCopyBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002497 BufferBinding readTarget,
2498 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002499 GLintptr readOffset,
2500 GLintptr writeOffset,
2501 GLsizeiptr size)
2502{
2503 if (context->getClientMajorVersion() < 3)
2504 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002506 return false;
2507 }
2508
Corentin Walleze4477002017-12-01 14:39:58 -05002509 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002512 return false;
2513 }
2514
2515 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2516 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2517
2518 if (!readBuffer || !writeBuffer)
2519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002520 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002521 return false;
2522 }
2523
2524 // Verify that readBuffer and writeBuffer are not currently mapped
2525 if (readBuffer->isMapped() || writeBuffer->isMapped())
2526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002527 context->handleError(InvalidOperation()
2528 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002529 return false;
2530 }
2531
Jamie Madilld2f0c742016-11-02 10:34:41 -04002532 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2533 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2534 CheckedNumeric<GLintptr> checkedSize(size);
2535
2536 auto checkedReadSum = checkedReadOffset + checkedSize;
2537 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2538
2539 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2540 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2541 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002543 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002544 return false;
2545 }
2546
Jamie Madilld2f0c742016-11-02 10:34:41 -04002547 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002549 context->handleError(InvalidValue()
2550 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002551 return false;
2552 }
2553
Jamie Madilld2f0c742016-11-02 10:34:41 -04002554 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2555 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002557 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002558 return false;
2559 }
2560
2561 if (readBuffer == writeBuffer)
2562 {
2563 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2564 if (!checkedOffsetDiff.IsValid())
2565 {
2566 // This shold not be possible.
2567 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 context->handleError(InvalidValue()
2569 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002570 return false;
2571 }
2572
2573 if (checkedOffsetDiff.ValueOrDie() < size)
2574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002575 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002576 return false;
2577 }
2578 }
2579
Jamie Madillb0817d12016-11-01 15:48:31 -04002580 return true;
2581}
2582
Geoff Langc339c4e2016-11-29 10:37:36 -05002583bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2584{
2585 if (context->getClientMajorVersion() < 3)
2586 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002588 return false;
2589 }
2590
2591 switch (name)
2592 {
2593 case GL_EXTENSIONS:
2594 if (index >= context->getExtensionStringCount())
2595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002596 context->handleError(InvalidValue()
2597 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002598 return false;
2599 }
2600 break;
2601
2602 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2603 if (!context->getExtensions().requestExtension)
2604 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002605 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002606 return false;
2607 }
2608 if (index >= context->getRequestableExtensionStringCount())
2609 {
2610 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002611 InvalidValue()
2612 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002613 return false;
2614 }
2615 break;
2616
2617 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002618 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002619 return false;
2620 }
2621
2622 return true;
2623}
2624
Jamie Madille8fb6402017-02-14 17:56:40 -05002625bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2626 GLenum target,
2627 GLsizei samples,
2628 GLenum internalformat,
2629 GLsizei width,
2630 GLsizei height)
2631{
2632 if (context->getClientMajorVersion() < 3)
2633 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002635 return false;
2636 }
2637
2638 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2639 height))
2640 {
2641 return false;
2642 }
2643
2644 // 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 +08002645 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2646 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002647 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002648 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002649 {
Yunchao Hec0810202018-01-22 09:48:48 +08002650 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2651 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2652 {
2653 context->handleError(InvalidOperation());
2654 return false;
2655 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002656 }
2657
2658 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2659 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2660 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2661 {
2662 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002663 InvalidOperation()
2664 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002665 return false;
2666 }
2667
2668 return true;
2669}
2670
Geoff Langaa086d62017-03-23 16:47:21 -04002671bool ValidateVertexAttribIPointer(ValidationContext *context,
2672 GLuint index,
2673 GLint size,
2674 GLenum type,
2675 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002676 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002677{
2678 if (context->getClientMajorVersion() < 3)
2679 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002681 return false;
2682 }
2683
Shao80957d92017-02-20 21:25:59 +08002684 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002685 {
Geoff Langaa086d62017-03-23 16:47:21 -04002686 return false;
2687 }
2688
Geoff Langaa086d62017-03-23 16:47:21 -04002689 if (stride < 0)
2690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002691 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002692 return false;
2693 }
2694
Shao80957d92017-02-20 21:25:59 +08002695 const Caps &caps = context->getCaps();
2696 if (context->getClientVersion() >= ES_3_1)
2697 {
2698 if (stride > caps.maxVertexAttribStride)
2699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002700 context->handleError(InvalidValue()
2701 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002702 return false;
2703 }
2704
2705 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2706 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2707 // validation should be inherited.
2708 if (index >= caps.maxVertexAttribBindings)
2709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002710 context->handleError(InvalidValue()
2711 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002712 return false;
2713 }
2714 }
2715
Geoff Langaa086d62017-03-23 16:47:21 -04002716 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2717 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2718 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2719 // and the pointer argument is not NULL.
2720 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002721 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002723 context
2724 ->handleError(InvalidOperation()
2725 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002726 return false;
2727 }
2728
Geoff Lang2d62ab72017-03-23 16:54:40 -04002729 if (context->getExtensions().webglCompatibility)
2730 {
2731 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2732 {
2733 return false;
2734 }
2735 }
2736
Geoff Langaa086d62017-03-23 16:47:21 -04002737 return true;
2738}
2739
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002740bool ValidateGetSynciv(Context *context,
2741 GLsync sync,
2742 GLenum pname,
2743 GLsizei bufSize,
2744 GLsizei *length,
2745 GLint *values)
2746{
2747 if (context->getClientMajorVersion() < 3)
2748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002749 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002750 return false;
2751 }
2752
2753 if (bufSize < 0)
2754 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002755 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002756 return false;
2757 }
2758
Jamie Madill70b5bb02017-08-28 13:32:37 -04002759 Sync *syncObject = context->getSync(sync);
2760 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002762 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002763 return false;
2764 }
2765
2766 switch (pname)
2767 {
2768 case GL_OBJECT_TYPE:
2769 case GL_SYNC_CONDITION:
2770 case GL_SYNC_FLAGS:
2771 case GL_SYNC_STATUS:
2772 break;
2773
2774 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002776 return false;
2777 }
2778
2779 return true;
2780}
2781
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002782bool ValidateDrawElementsInstanced(ValidationContext *context,
2783 GLenum mode,
2784 GLsizei count,
2785 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002786 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002787 GLsizei instanceCount)
2788{
2789 if (context->getClientMajorVersion() < 3)
2790 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002792 return false;
2793 }
2794
2795 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2796}
2797
Martin Radev137032d2017-07-13 10:11:12 +03002798bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2799 GLenum target,
2800 GLenum attachment,
2801 GLuint texture,
2802 GLint level,
2803 GLint baseViewIndex,
2804 GLsizei numViews)
2805{
2806
2807 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2808 numViews))
2809 {
2810 return false;
2811 }
2812
Martin Radev137032d2017-07-13 10:11:12 +03002813 if (texture != 0)
2814 {
Martin Radev14b21262017-08-25 13:54:37 +03002815 if (baseViewIndex < 0)
2816 {
2817 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2818 return false;
2819 }
2820
Martin Radev137032d2017-07-13 10:11:12 +03002821 Texture *tex = context->getTexture(texture);
2822 ASSERT(tex);
2823
2824 switch (tex->getTarget())
2825 {
2826 case GL_TEXTURE_2D_ARRAY:
2827 {
2828 const Caps &caps = context->getCaps();
2829 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2830 {
2831 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2832 "greater than "
2833 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2834 return false;
2835 }
2836 }
2837 break;
2838 default:
2839 context->handleError(InvalidOperation()
2840 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2841 return false;
2842 }
2843
2844 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2845 {
2846 return false;
2847 }
2848 }
2849
2850 return true;
2851}
2852
2853bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2854 GLenum target,
2855 GLenum attachment,
2856 GLuint texture,
2857 GLint level,
2858 GLsizei numViews,
2859 const GLint *viewportOffsets)
2860{
2861 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2862 numViews))
2863 {
2864 return false;
2865 }
2866
Martin Radev137032d2017-07-13 10:11:12 +03002867 if (texture != 0)
2868 {
Martin Radev14b21262017-08-25 13:54:37 +03002869 const GLsizei numViewportOffsetValues = numViews * 2;
2870 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2871 {
2872 if (viewportOffsets[i] < 0)
2873 {
2874 context->handleError(InvalidValue()
2875 << "viewportOffsets cannot contain negative values.");
2876 return false;
2877 }
2878 }
2879
Martin Radev137032d2017-07-13 10:11:12 +03002880 Texture *tex = context->getTexture(texture);
2881 ASSERT(tex);
2882
2883 switch (tex->getTarget())
2884 {
2885 case GL_TEXTURE_2D:
2886 break;
2887 default:
2888 context->handleError(InvalidOperation()
2889 << "Texture's target must be GL_TEXTURE_2D.");
2890 return false;
2891 }
2892
2893 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2894 {
2895 return false;
2896 }
2897 }
2898
2899 return true;
2900}
2901
Jamie Madillff325f12017-08-26 15:06:05 -04002902bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2903{
2904 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2905}
2906
2907bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2908{
2909 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2910}
2911
2912bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2913{
2914 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2915}
2916
2917bool ValidateUniform4ui(Context *context,
2918 GLint location,
2919 GLuint v0,
2920 GLuint v1,
2921 GLuint v2,
2922 GLuint v3)
2923{
2924 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2925}
2926
2927bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2928{
2929 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2930}
2931
2932bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2933{
2934 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2935}
2936
2937bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2938{
2939 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2940}
2941
2942bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2943{
2944 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2945}
2946
Jamie Madillf0e04492017-08-26 15:28:42 -04002947bool ValidateIsQuery(Context *context, GLuint id)
2948{
2949 if (context->getClientMajorVersion() < 3)
2950 {
2951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2952 return false;
2953 }
2954
2955 return true;
2956}
2957
Jamie Madillc8c95812017-08-26 18:40:09 -04002958bool ValidateUniformMatrix2x3fv(Context *context,
2959 GLint location,
2960 GLsizei count,
2961 GLboolean transpose,
2962 const GLfloat *value)
2963{
2964 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2965}
2966
2967bool ValidateUniformMatrix3x2fv(Context *context,
2968 GLint location,
2969 GLsizei count,
2970 GLboolean transpose,
2971 const GLfloat *value)
2972{
2973 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2974}
2975
2976bool ValidateUniformMatrix2x4fv(Context *context,
2977 GLint location,
2978 GLsizei count,
2979 GLboolean transpose,
2980 const GLfloat *value)
2981{
2982 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2983}
2984
2985bool ValidateUniformMatrix4x2fv(Context *context,
2986 GLint location,
2987 GLsizei count,
2988 GLboolean transpose,
2989 const GLfloat *value)
2990{
2991 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2992}
2993
2994bool ValidateUniformMatrix3x4fv(Context *context,
2995 GLint location,
2996 GLsizei count,
2997 GLboolean transpose,
2998 const GLfloat *value)
2999{
3000 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3001}
3002
3003bool ValidateUniformMatrix4x3fv(Context *context,
3004 GLint location,
3005 GLsizei count,
3006 GLboolean transpose,
3007 const GLfloat *value)
3008{
3009 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3010}
3011
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003012bool ValidateEndTransformFeedback(Context *context)
3013{
3014 if (context->getClientMajorVersion() < 3)
3015 {
3016 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3017 return false;
3018 }
3019
3020 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3021 ASSERT(transformFeedback != nullptr);
3022
3023 if (!transformFeedback->isActive())
3024 {
3025 context->handleError(InvalidOperation());
3026 return false;
3027 }
3028
3029 return true;
3030}
3031
3032bool ValidateTransformFeedbackVaryings(Context *context,
3033 GLuint program,
3034 GLsizei count,
3035 const GLchar *const *varyings,
3036 GLenum bufferMode)
3037{
3038 if (context->getClientMajorVersion() < 3)
3039 {
3040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3041 return false;
3042 }
3043
3044 if (count < 0)
3045 {
3046 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3047 return false;
3048 }
3049
3050 switch (bufferMode)
3051 {
3052 case GL_INTERLEAVED_ATTRIBS:
3053 break;
3054 case GL_SEPARATE_ATTRIBS:
3055 {
3056 const Caps &caps = context->getCaps();
3057 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3058 {
3059 context->handleError(InvalidValue());
3060 return false;
3061 }
3062 break;
3063 }
3064 default:
3065 context->handleError(InvalidEnum());
3066 return false;
3067 }
3068
3069 Program *programObject = GetValidProgram(context, program);
3070 if (!programObject)
3071 {
3072 return false;
3073 }
3074
3075 return true;
3076}
3077
3078bool ValidateGetTransformFeedbackVarying(Context *context,
3079 GLuint program,
3080 GLuint index,
3081 GLsizei bufSize,
3082 GLsizei *length,
3083 GLsizei *size,
3084 GLenum *type,
3085 GLchar *name)
3086{
3087 if (context->getClientMajorVersion() < 3)
3088 {
3089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3090 return false;
3091 }
3092
3093 if (bufSize < 0)
3094 {
3095 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3096 return false;
3097 }
3098
3099 Program *programObject = GetValidProgram(context, program);
3100 if (!programObject)
3101 {
3102 return false;
3103 }
3104
3105 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3106 {
3107 context->handleError(InvalidValue());
3108 return false;
3109 }
3110
3111 return true;
3112}
3113
3114bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3115{
3116 if (context->getClientMajorVersion() < 3)
3117 {
3118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3119 return false;
3120 }
3121
3122 switch (target)
3123 {
3124 case GL_TRANSFORM_FEEDBACK:
3125 {
3126 // Cannot bind a transform feedback object if the current one is started and not
3127 // paused (3.0.2 pg 85 section 2.14.1)
3128 TransformFeedback *curTransformFeedback =
3129 context->getGLState().getCurrentTransformFeedback();
3130 if (curTransformFeedback && curTransformFeedback->isActive() &&
3131 !curTransformFeedback->isPaused())
3132 {
3133 context->handleError(InvalidOperation());
3134 return false;
3135 }
3136
3137 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3138 // 2.14.1)
3139 if (!context->isTransformFeedbackGenerated(id))
3140 {
3141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3142 return false;
3143 }
3144 }
3145 break;
3146
3147 default:
3148 context->handleError(InvalidEnum());
3149 return false;
3150 }
3151
3152 return true;
3153}
3154
3155bool ValidateIsTransformFeedback(Context *context, GLuint id)
3156{
3157 if (context->getClientMajorVersion() < 3)
3158 {
3159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3160 return false;
3161 }
3162
3163 return true;
3164}
3165
3166bool ValidatePauseTransformFeedback(Context *context)
3167{
3168 if (context->getClientMajorVersion() < 3)
3169 {
3170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3171 return false;
3172 }
3173
3174 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3175 ASSERT(transformFeedback != nullptr);
3176
3177 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3178 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3179 {
3180 context->handleError(InvalidOperation());
3181 return false;
3182 }
3183
3184 return true;
3185}
3186
3187bool ValidateResumeTransformFeedback(Context *context)
3188{
3189 if (context->getClientMajorVersion() < 3)
3190 {
3191 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3192 return false;
3193 }
3194
3195 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3196 ASSERT(transformFeedback != nullptr);
3197
3198 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3199 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3200 {
3201 context->handleError(InvalidOperation());
3202 return false;
3203 }
3204
3205 return true;
3206}
3207
Jamie Madill12e957f2017-08-26 21:42:26 -04003208bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3209{
3210 if (context->getClientMajorVersion() < 3)
3211 {
3212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3213 return false;
3214 }
3215
3216 return ValidateVertexAttribIndex(context, index);
3217}
3218
3219bool ValidateVertexAttribI4ui(Context *context,
3220 GLuint index,
3221 GLuint x,
3222 GLuint y,
3223 GLuint z,
3224 GLuint w)
3225{
3226 if (context->getClientMajorVersion() < 3)
3227 {
3228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3229 return false;
3230 }
3231
3232 return ValidateVertexAttribIndex(context, index);
3233}
3234
3235bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3236{
3237 if (context->getClientMajorVersion() < 3)
3238 {
3239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3240 return false;
3241 }
3242
3243 return ValidateVertexAttribIndex(context, index);
3244}
3245
3246bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3247{
3248 if (context->getClientMajorVersion() < 3)
3249 {
3250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3251 return false;
3252 }
3253
3254 return ValidateVertexAttribIndex(context, index);
3255}
3256
3257bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3258{
3259 if (context->getClientMajorVersion() < 3)
3260 {
3261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3262 return false;
3263 }
3264
3265 Program *programObject = GetValidProgram(context, program);
3266 if (!programObject)
3267 {
3268 return false;
3269 }
3270
3271 if (!programObject->isLinked())
3272 {
3273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3274 return false;
3275 }
3276
3277 return true;
3278}
3279
3280bool ValidateGetUniformIndices(Context *context,
3281 GLuint program,
3282 GLsizei uniformCount,
3283 const GLchar *const *uniformNames,
3284 GLuint *uniformIndices)
3285{
3286 if (context->getClientMajorVersion() < 3)
3287 {
3288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3289 return false;
3290 }
3291
3292 if (uniformCount < 0)
3293 {
3294 context->handleError(InvalidValue());
3295 return false;
3296 }
3297
3298 Program *programObject = GetValidProgram(context, program);
3299 if (!programObject)
3300 {
3301 return false;
3302 }
3303
3304 return true;
3305}
3306
3307bool ValidateGetActiveUniformsiv(Context *context,
3308 GLuint program,
3309 GLsizei uniformCount,
3310 const GLuint *uniformIndices,
3311 GLenum pname,
3312 GLint *params)
3313{
3314 if (context->getClientMajorVersion() < 3)
3315 {
3316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3317 return false;
3318 }
3319
3320 if (uniformCount < 0)
3321 {
3322 context->handleError(InvalidValue());
3323 return false;
3324 }
3325
3326 Program *programObject = GetValidProgram(context, program);
3327 if (!programObject)
3328 {
3329 return false;
3330 }
3331
3332 switch (pname)
3333 {
3334 case GL_UNIFORM_TYPE:
3335 case GL_UNIFORM_SIZE:
3336 case GL_UNIFORM_NAME_LENGTH:
3337 case GL_UNIFORM_BLOCK_INDEX:
3338 case GL_UNIFORM_OFFSET:
3339 case GL_UNIFORM_ARRAY_STRIDE:
3340 case GL_UNIFORM_MATRIX_STRIDE:
3341 case GL_UNIFORM_IS_ROW_MAJOR:
3342 break;
3343
3344 default:
3345 context->handleError(InvalidEnum());
3346 return false;
3347 }
3348
3349 if (uniformCount > programObject->getActiveUniformCount())
3350 {
3351 context->handleError(InvalidValue());
3352 return false;
3353 }
3354
3355 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3356 {
3357 const GLuint index = uniformIndices[uniformId];
3358
3359 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3360 {
3361 context->handleError(InvalidValue());
3362 return false;
3363 }
3364 }
3365
3366 return true;
3367}
3368
3369bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3370{
3371 if (context->getClientMajorVersion() < 3)
3372 {
3373 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3374 return false;
3375 }
3376
3377 Program *programObject = GetValidProgram(context, program);
3378 if (!programObject)
3379 {
3380 return false;
3381 }
3382
3383 return true;
3384}
3385
3386bool ValidateGetActiveUniformBlockiv(Context *context,
3387 GLuint program,
3388 GLuint uniformBlockIndex,
3389 GLenum pname,
3390 GLint *params)
3391{
3392 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3393}
3394
3395bool ValidateGetActiveUniformBlockName(Context *context,
3396 GLuint program,
3397 GLuint uniformBlockIndex,
3398 GLsizei bufSize,
3399 GLsizei *length,
3400 GLchar *uniformBlockName)
3401{
3402 if (context->getClientMajorVersion() < 3)
3403 {
3404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3405 return false;
3406 }
3407
3408 Program *programObject = GetValidProgram(context, program);
3409 if (!programObject)
3410 {
3411 return false;
3412 }
3413
3414 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3415 {
3416 context->handleError(InvalidValue());
3417 return false;
3418 }
3419
3420 return true;
3421}
3422
3423bool ValidateUniformBlockBinding(Context *context,
3424 GLuint program,
3425 GLuint uniformBlockIndex,
3426 GLuint uniformBlockBinding)
3427{
3428 if (context->getClientMajorVersion() < 3)
3429 {
3430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3431 return false;
3432 }
3433
3434 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3435 {
3436 context->handleError(InvalidValue());
3437 return false;
3438 }
3439
3440 Program *programObject = GetValidProgram(context, program);
3441 if (!programObject)
3442 {
3443 return false;
3444 }
3445
3446 // if never linked, there won't be any uniform blocks
3447 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3448 {
3449 context->handleError(InvalidValue());
3450 return false;
3451 }
3452
3453 return true;
3454}
3455
3456bool ValidateDrawArraysInstanced(Context *context,
3457 GLenum mode,
3458 GLint first,
3459 GLsizei count,
3460 GLsizei primcount)
3461{
3462 if (context->getClientMajorVersion() < 3)
3463 {
3464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3465 return false;
3466 }
3467
3468 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3469}
3470
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003471bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3472{
3473 if (context->getClientMajorVersion() < 3)
3474 {
3475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3476 return false;
3477 }
3478
3479 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3480 {
3481 context->handleError(InvalidEnum());
3482 return false;
3483 }
3484
3485 if (flags != 0)
3486 {
3487 context->handleError(InvalidValue());
3488 return false;
3489 }
3490
3491 return true;
3492}
3493
3494bool ValidateIsSync(Context *context, GLsync sync)
3495{
3496 if (context->getClientMajorVersion() < 3)
3497 {
3498 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3499 return false;
3500 }
3501
3502 return true;
3503}
3504
3505bool ValidateDeleteSync(Context *context, GLsync sync)
3506{
3507 if (context->getClientMajorVersion() < 3)
3508 {
3509 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3510 return false;
3511 }
3512
Jamie Madill70b5bb02017-08-28 13:32:37 -04003513 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003514 {
3515 context->handleError(InvalidValue());
3516 return false;
3517 }
3518
3519 return true;
3520}
3521
3522bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3523{
3524 if (context->getClientMajorVersion() < 3)
3525 {
3526 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3527 return false;
3528 }
3529
3530 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3531 {
3532 context->handleError(InvalidValue());
3533 return false;
3534 }
3535
Jamie Madill70b5bb02017-08-28 13:32:37 -04003536 Sync *clientWaitSync = context->getSync(sync);
3537 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003538 {
3539 context->handleError(InvalidValue());
3540 return false;
3541 }
3542
3543 return true;
3544}
3545
3546bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3547{
3548 if (context->getClientMajorVersion() < 3)
3549 {
3550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3551 return false;
3552 }
3553
3554 if (flags != 0)
3555 {
3556 context->handleError(InvalidValue());
3557 return false;
3558 }
3559
3560 if (timeout != GL_TIMEOUT_IGNORED)
3561 {
3562 context->handleError(InvalidValue());
3563 return false;
3564 }
3565
Jamie Madill70b5bb02017-08-28 13:32:37 -04003566 Sync *waitSync = context->getSync(sync);
3567 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003568 {
3569 context->handleError(InvalidValue());
3570 return false;
3571 }
3572
3573 return true;
3574}
3575
3576bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3577{
3578 if (context->getClientMajorVersion() < 3)
3579 {
3580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3581 return false;
3582 }
3583
3584 GLenum nativeType = GL_NONE;
3585 unsigned int numParams = 0;
3586 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3587 {
3588 return false;
3589 }
3590
3591 return true;
3592}
3593
Jamie Madill3ef140a2017-08-26 23:11:21 -04003594bool ValidateIsSampler(Context *context, GLuint sampler)
3595{
3596 if (context->getClientMajorVersion() < 3)
3597 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003599 return false;
3600 }
3601
3602 return true;
3603}
3604
3605bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3606{
3607 if (context->getClientMajorVersion() < 3)
3608 {
3609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3610 return false;
3611 }
3612
3613 if (sampler != 0 && !context->isSampler(sampler))
3614 {
3615 context->handleError(InvalidOperation());
3616 return false;
3617 }
3618
3619 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3620 {
3621 context->handleError(InvalidValue());
3622 return false;
3623 }
3624
3625 return true;
3626}
3627
3628bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3629{
3630 if (context->getClientMajorVersion() < 3)
3631 {
3632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3633 return false;
3634 }
3635
3636 return ValidateVertexAttribIndex(context, index);
3637}
3638
3639bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003640 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003641 GLsizei levels,
3642 GLenum internalformat,
3643 GLsizei width,
3644 GLsizei height)
3645{
3646 if (context->getClientMajorVersion() < 3)
3647 {
3648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3649 return false;
3650 }
3651
3652 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3653 1))
3654 {
3655 return false;
3656 }
3657
3658 return true;
3659}
3660
3661bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003662 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003663 GLsizei levels,
3664 GLenum internalformat,
3665 GLsizei width,
3666 GLsizei height,
3667 GLsizei depth)
3668{
3669 if (context->getClientMajorVersion() < 3)
3670 {
3671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3672 return false;
3673 }
3674
3675 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3676 depth))
3677 {
3678 return false;
3679 }
3680
3681 return true;
3682}
3683
Jamie Madill9696d072017-08-26 23:19:57 -04003684bool ValidateGetBufferParameteri64v(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003685 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003686 GLenum pname,
3687 GLint64 *params)
3688{
3689 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3690}
3691
3692bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3693{
3694 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3695}
3696
3697bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3698{
3699 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3700}
3701
3702bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3703{
3704 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3705}
3706
3707bool ValidateSamplerParameterfv(Context *context,
3708 GLuint sampler,
3709 GLenum pname,
3710 const GLfloat *params)
3711{
3712 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3713}
3714
3715bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3716{
3717 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3718}
3719
3720bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3721{
3722 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3723}
3724
3725bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3726{
3727 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3728}
3729
3730bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3731{
3732 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3733}
3734
3735bool ValidateGetInternalformativ(Context *context,
3736 GLenum target,
3737 GLenum internalformat,
3738 GLenum pname,
3739 GLsizei bufSize,
3740 GLint *params)
3741{
3742 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3743 nullptr);
3744}
3745
Jamie Madillc29968b2016-01-20 11:17:23 -05003746} // namespace gl