blob: a08ae78274c6cb6e0cfd0e0e900ff623061c92ac [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{
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 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,
Geoff Langca271392017-04-05 12:30:00 -0400140 GLenum 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.
174 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
175 {
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,
201 GLenum target,
202 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{
218 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700219 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500221 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 }
224
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 // Verify zero border
226 if (border != 0)
227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500228 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 }
231
Jamie Madill6f38f822014-06-06 17:12:20 -0400232 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
233 std::numeric_limits<GLsizei>::max() - xoffset < width ||
234 std::numeric_limits<GLsizei>::max() - yoffset < height ||
235 std::numeric_limits<GLsizei>::max() - zoffset < depth)
236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500237 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400238 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400239 }
240
Geoff Langaae65a42014-05-26 12:43:44 -0400241 const gl::Caps &caps = context->getCaps();
242
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 switch (target)
244 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800245 case GL_TEXTURE_2D:
246 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
247 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800250 return false;
251 }
252 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400254 case GL_TEXTURE_RECTANGLE_ANGLE:
255 ASSERT(level == 0);
256 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
257 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
258 {
259 context->handleError(InvalidValue());
260 return false;
261 }
262 if (isCompressed)
263 {
264 context->handleError(InvalidEnum()
265 << "Rectangle texture cannot have a compressed format.");
266 return false;
267 }
268 break;
269
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
271 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
272 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
276 if (!isSubImage && width != height)
277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500278 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 return false;
280 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500284 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800285 return false;
286 }
287 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400288
He Yunchaoced53ae2016-11-29 15:00:51 +0800289 case GL_TEXTURE_3D:
290 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
291 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
292 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500294 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800295 return false;
296 }
297 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298
He Yunchaoced53ae2016-11-29 15:00:51 +0800299 case GL_TEXTURE_2D_ARRAY:
300 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
301 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
302 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500304 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800305 return false;
306 }
307 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400308
He Yunchaoced53ae2016-11-29 15:00:51 +0800309 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500310 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
He Yunchaoced53ae2016-11-29 15:00:51 +0800314 gl::Texture *texture =
315 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 if (!texture)
317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500318 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 }
321
Geoff Lang69cce582015-09-17 13:20:36 -0400322 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500324 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 }
327
328 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400329 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400330 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500331 if (isSubImage && actualInternalFormat == GL_NONE)
332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500333 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500334 return false;
335 }
336
Geoff Langc4e93662017-05-01 10:45:59 -0400337 const gl::InternalFormat &actualFormatInfo = isSubImage
338 ? *texture->getFormat(target, level).info
339 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 if (isCompressed)
341 {
tmartino7c102692015-10-02 16:43:40 -0400342 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(
345 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400346 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400347 }
348
Geoff Lang966c9402017-04-18 12:38:27 -0400349 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350 {
Geoff Lang966c9402017-04-18 12:38:27 -0400351 if (!ValidCompressedSubImageSize(
352 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
353 texture->getWidth(target, level), texture->getHeight(target, level)))
354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500355 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400356 return false;
357 }
358
359 if (format != actualInternalFormat)
360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500361 context->handleError(InvalidOperation()
362 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400363 return false;
364 }
Geoff Lang86f81162017-10-30 15:10:45 -0400365
366 if (actualInternalFormat == GL_ETC1_RGB8_OES)
367 {
368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
369 return false;
370 }
Geoff Lang966c9402017-04-18 12:38:27 -0400371 }
372 else
373 {
374 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500376 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400377 return false;
378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 }
380
Geoff Langeb66a6e2016-10-31 13:06:12 -0400381 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500383 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400384 return false;
385 }
386
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 if (target == GL_TEXTURE_3D)
388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500389 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392 }
393 else
394 {
Geoff Langca271392017-04-05 12:30:00 -0400395 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 {
Geoff Lang5d601382014-07-22 15:14:06 -0400397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 }
400
401 // Validate sub image parameters
402 if (isSubImage)
403 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500404 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500406 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500412 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 }
415
416 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
417 std::numeric_limits<GLsizei>::max() - yoffset < height ||
418 std::numeric_limits<GLsizei>::max() - zoffset < depth)
419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500420 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 }
423
Geoff Langa9be0dc2014-12-17 12:34:40 -0500424 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
425 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
426 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500428 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
Geoff Langfb052642017-10-24 13:42:09 -0400431
432 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400433 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400434 {
435 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
436 return false;
437 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 }
439
Geoff Langdbcced82017-06-06 15:55:54 -0400440 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
441 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
442 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400443 {
444 return false;
445 }
446
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400447 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400448 gl::Buffer *pixelUnpackBuffer =
449 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400450 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400451 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800452 // ...data is not evenly divisible into the number of bytes needed to store in memory a
453 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400454 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400455 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400456 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400457 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400458 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
459
Geoff Langff5b2d52016-09-07 11:32:23 -0400460 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500462 context->handleError(InvalidOperation()
463 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400464 return false;
465 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400466 }
467
Jamie Madill7a5f7382014-03-05 15:01:24 -0500468 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700469 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500471 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400472 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500473 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400474 }
475
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 return true;
477}
478
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500479bool ValidateES3TexImage2DParameters(Context *context,
480 GLenum target,
481 GLint level,
482 GLenum internalformat,
483 bool isCompressed,
484 bool isSubImage,
485 GLint xoffset,
486 GLint yoffset,
487 GLint zoffset,
488 GLsizei width,
489 GLsizei height,
490 GLsizei depth,
491 GLint border,
492 GLenum format,
493 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400494 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400495 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500496{
497 if (!ValidTexture2DDestinationTarget(context, target))
498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500499 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500500 return false;
501 }
502
503 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
504 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400505 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500506}
507
508bool ValidateES3TexImage3DParameters(Context *context,
509 GLenum target,
510 GLint level,
511 GLenum internalformat,
512 bool isCompressed,
513 bool isSubImage,
514 GLint xoffset,
515 GLint yoffset,
516 GLint zoffset,
517 GLsizei width,
518 GLsizei height,
519 GLsizei depth,
520 GLint border,
521 GLenum format,
522 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400523 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400524 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500525{
526 if (!ValidTexture3DDestinationTarget(context, target))
527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500528 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500529 return false;
530 }
531
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500532 if (IsETC2EACFormat(format) && target != GL_TEXTURE_2D_ARRAY)
533 {
534 // ES 3.1, Section 8.7, page 169.
535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
536 return false;
537 }
538
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500539 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
540 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400541 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542}
543
Geoff Lang5d601382014-07-22 15:14:06 -0400544struct EffectiveInternalFormatInfo
545{
Jamie Madill76648fe2016-10-05 17:01:41 -0400546 GLenum effectiveFormat;
547 GLenum destFormat;
548 GLuint minRedBits;
549 GLuint maxRedBits;
550 GLuint minGreenBits;
551 GLuint maxGreenBits;
552 GLuint minBlueBits;
553 GLuint maxBlueBits;
554 GLuint minAlphaBits;
555 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400556};
557
Jamie Madill76648fe2016-10-05 17:01:41 -0400558static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
559 GLenum targetFormat,
560 const EffectiveInternalFormatInfo *list,
561 size_t size,
562 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400563{
Jamie Madill76648fe2016-10-05 17:01:41 -0400564 for (size_t curFormat = 0; curFormat < size; ++curFormat)
565 {
566 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
567 if ((formatInfo.destFormat == targetFormat) &&
568 (formatInfo.minRedBits <= srcFormat.redBits &&
569 formatInfo.maxRedBits >= srcFormat.redBits) &&
570 (formatInfo.minGreenBits <= srcFormat.greenBits &&
571 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
572 (formatInfo.minBlueBits <= srcFormat.blueBits &&
573 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
574 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
575 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
576 {
577 *outEffectiveFormat = formatInfo.effectiveFormat;
578 return true;
579 }
580 }
Geoff Lang5d601382014-07-22 15:14:06 -0400581
Jamie Madill76648fe2016-10-05 17:01:41 -0400582 *outEffectiveFormat = GL_NONE;
583 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400584}
585
Jamie Madill76648fe2016-10-05 17:01:41 -0400586bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
587 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400588{
Jamie Madill76648fe2016-10-05 17:01:41 -0400589 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
590 // Effective internal format coresponding to destination internal format and linear source
591 // buffer component sizes.
592 // | Source channel min/max sizes |
593 // Effective Internal Format | N/A | R | G | B | A |
594 // clang-format off
595 constexpr EffectiveInternalFormatInfo list[] = {
596 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
597 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
598 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
599 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
600 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
601 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
602 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
603 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
604 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
605 };
606 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400607
Jamie Madill76648fe2016-10-05 17:01:41 -0400608 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
609}
Geoff Lang5d601382014-07-22 15:14:06 -0400610
Jamie Madill76648fe2016-10-05 17:01:41 -0400611bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
612 const InternalFormat &destFormat,
613 GLenum *outEffectiveFormat)
614{
615 constexpr GLuint umax = UINT_MAX;
616
617 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
618 // Effective internal format coresponding to destination internal format andlinear source buffer
619 // component sizes.
620 // | Source channel min/max sizes |
621 // Effective Internal Format | Dest Format | R | G | B | A |
622 // clang-format off
623 constexpr EffectiveInternalFormatInfo list[] = {
624 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
625 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
626 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
627 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
628 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
629 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
630 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
631 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
632 };
633 // clang-format on
634
635 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
636 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400637}
638
He Yunchaoced53ae2016-11-29 15:00:51 +0800639static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
640 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400641 GLenum *outEffectiveFormat)
642{
Geoff Langca271392017-04-05 12:30:00 -0400643 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400644 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400645 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400646 }
647 else
648 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400649 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400650 }
Geoff Lang5d601382014-07-22 15:14:06 -0400651}
652
Corentin Wallez76287682016-04-25 09:23:38 -0400653static bool EqualOrFirstZero(GLuint first, GLuint second)
654{
655 return first == 0 || first == second;
656}
657
Geoff Langca271392017-04-05 12:30:00 -0400658static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
659 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400660 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400661{
Jamie Madill21b786b2016-11-01 17:41:31 -0400662 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400663 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400664 return false;
665 }
Geoff Lang5d601382014-07-22 15:14:06 -0400666
Jamie Madill21b786b2016-11-01 17:41:31 -0400667 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
668 // must both be signed, unsigned, or fixed point and both source and destinations
669 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
670 // conversion between fixed and floating point.
671
672 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
673 (framebufferFormatInfo.colorEncoding == GL_SRGB))
674 {
675 return false;
676 }
677
678 if (((textureFormatInfo.componentType == GL_INT) !=
679 (framebufferFormatInfo.componentType == GL_INT)) ||
680 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
681 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
682 {
683 return false;
684 }
685
686 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
687 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
688 textureFormatInfo.componentType == GL_FLOAT) &&
689 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
690 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
691 framebufferFormatInfo.componentType == GL_FLOAT))
692 {
693 return false;
694 }
695
696 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
697 // The effective internal format of the source buffer is determined with the following rules
698 // applied in order:
699 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
700 // format then the effective internal format is the source buffer's sized internal format.
701 // * If the source buffer is a texture that was created with an unsized base internal format,
702 // then the effective internal format is the source image array's effective internal
703 // format, as specified by table 3.12, which is determined from the <format> and <type>
704 // that were used when the source image array was specified by TexImage*.
705 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
706 // where Destination Internal Format matches internalformat and where the [source channel
707 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
708 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
709 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800710 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400711 if (readBufferHandle != 0)
712 {
713 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
714 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400715 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400716 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400718 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 else
Geoff Lang5d601382014-07-22 15:14:06 -0400720 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400721 // Renderbuffers cannot be created with an unsized internal format, so this must be an
722 // unsized-format texture. We can use the same table we use when creating textures to
723 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400724 sourceEffectiveFormat =
725 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400726 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400727 }
728 else
729 {
730 // The effective internal format must be derived from the source framebuffer's channel
731 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
732 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400733 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400734 GLenum effectiveFormat;
735 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
736 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400737 {
Geoff Langca271392017-04-05 12:30:00 -0400738 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400739 }
740 else
741 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400742 return false;
743 }
744 }
745 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
746 {
747 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400748 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400749 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
750 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
751 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
752 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
753 {
Geoff Langca271392017-04-05 12:30:00 -0400754 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400755 }
756 else
757 {
758 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400759 }
760 }
761 else
762 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400763 UNREACHABLE();
764 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400765 }
Geoff Lang5d601382014-07-22 15:14:06 -0400766 }
767
Geoff Langca271392017-04-05 12:30:00 -0400768 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400769 {
770 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
771 // sized, component sizes of the source and destination formats must exactly match if the
772 // destination format exists.
773 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
774 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
775 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
776 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
777 {
778 return false;
779 }
780 }
781
782 return true; // A conversion function exists, and no rule in the specification has precluded
783 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400784}
785
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
787 GLenum target,
788 GLint level,
789 GLenum internalformat,
790 bool isSubImage,
791 GLint xoffset,
792 GLint yoffset,
793 GLint zoffset,
794 GLint x,
795 GLint y,
796 GLsizei width,
797 GLsizei height,
798 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400799{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400801 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400802 xoffset, yoffset, zoffset, x, y, width, height, border,
803 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400804 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400805 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400807 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808
Jamie Madill51f40ec2016-06-15 14:06:00 -0400809 const auto &state = context->getGLState();
810 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
811 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400813 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500815 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400816 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400817 }
818
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400819 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500821 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400822 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400823 }
824
Jamie Madill0c8abca2016-07-22 20:21:26 -0400825 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826
827 if (isSubImage)
828 {
Geoff Langca271392017-04-05 12:30:00 -0400829 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500830 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500832 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400833 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 }
835 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400836 else
837 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400838 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400839 const InternalFormat &framebufferFormat = *source->getFormat().info;
840 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400841 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500843 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400844 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400845 }
846 }
847
Geoff Lang784a8fd2013-09-24 12:33:16 -0400848 // If width or height is zero, it is a no-op. Return false without setting an error.
849 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850}
851
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500852bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
853 GLenum target,
854 GLint level,
855 GLenum internalformat,
856 bool isSubImage,
857 GLint xoffset,
858 GLint yoffset,
859 GLint zoffset,
860 GLint x,
861 GLint y,
862 GLsizei width,
863 GLsizei height,
864 GLint border)
865{
866 if (!ValidTexture2DDestinationTarget(context, target))
867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500868 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500869 return false;
870 }
871
872 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
873 xoffset, yoffset, zoffset, x, y, width, height,
874 border);
875}
876
877bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
878 GLenum target,
879 GLint level,
880 GLenum internalformat,
881 bool isSubImage,
882 GLint xoffset,
883 GLint yoffset,
884 GLint zoffset,
885 GLint x,
886 GLint y,
887 GLsizei width,
888 GLsizei height,
889 GLint border)
890{
891 if (!ValidTexture3DDestinationTarget(context, target))
892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500893 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500894 return false;
895 }
896
897 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
898 xoffset, yoffset, zoffset, x, y, width, height,
899 border);
900}
901
902bool ValidateES3TexStorageParametersBase(Context *context,
903 GLenum target,
904 GLsizei levels,
905 GLenum internalformat,
906 GLsizei width,
907 GLsizei height,
908 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909{
910 if (width < 1 || height < 1 || depth < 1 || levels < 1)
911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500912 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400913 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 }
915
Geoff Langb92c1332015-09-04 12:54:55 -0400916 GLsizei maxDim = std::max(width, height);
917 if (target != GL_TEXTURE_2D_ARRAY)
918 {
919 maxDim = std::max(maxDim, depth);
920 }
921
922 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500924 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400925 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 }
927
Geoff Langaae65a42014-05-26 12:43:44 -0400928 const gl::Caps &caps = context->getCaps();
929
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 switch (target)
931 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800932 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 {
Geoff Langaae65a42014-05-26 12:43:44 -0400934 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
935 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500937 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 }
940 }
941 break;
942
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400943 case GL_TEXTURE_RECTANGLE_ANGLE:
944 {
945 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
946 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
947 {
948 context->handleError(InvalidValue());
949 return false;
950 }
951 }
952 break;
953
He Yunchaoced53ae2016-11-29 15:00:51 +0800954 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400955 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 if (width != height)
957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500958 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 }
961
Geoff Langaae65a42014-05-26 12:43:44 -0400962 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500964 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400965 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966 }
967 }
968 break;
969
He Yunchaoced53ae2016-11-29 15:00:51 +0800970 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 {
Geoff Langaae65a42014-05-26 12:43:44 -0400972 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
973 static_cast<GLuint>(height) > caps.max3DTextureSize ||
974 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500976 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400977 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400978 }
979 }
980 break;
981
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 {
Geoff Langaae65a42014-05-26 12:43:44 -0400984 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
985 static_cast<GLuint>(height) > caps.max2DTextureSize ||
986 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500988 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 }
991 }
992 break;
993
He Yunchaoced53ae2016-11-29 15:00:51 +0800994 default:
995 UNREACHABLE();
996 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997 }
998
Geoff Lang691e58c2014-12-19 17:03:25 -0500999 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 if (!texture || texture->id() == 0)
1001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001002 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001003 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 }
1005
Geoff Lang69cce582015-09-17 13:20:36 -04001006 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001009 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 }
1011
Geoff Langca271392017-04-05 12:30:00 -04001012 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001013 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001015 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001017 }
1018
Geoff Langca271392017-04-05 12:30:00 -04001019 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001021 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001025 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1026 {
1027 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1028 return false;
1029 }
1030
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 return true;
1032}
1033
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001034bool ValidateES3TexStorage2DParameters(Context *context,
1035 GLenum target,
1036 GLsizei levels,
1037 GLenum internalformat,
1038 GLsizei width,
1039 GLsizei height,
1040 GLsizei depth)
1041{
1042 if (!ValidTexture2DTarget(context, target))
1043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001044 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001045 return false;
1046 }
1047
1048 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1049 height, depth);
1050}
1051
1052bool ValidateES3TexStorage3DParameters(Context *context,
1053 GLenum target,
1054 GLsizei levels,
1055 GLenum internalformat,
1056 GLsizei width,
1057 GLsizei height,
1058 GLsizei depth)
1059{
1060 if (!ValidTexture3DTarget(context, target))
1061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001062 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001063 return false;
1064 }
1065
1066 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1067 height, depth);
1068}
1069
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001070bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1071{
Martin Radev1be913c2016-07-11 17:59:16 +03001072 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001073 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001075 return false;
1076 }
1077
1078 return ValidateBeginQueryBase(context, target, id);
1079}
1080
1081bool ValidateEndQuery(gl::Context *context, GLenum target)
1082{
Martin Radev1be913c2016-07-11 17:59:16 +03001083 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001084 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086 return false;
1087 }
1088
1089 return ValidateEndQueryBase(context, target);
1090}
1091
1092bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1093{
Martin Radev1be913c2016-07-11 17:59:16 +03001094 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001095 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097 return false;
1098 }
1099
Geoff Lang2186c382016-10-14 10:54:54 -04001100 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001101}
1102
1103bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1104{
Martin Radev1be913c2016-07-11 17:59:16 +03001105 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001106 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001107 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001108 return false;
1109 }
1110
Geoff Lang2186c382016-10-14 10:54:54 -04001111 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001112}
1113
He Yunchaoced53ae2016-11-29 15:00:51 +08001114bool ValidateFramebufferTextureLayer(Context *context,
1115 GLenum target,
1116 GLenum attachment,
1117 GLuint texture,
1118 GLint level,
1119 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001120{
Martin Radev1be913c2016-07-11 17:59:16 +03001121 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001122 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001125 }
1126
Jamie Madill55ec3b12014-07-03 10:38:57 -04001127 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1128 {
1129 return false;
1130 }
1131
1132 const gl::Caps &caps = context->getCaps();
1133 if (texture != 0)
1134 {
Geoff Lang23e02842017-10-17 13:24:09 -04001135 if (layer < 0)
1136 {
1137 context->handleError(InvalidValue());
1138 return false;
1139 }
1140
Jamie Madill55ec3b12014-07-03 10:38:57 -04001141 gl::Texture *tex = context->getTexture(texture);
1142 ASSERT(tex);
1143
1144 switch (tex->getTarget())
1145 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001147 {
1148 if (level > gl::log2(caps.max2DTextureSize))
1149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001150 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001151 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001152 }
1153
1154 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001158 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001159 }
1160 break;
1161
He Yunchaoced53ae2016-11-29 15:00:51 +08001162 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001163 {
1164 if (level > gl::log2(caps.max3DTextureSize))
1165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001166 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001168 }
1169
1170 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001172 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001174 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001175 }
1176 break;
1177
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001179 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001180 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001181 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001182
Jamie Madilla3944d42016-07-22 22:13:26 -04001183 const auto &format = tex->getFormat(tex->getTarget(), level);
1184 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001186 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001187 return false;
1188 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001189 }
1190
1191 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001192}
1193
He Yunchaoced53ae2016-11-29 15:00:51 +08001194bool ValidateInvalidateFramebuffer(Context *context,
1195 GLenum target,
1196 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001197 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001198{
Martin Radev1be913c2016-07-11 17:59:16 +03001199 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001202 return false;
1203 }
1204
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001205 bool defaultFramebuffer = false;
1206
1207 switch (target)
1208 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001209 case GL_DRAW_FRAMEBUFFER:
1210 case GL_FRAMEBUFFER:
1211 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1212 break;
1213 case GL_READ_FRAMEBUFFER:
1214 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1215 break;
1216 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001217 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 }
1220
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1222 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223}
1224
Jamie Madill3ef140a2017-08-26 23:11:21 -04001225bool ValidateInvalidateSubFramebuffer(Context *context,
1226 GLenum target,
1227 GLsizei numAttachments,
1228 const GLenum *attachments,
1229 GLint x,
1230 GLint y,
1231 GLsizei width,
1232 GLsizei height)
1233{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001234 if (width < 0 || height < 0)
1235 {
1236 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1237 return false;
1238 }
1239
Jamie Madill3ef140a2017-08-26 23:11:21 -04001240 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1241}
1242
Jamie Madillc29968b2016-01-20 11:17:23 -05001243bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001244{
Martin Radev1be913c2016-07-11 17:59:16 +03001245 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001246 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001249 }
1250
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001251 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001253 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001254 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001255 }
1256
1257 return true;
1258}
1259
Olli Etuaho71dfb362016-03-10 14:04:27 +02001260bool ValidateDrawRangeElements(Context *context,
1261 GLenum mode,
1262 GLuint start,
1263 GLuint end,
1264 GLsizei count,
1265 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001266 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001267{
Martin Radev1be913c2016-07-11 17:59:16 +03001268 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001269 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001271 return false;
1272 }
1273
1274 if (end < start)
1275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001276 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001277 return false;
1278 }
1279
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001280 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001281 {
1282 return false;
1283 }
1284
Jamie Madill9fdaa492018-02-16 10:52:11 -05001285 // Skip range checks for no-op calls.
1286 if (count <= 0)
1287 {
1288 return true;
1289 }
1290
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001291 // Use the parameter buffer to retrieve and cache the index range.
1292 const auto &params = context->getParams<HasIndexRange>();
1293 const auto &indexRangeOpt = params.getIndexRange();
1294 if (!indexRangeOpt.valid())
1295 {
1296 // Unexpected error.
1297 return false;
1298 }
1299
1300 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001301 {
1302 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001304 return false;
1305 }
1306 return true;
1307}
1308
He Yunchaoced53ae2016-11-29 15:00:51 +08001309bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001310{
Martin Radev1be913c2016-07-11 17:59:16 +03001311 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001312 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001315 }
1316
Jamie Madill78f41802014-08-25 15:47:55 -04001317 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001318}
1319
Jamie Madillb885e572015-02-03 16:16:04 -05001320bool ValidateReadBuffer(Context *context, GLenum src)
1321{
Martin Radev1be913c2016-07-11 17:59:16 +03001322 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001323 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001325 return false;
1326 }
1327
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001328 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001329
1330 if (readFBO == nullptr)
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001333 return false;
1334 }
1335
1336 if (src == GL_NONE)
1337 {
1338 return true;
1339 }
1340
Olli Etuaho84c9f592016-03-09 14:37:25 +02001341 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001344 return false;
1345 }
1346
1347 if (readFBO->id() == 0)
1348 {
1349 if (src != GL_BACK)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(
1352 InvalidOperation()
1353 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001354 return false;
1355 }
1356 }
1357 else
1358 {
1359 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1360
1361 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001364 return false;
1365 }
1366 }
1367
1368 return true;
1369}
1370
Jamie Madill86af3d22015-07-21 15:14:07 -04001371bool ValidateCompressedTexImage3D(Context *context,
1372 GLenum target,
1373 GLint level,
1374 GLenum internalformat,
1375 GLsizei width,
1376 GLsizei height,
1377 GLsizei depth,
1378 GLint border,
1379 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001380 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001381{
Martin Radev1be913c2016-07-11 17:59:16 +03001382 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001384 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001385 return false;
1386 }
1387
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001388 if (!ValidTextureTarget(context, target))
1389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001391 return false;
1392 }
1393
Jamie Madille2e406c2016-06-02 13:04:10 -04001394 // Validate image size
1395 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001398 return false;
1399 }
1400
Geoff Langca271392017-04-05 12:30:00 -04001401 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001402 if (!formatInfo.compressed)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001405 return false;
1406 }
1407
Jeff Gilbert48590352017-11-07 16:03:38 -08001408 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001409 if (blockSizeOrErr.isError())
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001412 return false;
1413 }
1414 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001417 return false;
1418 }
1419
1420 // 3D texture target validation
1421 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001424 return false;
1425 }
1426
1427 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001428 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001429 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1430 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001431 {
1432 return false;
1433 }
1434
1435 return true;
1436}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001437
Corentin Wallezb2931602017-04-11 15:58:57 -04001438bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1439 GLenum target,
1440 GLint level,
1441 GLenum internalformat,
1442 GLsizei width,
1443 GLsizei height,
1444 GLsizei depth,
1445 GLint border,
1446 GLsizei imageSize,
1447 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001448 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001449{
1450 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1451 {
1452 return false;
1453 }
1454
1455 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1456 depth, border, imageSize, data);
1457}
1458
Austin Kinrossbc781f32015-10-26 09:27:38 -07001459bool ValidateBindVertexArray(Context *context, GLuint array)
1460{
Martin Radev1be913c2016-07-11 17:59:16 +03001461 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001462 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001464 return false;
1465 }
1466
1467 return ValidateBindVertexArrayBase(context, array);
1468}
1469
Jamie Madilld7576732017-08-26 18:49:50 -04001470bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001471{
Martin Radev1be913c2016-07-11 17:59:16 +03001472 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001473 {
Jamie Madilld7576732017-08-26 18:49:50 -04001474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001475 return false;
1476 }
1477
1478 return true;
1479}
Geoff Langc5629752015-12-07 16:29:04 -05001480
Jiajia Qin6eafb042016-12-27 17:04:07 +08001481static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001482 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001483 GLuint index,
1484 GLuint buffer,
1485 GLintptr offset,
1486 GLsizeiptr size)
1487{
1488 if (context->getClientMajorVersion() < 3)
1489 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001491 return false;
1492 }
1493
1494 if (buffer != 0 && offset < 0)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001497 return false;
1498 }
1499
1500 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1501 !context->isBufferGenerated(buffer))
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 return false;
1505 }
1506
1507 const Caps &caps = context->getCaps();
1508 switch (target)
1509 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001510 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001511 {
1512 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidValue() << "index is greater than or equal to the "
1515 "number of TRANSFORM_FEEDBACK_BUFFER "
1516 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001517 return false;
1518 }
1519 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001522 return false;
1523 }
1524
1525 TransformFeedback *curTransformFeedback =
1526 context->getGLState().getCurrentTransformFeedback();
1527 if (curTransformFeedback && curTransformFeedback->isActive())
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation()
1530 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1531 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 return false;
1533 }
1534 break;
1535 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001536 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001537 {
1538 if (index >= caps.maxUniformBufferBindings)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidValue() << "index is greater than or equal to the "
1541 "number of UNIFORM_BUFFER indexed "
1542 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001543 return false;
1544 }
1545
1546 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1547 {
1548 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001549 InvalidValue()
1550 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001551 return false;
1552 }
1553 break;
1554 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001555 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001556 {
1557 if (context->getClientVersion() < ES_3_1)
1558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001559 context->handleError(InvalidEnum()
1560 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001561 return false;
1562 }
1563 if (index >= caps.maxAtomicCounterBufferBindings)
1564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001565 context->handleError(InvalidValue() << "index is greater than or equal to the "
1566 "number of ATOMIC_COUNTER_BUFFER "
1567 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001568 return false;
1569 }
1570 if (buffer != 0 && (offset % 4) != 0)
1571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001572 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001573 return false;
1574 }
1575 break;
1576 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001577 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001578 {
1579 if (context->getClientVersion() < ES_3_1)
1580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001581 context->handleError(InvalidEnum()
1582 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001583 return false;
1584 }
1585 if (index >= caps.maxShaderStorageBufferBindings)
1586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidValue() << "index is greater than or equal to the "
1588 "number of SHADER_STORAGE_BUFFER "
1589 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001590 return false;
1591 }
1592 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidValue() << "offset must be multiple of value of "
1595 "SHADER_STORAGE_BUFFER_OFFSET_"
1596 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001597 return false;
1598 }
1599 break;
1600 }
1601 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001602 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001603 return false;
1604 }
1605
1606 return true;
1607}
1608
Corentin Wallez336129f2017-10-17 15:55:40 -04001609bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001610{
1611 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1612}
1613
1614bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001615 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001616 GLuint index,
1617 GLuint buffer,
1618 GLintptr offset,
1619 GLsizeiptr size)
1620{
1621 if (buffer != 0 && size <= 0)
1622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001623 context->handleError(InvalidValue()
1624 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001625 return false;
1626 }
1627 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1628}
1629
Geoff Langc5629752015-12-07 16:29:04 -05001630bool ValidateProgramBinary(Context *context,
1631 GLuint program,
1632 GLenum binaryFormat,
1633 const void *binary,
1634 GLint length)
1635{
Martin Radev1be913c2016-07-11 17:59:16 +03001636 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001637 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001639 return false;
1640 }
1641
1642 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1643}
1644
1645bool ValidateGetProgramBinary(Context *context,
1646 GLuint program,
1647 GLsizei bufSize,
1648 GLsizei *length,
1649 GLenum *binaryFormat,
1650 void *binary)
1651{
Martin Radev1be913c2016-07-11 17:59:16 +03001652 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001653 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001655 return false;
1656 }
1657
1658 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1659}
1660
Olli Etuahof0fee072016-03-30 15:11:58 +03001661bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001662{
Martin Radev1be913c2016-07-11 17:59:16 +03001663 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001664 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001666 return false;
1667 }
1668
1669 if (GetValidProgram(context, program) == nullptr)
1670 {
1671 return false;
1672 }
1673
1674 switch (pname)
1675 {
1676 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001677 if (value != GL_FALSE && value != GL_TRUE)
1678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001679 context->handleError(InvalidValue()
1680 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001681 return false;
1682 }
Geoff Langc5629752015-12-07 16:29:04 -05001683 break;
1684
Yunchao He61afff12017-03-14 15:34:03 +08001685 case GL_PROGRAM_SEPARABLE:
1686 if (context->getClientVersion() < ES_3_1)
1687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(InvalidEnum()
1689 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001690 return false;
1691 }
1692
1693 if (value != GL_FALSE && value != GL_TRUE)
1694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001695 context->handleError(InvalidValue()
1696 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001697 return false;
1698 }
1699 break;
1700
Geoff Langc5629752015-12-07 16:29:04 -05001701 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(InvalidEnum()
1703 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001704 return false;
1705 }
1706
1707 return true;
1708}
Jamie Madillc29968b2016-01-20 11:17:23 -05001709
1710bool ValidateBlitFramebuffer(Context *context,
1711 GLint srcX0,
1712 GLint srcY0,
1713 GLint srcX1,
1714 GLint srcY1,
1715 GLint dstX0,
1716 GLint dstY0,
1717 GLint dstX1,
1718 GLint dstY1,
1719 GLbitfield mask,
1720 GLenum filter)
1721{
Martin Radev1be913c2016-07-11 17:59:16 +03001722 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
1727
1728 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1729 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001730}
Jamie Madillc29968b2016-01-20 11:17:23 -05001731
1732bool ValidateClearBufferiv(ValidationContext *context,
1733 GLenum buffer,
1734 GLint drawbuffer,
1735 const GLint *value)
1736{
1737 switch (buffer)
1738 {
1739 case GL_COLOR:
1740 if (drawbuffer < 0 ||
1741 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001744 return false;
1745 }
Geoff Lang76e65652017-03-27 14:58:02 -04001746 if (context->getExtensions().webglCompatibility)
1747 {
1748 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001749 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001750 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1751 {
1752 return false;
1753 }
1754 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001755 break;
1756
1757 case GL_STENCIL:
1758 if (drawbuffer != 0)
1759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
1763 break;
1764
1765 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001767 return false;
1768 }
1769
1770 return ValidateClearBuffer(context);
1771}
1772
1773bool ValidateClearBufferuiv(ValidationContext *context,
1774 GLenum buffer,
1775 GLint drawbuffer,
1776 const GLuint *value)
1777{
1778 switch (buffer)
1779 {
1780 case GL_COLOR:
1781 if (drawbuffer < 0 ||
1782 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001784 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 return false;
1786 }
Geoff Lang76e65652017-03-27 14:58:02 -04001787 if (context->getExtensions().webglCompatibility)
1788 {
1789 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001790 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001791 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1792 {
1793 return false;
1794 }
1795 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001796 break;
1797
1798 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001800 return false;
1801 }
1802
1803 return ValidateClearBuffer(context);
1804}
1805
1806bool ValidateClearBufferfv(ValidationContext *context,
1807 GLenum buffer,
1808 GLint drawbuffer,
1809 const GLfloat *value)
1810{
1811 switch (buffer)
1812 {
1813 case GL_COLOR:
1814 if (drawbuffer < 0 ||
1815 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001817 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001818 return false;
1819 }
Geoff Lang76e65652017-03-27 14:58:02 -04001820 if (context->getExtensions().webglCompatibility)
1821 {
1822 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1823 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001824 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001825 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1826 {
1827 return false;
1828 }
1829 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 break;
1831
1832 case GL_DEPTH:
1833 if (drawbuffer != 0)
1834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001836 return false;
1837 }
1838 break;
1839
1840 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001841 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001842 return false;
1843 }
1844
1845 return ValidateClearBuffer(context);
1846}
1847
1848bool ValidateClearBufferfi(ValidationContext *context,
1849 GLenum buffer,
1850 GLint drawbuffer,
1851 GLfloat depth,
1852 GLint stencil)
1853{
1854 switch (buffer)
1855 {
1856 case GL_DEPTH_STENCIL:
1857 if (drawbuffer != 0)
1858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001859 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001860 return false;
1861 }
1862 break;
1863
1864 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001865 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001866 return false;
1867 }
1868
1869 return ValidateClearBuffer(context);
1870}
1871
1872bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1873{
Martin Radev1be913c2016-07-11 17:59:16 +03001874 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001875 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001876 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001877 return false;
1878 }
1879
1880 return ValidateDrawBuffersBase(context, n, bufs);
1881}
1882
1883bool ValidateCopyTexSubImage3D(Context *context,
1884 GLenum target,
1885 GLint level,
1886 GLint xoffset,
1887 GLint yoffset,
1888 GLint zoffset,
1889 GLint x,
1890 GLint y,
1891 GLsizei width,
1892 GLsizei height)
1893{
Martin Radev1be913c2016-07-11 17:59:16 +03001894 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001895 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001897 return false;
1898 }
1899
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001900 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1901 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001902}
1903
Jamie Madill73a84962016-02-12 09:27:23 -05001904bool ValidateTexImage3D(Context *context,
1905 GLenum target,
1906 GLint level,
1907 GLint internalformat,
1908 GLsizei width,
1909 GLsizei height,
1910 GLsizei depth,
1911 GLint border,
1912 GLenum format,
1913 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001914 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001915{
Martin Radev1be913c2016-07-11 17:59:16 +03001916 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001917 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001919 return false;
1920 }
1921
1922 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001923 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001924 pixels);
1925}
1926
Geoff Langc52f6f12016-10-14 10:18:00 -04001927bool ValidateTexImage3DRobustANGLE(Context *context,
1928 GLenum target,
1929 GLint level,
1930 GLint internalformat,
1931 GLsizei width,
1932 GLsizei height,
1933 GLsizei depth,
1934 GLint border,
1935 GLenum format,
1936 GLenum type,
1937 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001938 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001939{
1940 if (context->getClientMajorVersion() < 3)
1941 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001943 return false;
1944 }
1945
1946 if (!ValidateRobustEntryPoint(context, bufSize))
1947 {
1948 return false;
1949 }
1950
1951 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1952 0, 0, width, height, depth, border, format, type,
1953 bufSize, pixels);
1954}
1955
Jamie Madill73a84962016-02-12 09:27:23 -05001956bool ValidateTexSubImage3D(Context *context,
1957 GLenum target,
1958 GLint level,
1959 GLint xoffset,
1960 GLint yoffset,
1961 GLint zoffset,
1962 GLsizei width,
1963 GLsizei height,
1964 GLsizei depth,
1965 GLenum format,
1966 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001967 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001968{
Martin Radev1be913c2016-07-11 17:59:16 +03001969 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001970 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001971 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001972 return false;
1973 }
1974
1975 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1976 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001977 -1, pixels);
1978}
1979
1980bool ValidateTexSubImage3DRobustANGLE(Context *context,
1981 GLenum target,
1982 GLint level,
1983 GLint xoffset,
1984 GLint yoffset,
1985 GLint zoffset,
1986 GLsizei width,
1987 GLsizei height,
1988 GLsizei depth,
1989 GLenum format,
1990 GLenum type,
1991 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001992 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001993{
1994 if (context->getClientMajorVersion() < 3)
1995 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001997 return false;
1998 }
1999
2000 if (!ValidateRobustEntryPoint(context, bufSize))
2001 {
2002 return false;
2003 }
2004
2005 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2006 yoffset, zoffset, width, height, depth, 0, format, type,
2007 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002008}
2009
2010bool ValidateCompressedTexSubImage3D(Context *context,
2011 GLenum target,
2012 GLint level,
2013 GLint xoffset,
2014 GLint yoffset,
2015 GLint zoffset,
2016 GLsizei width,
2017 GLsizei height,
2018 GLsizei depth,
2019 GLenum format,
2020 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002021 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002022{
Martin Radev1be913c2016-07-11 17:59:16 +03002023 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002024 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002026 return false;
2027 }
2028
Geoff Langca271392017-04-05 12:30:00 -04002029 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002030 if (!formatInfo.compressed)
2031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002032 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002033 return false;
2034 }
2035
Jeff Gilbert48590352017-11-07 16:03:38 -08002036 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002037 if (blockSizeOrErr.isError())
2038 {
2039 context->handleError(blockSizeOrErr.getError());
2040 return false;
2041 }
2042 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002044 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002045 return false;
2046 }
2047
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002048 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2049 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2050 -1, data))
2051 {
2052 return false;
2053 }
2054
Jamie Madill73a84962016-02-12 09:27:23 -05002055 if (!data)
2056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002058 return false;
2059 }
2060
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002061 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002062}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002063
Corentin Wallezb2931602017-04-11 15:58:57 -04002064bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2065 GLenum target,
2066 GLint level,
2067 GLint xoffset,
2068 GLint yoffset,
2069 GLint zoffset,
2070 GLsizei width,
2071 GLsizei height,
2072 GLsizei depth,
2073 GLenum format,
2074 GLsizei imageSize,
2075 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002076 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002077{
2078 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2079 {
2080 return false;
2081 }
2082
2083 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2084 height, depth, format, imageSize, data);
2085}
Jamie Madill73a84962016-02-12 09:27:23 -05002086
Olli Etuaho41997e72016-03-10 13:38:39 +02002087bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2088{
2089 return ValidateGenOrDeleteES3(context, n);
2090}
2091
2092bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2093{
2094 return ValidateGenOrDeleteES3(context, n);
2095}
2096
2097bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2098{
2099 return ValidateGenOrDeleteCountES3(context, count);
2100}
2101
2102bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2103{
2104 return ValidateGenOrDeleteCountES3(context, count);
2105}
2106
2107bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2108{
2109 return ValidateGenOrDeleteES3(context, n);
2110}
2111
2112bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2113{
2114 if (!ValidateGenOrDeleteES3(context, n))
2115 {
2116 return false;
2117 }
2118 for (GLint i = 0; i < n; ++i)
2119 {
2120 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2121 if (transformFeedback != nullptr && transformFeedback->isActive())
2122 {
2123 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002124 context->handleError(InvalidOperation()
2125 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002126 return false;
2127 }
2128 }
2129 return true;
2130}
2131
2132bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2133{
2134 return ValidateGenOrDeleteES3(context, n);
2135}
2136
2137bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2138{
2139 return ValidateGenOrDeleteES3(context, n);
2140}
2141
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002142bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2143{
Martin Radev1be913c2016-07-11 17:59:16 +03002144 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002145 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002147 return false;
2148 }
2149 switch (primitiveMode)
2150 {
2151 case GL_TRIANGLES:
2152 case GL_LINES:
2153 case GL_POINTS:
2154 break;
2155
2156 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002157 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002158 return false;
2159 }
2160
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002161 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002162 ASSERT(transformFeedback != nullptr);
2163
2164 if (transformFeedback->isActive())
2165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002166 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002167 return false;
2168 }
Geoff Lang79f71042017-08-14 16:43:43 -04002169
2170 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2171 {
2172 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2173 if (buffer.get() && buffer->isMapped())
2174 {
2175 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2176 return false;
2177 }
2178 }
2179
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002180 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002181
2182 if (!program)
2183 {
2184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2185 return false;
2186 }
2187
2188 if (program->getTransformFeedbackVaryingCount() == 0)
2189 {
2190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2191 return false;
2192 }
2193
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002194 return true;
2195}
2196
Corentin Wallez336129f2017-10-17 15:55:40 -04002197bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002198{
Geoff Lang496c02d2016-10-20 11:38:11 -07002199 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2200}
2201
2202bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002203 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002204 GLenum pname,
2205 GLsizei bufSize,
2206 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002207 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002208{
2209 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002210 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002211 return false;
2212 }
2213
Geoff Lang496c02d2016-10-20 11:38:11 -07002214 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2215 {
2216 return false;
2217 }
2218
2219 if (!ValidateRobustBufferSize(context, bufSize, *length))
2220 {
2221 return false;
2222 }
2223
2224 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002225}
2226
Corentin Wallez336129f2017-10-17 15:55:40 -04002227bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002228{
Martin Radev1be913c2016-07-11 17:59:16 +03002229 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002230 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002232 return false;
2233 }
2234
2235 return ValidateUnmapBufferBase(context, target);
2236}
2237
2238bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002239 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002240 GLintptr offset,
2241 GLsizeiptr length,
2242 GLbitfield access)
2243{
Martin Radev1be913c2016-07-11 17:59:16 +03002244 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002245 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002247 return false;
2248 }
2249
2250 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2251}
2252
2253bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002254 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002255 GLintptr offset,
2256 GLsizeiptr length)
2257{
Martin Radev1be913c2016-07-11 17:59:16 +03002258 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002259 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002261 return false;
2262 }
2263
2264 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2265}
2266
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002267bool ValidateIndexedStateQuery(ValidationContext *context,
2268 GLenum pname,
2269 GLuint index,
2270 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002271{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002272 if (length)
2273 {
2274 *length = 0;
2275 }
2276
Martin Radev66fb8202016-07-28 11:45:20 +03002277 GLenum nativeType;
2278 unsigned int numParams;
2279 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002281 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002282 return false;
2283 }
2284
2285 const Caps &caps = context->getCaps();
2286 switch (pname)
2287 {
2288 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2289 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2290 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2291 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002293 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002294 return false;
2295 }
2296 break;
2297
2298 case GL_UNIFORM_BUFFER_START:
2299 case GL_UNIFORM_BUFFER_SIZE:
2300 case GL_UNIFORM_BUFFER_BINDING:
2301 if (index >= caps.maxUniformBufferBindings)
2302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002303 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002304 return false;
2305 }
2306 break;
Shao80957d92017-02-20 21:25:59 +08002307
Martin Radev66fb8202016-07-28 11:45:20 +03002308 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2309 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2310 if (index >= 3u)
2311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002312 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002313 return false;
2314 }
2315 break;
Shao80957d92017-02-20 21:25:59 +08002316
Jiajia Qin6eafb042016-12-27 17:04:07 +08002317 case GL_ATOMIC_COUNTER_BUFFER_START:
2318 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2319 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2320 if (context->getClientVersion() < ES_3_1)
2321 {
2322 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 InvalidEnum()
2324 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002325 return false;
2326 }
2327 if (index >= caps.maxAtomicCounterBufferBindings)
2328 {
2329 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002330 InvalidValue()
2331 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002332 return false;
2333 }
2334 break;
Shao80957d92017-02-20 21:25:59 +08002335
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002336 case GL_SHADER_STORAGE_BUFFER_START:
2337 case GL_SHADER_STORAGE_BUFFER_SIZE:
2338 case GL_SHADER_STORAGE_BUFFER_BINDING:
2339 if (context->getClientVersion() < ES_3_1)
2340 {
2341 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002342 InvalidEnum()
2343 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002344 return false;
2345 }
2346 if (index >= caps.maxShaderStorageBufferBindings)
2347 {
2348 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002349 InvalidValue()
2350 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002351 return false;
2352 }
2353 break;
2354
Shao80957d92017-02-20 21:25:59 +08002355 case GL_VERTEX_BINDING_BUFFER:
2356 case GL_VERTEX_BINDING_DIVISOR:
2357 case GL_VERTEX_BINDING_OFFSET:
2358 case GL_VERTEX_BINDING_STRIDE:
2359 if (context->getClientVersion() < ES_3_1)
2360 {
2361 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002362 InvalidEnum()
2363 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002364 return false;
2365 }
2366 if (index >= caps.maxVertexAttribBindings)
2367 {
2368 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002369 InvalidValue()
2370 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002371 return false;
2372 }
2373 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002374 case GL_SAMPLE_MASK_VALUE:
2375 if (context->getClientVersion() < ES_3_1)
2376 {
2377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2378 return false;
2379 }
2380 if (index >= caps.maxSampleMaskWords)
2381 {
2382 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2383 return false;
2384 }
2385 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002386 case GL_IMAGE_BINDING_NAME:
2387 case GL_IMAGE_BINDING_LEVEL:
2388 case GL_IMAGE_BINDING_LAYERED:
2389 case GL_IMAGE_BINDING_LAYER:
2390 case GL_IMAGE_BINDING_ACCESS:
2391 case GL_IMAGE_BINDING_FORMAT:
2392 if (context->getClientVersion() < ES_3_1)
2393 {
2394 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2395 return false;
2396 }
2397 if (index >= caps.maxImageUnits)
2398 {
2399 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2400 return false;
2401 }
2402 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002403 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002404 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002405 return false;
2406 }
2407
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002408 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002409 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002410 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002411 }
2412
2413 return true;
2414}
2415
2416bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2417{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002418 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002419 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002420 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002421 return false;
2422 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002423 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002424}
2425
Geoff Langcf255ea2016-10-20 11:39:09 -07002426bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2427 GLenum target,
2428 GLuint index,
2429 GLsizei bufSize,
2430 GLsizei *length,
2431 GLint *data)
2432{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002433 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002434 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002435 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002436 return false;
2437 }
2438
2439 if (!ValidateRobustEntryPoint(context, bufSize))
2440 {
2441 return false;
2442 }
2443
2444 if (!ValidateIndexedStateQuery(context, target, index, length))
2445 {
2446 return false;
2447 }
2448
2449 if (!ValidateRobustBufferSize(context, bufSize, *length))
2450 {
2451 return false;
2452 }
2453
2454 return true;
2455}
2456
Martin Radev66fb8202016-07-28 11:45:20 +03002457bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2458{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002459 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002460 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002461 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002462 return false;
2463 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002464 return ValidateIndexedStateQuery(context, target, index, nullptr);
2465}
2466
2467bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2468 GLenum target,
2469 GLuint index,
2470 GLsizei bufSize,
2471 GLsizei *length,
2472 GLint64 *data)
2473{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002474 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002475 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002477 return false;
2478 }
2479
2480 if (!ValidateRobustEntryPoint(context, bufSize))
2481 {
2482 return false;
2483 }
2484
2485 if (!ValidateIndexedStateQuery(context, target, index, length))
2486 {
2487 return false;
2488 }
2489
2490 if (!ValidateRobustBufferSize(context, bufSize, *length))
2491 {
2492 return false;
2493 }
2494
2495 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002496}
2497
Jamie Madillb0817d12016-11-01 15:48:31 -04002498bool ValidateCopyBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002499 BufferBinding readTarget,
2500 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002501 GLintptr readOffset,
2502 GLintptr writeOffset,
2503 GLsizeiptr size)
2504{
2505 if (context->getClientMajorVersion() < 3)
2506 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002508 return false;
2509 }
2510
Corentin Walleze4477002017-12-01 14:39:58 -05002511 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002514 return false;
2515 }
2516
2517 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2518 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2519
2520 if (!readBuffer || !writeBuffer)
2521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002523 return false;
2524 }
2525
2526 // Verify that readBuffer and writeBuffer are not currently mapped
2527 if (readBuffer->isMapped() || writeBuffer->isMapped())
2528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidOperation()
2530 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002531 return false;
2532 }
2533
Jamie Madilld2f0c742016-11-02 10:34:41 -04002534 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2535 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2536 CheckedNumeric<GLintptr> checkedSize(size);
2537
2538 auto checkedReadSum = checkedReadOffset + checkedSize;
2539 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2540
2541 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2542 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2543 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002546 return false;
2547 }
2548
Jamie Madilld2f0c742016-11-02 10:34:41 -04002549 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002551 context->handleError(InvalidValue()
2552 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002553 return false;
2554 }
2555
Jamie Madilld2f0c742016-11-02 10:34:41 -04002556 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2557 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002560 return false;
2561 }
2562
2563 if (readBuffer == writeBuffer)
2564 {
2565 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2566 if (!checkedOffsetDiff.IsValid())
2567 {
2568 // This shold not be possible.
2569 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002570 context->handleError(InvalidValue()
2571 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002572 return false;
2573 }
2574
2575 if (checkedOffsetDiff.ValueOrDie() < size)
2576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002577 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002578 return false;
2579 }
2580 }
2581
Jamie Madillb0817d12016-11-01 15:48:31 -04002582 return true;
2583}
2584
Geoff Langc339c4e2016-11-29 10:37:36 -05002585bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2586{
2587 if (context->getClientMajorVersion() < 3)
2588 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002590 return false;
2591 }
2592
2593 switch (name)
2594 {
2595 case GL_EXTENSIONS:
2596 if (index >= context->getExtensionStringCount())
2597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidValue()
2599 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002600 return false;
2601 }
2602 break;
2603
2604 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2605 if (!context->getExtensions().requestExtension)
2606 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002607 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002608 return false;
2609 }
2610 if (index >= context->getRequestableExtensionStringCount())
2611 {
2612 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002613 InvalidValue()
2614 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002615 return false;
2616 }
2617 break;
2618
2619 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002620 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002621 return false;
2622 }
2623
2624 return true;
2625}
2626
Jamie Madille8fb6402017-02-14 17:56:40 -05002627bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2628 GLenum target,
2629 GLsizei samples,
2630 GLenum internalformat,
2631 GLsizei width,
2632 GLsizei height)
2633{
2634 if (context->getClientMajorVersion() < 3)
2635 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002637 return false;
2638 }
2639
2640 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2641 height))
2642 {
2643 return false;
2644 }
2645
2646 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
Yunchao Hec0810202018-01-22 09:48:48 +08002647 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2648 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002649 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002650 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002651 {
Yunchao Hec0810202018-01-22 09:48:48 +08002652 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2653 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2654 {
2655 context->handleError(InvalidOperation());
2656 return false;
2657 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002658 }
2659
2660 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2661 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2662 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2663 {
2664 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002665 InvalidOperation()
2666 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002667 return false;
2668 }
2669
2670 return true;
2671}
2672
Geoff Langaa086d62017-03-23 16:47:21 -04002673bool ValidateVertexAttribIPointer(ValidationContext *context,
2674 GLuint index,
2675 GLint size,
2676 GLenum type,
2677 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002678 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002679{
2680 if (context->getClientMajorVersion() < 3)
2681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002683 return false;
2684 }
2685
Shao80957d92017-02-20 21:25:59 +08002686 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002687 {
Geoff Langaa086d62017-03-23 16:47:21 -04002688 return false;
2689 }
2690
Geoff Langaa086d62017-03-23 16:47:21 -04002691 if (stride < 0)
2692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002693 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002694 return false;
2695 }
2696
Shao80957d92017-02-20 21:25:59 +08002697 const Caps &caps = context->getCaps();
2698 if (context->getClientVersion() >= ES_3_1)
2699 {
2700 if (stride > caps.maxVertexAttribStride)
2701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002702 context->handleError(InvalidValue()
2703 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002704 return false;
2705 }
2706
2707 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2708 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2709 // validation should be inherited.
2710 if (index >= caps.maxVertexAttribBindings)
2711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002712 context->handleError(InvalidValue()
2713 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002714 return false;
2715 }
2716 }
2717
Geoff Langaa086d62017-03-23 16:47:21 -04002718 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2719 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2720 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2721 // and the pointer argument is not NULL.
2722 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002723 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002725 context
2726 ->handleError(InvalidOperation()
2727 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002728 return false;
2729 }
2730
Geoff Lang2d62ab72017-03-23 16:54:40 -04002731 if (context->getExtensions().webglCompatibility)
2732 {
2733 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2734 {
2735 return false;
2736 }
2737 }
2738
Geoff Langaa086d62017-03-23 16:47:21 -04002739 return true;
2740}
2741
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002742bool ValidateGetSynciv(Context *context,
2743 GLsync sync,
2744 GLenum pname,
2745 GLsizei bufSize,
2746 GLsizei *length,
2747 GLint *values)
2748{
2749 if (context->getClientMajorVersion() < 3)
2750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002751 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002752 return false;
2753 }
2754
2755 if (bufSize < 0)
2756 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002757 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002758 return false;
2759 }
2760
Jamie Madill70b5bb02017-08-28 13:32:37 -04002761 Sync *syncObject = context->getSync(sync);
2762 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002764 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002765 return false;
2766 }
2767
2768 switch (pname)
2769 {
2770 case GL_OBJECT_TYPE:
2771 case GL_SYNC_CONDITION:
2772 case GL_SYNC_FLAGS:
2773 case GL_SYNC_STATUS:
2774 break;
2775
2776 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002777 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002778 return false;
2779 }
2780
2781 return true;
2782}
2783
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002784bool ValidateDrawElementsInstanced(ValidationContext *context,
2785 GLenum mode,
2786 GLsizei count,
2787 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002788 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002789 GLsizei instanceCount)
2790{
2791 if (context->getClientMajorVersion() < 3)
2792 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002794 return false;
2795 }
2796
2797 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2798}
2799
Martin Radev137032d2017-07-13 10:11:12 +03002800bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2801 GLenum target,
2802 GLenum attachment,
2803 GLuint texture,
2804 GLint level,
2805 GLint baseViewIndex,
2806 GLsizei numViews)
2807{
2808
2809 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2810 numViews))
2811 {
2812 return false;
2813 }
2814
Martin Radev137032d2017-07-13 10:11:12 +03002815 if (texture != 0)
2816 {
Martin Radev14b21262017-08-25 13:54:37 +03002817 if (baseViewIndex < 0)
2818 {
2819 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2820 return false;
2821 }
2822
Martin Radev137032d2017-07-13 10:11:12 +03002823 Texture *tex = context->getTexture(texture);
2824 ASSERT(tex);
2825
2826 switch (tex->getTarget())
2827 {
2828 case GL_TEXTURE_2D_ARRAY:
2829 {
2830 const Caps &caps = context->getCaps();
2831 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2832 {
2833 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2834 "greater than "
2835 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2836 return false;
2837 }
2838 }
2839 break;
2840 default:
2841 context->handleError(InvalidOperation()
2842 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2843 return false;
2844 }
2845
2846 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2847 {
2848 return false;
2849 }
2850 }
2851
2852 return true;
2853}
2854
2855bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2856 GLenum target,
2857 GLenum attachment,
2858 GLuint texture,
2859 GLint level,
2860 GLsizei numViews,
2861 const GLint *viewportOffsets)
2862{
2863 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2864 numViews))
2865 {
2866 return false;
2867 }
2868
Martin Radev137032d2017-07-13 10:11:12 +03002869 if (texture != 0)
2870 {
Martin Radev14b21262017-08-25 13:54:37 +03002871 const GLsizei numViewportOffsetValues = numViews * 2;
2872 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2873 {
2874 if (viewportOffsets[i] < 0)
2875 {
2876 context->handleError(InvalidValue()
2877 << "viewportOffsets cannot contain negative values.");
2878 return false;
2879 }
2880 }
2881
Martin Radev137032d2017-07-13 10:11:12 +03002882 Texture *tex = context->getTexture(texture);
2883 ASSERT(tex);
2884
2885 switch (tex->getTarget())
2886 {
2887 case GL_TEXTURE_2D:
2888 break;
2889 default:
2890 context->handleError(InvalidOperation()
2891 << "Texture's target must be GL_TEXTURE_2D.");
2892 return false;
2893 }
2894
2895 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2896 {
2897 return false;
2898 }
2899 }
2900
2901 return true;
2902}
2903
Jamie Madillff325f12017-08-26 15:06:05 -04002904bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2905{
2906 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2907}
2908
2909bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2910{
2911 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2912}
2913
2914bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2915{
2916 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2917}
2918
2919bool ValidateUniform4ui(Context *context,
2920 GLint location,
2921 GLuint v0,
2922 GLuint v1,
2923 GLuint v2,
2924 GLuint v3)
2925{
2926 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2927}
2928
2929bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2930{
2931 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2932}
2933
2934bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2935{
2936 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2937}
2938
2939bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2940{
2941 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2942}
2943
2944bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2945{
2946 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2947}
2948
Jamie Madillf0e04492017-08-26 15:28:42 -04002949bool ValidateIsQuery(Context *context, GLuint id)
2950{
2951 if (context->getClientMajorVersion() < 3)
2952 {
2953 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2954 return false;
2955 }
2956
2957 return true;
2958}
2959
Jamie Madillc8c95812017-08-26 18:40:09 -04002960bool ValidateUniformMatrix2x3fv(Context *context,
2961 GLint location,
2962 GLsizei count,
2963 GLboolean transpose,
2964 const GLfloat *value)
2965{
2966 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2967}
2968
2969bool ValidateUniformMatrix3x2fv(Context *context,
2970 GLint location,
2971 GLsizei count,
2972 GLboolean transpose,
2973 const GLfloat *value)
2974{
2975 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2976}
2977
2978bool ValidateUniformMatrix2x4fv(Context *context,
2979 GLint location,
2980 GLsizei count,
2981 GLboolean transpose,
2982 const GLfloat *value)
2983{
2984 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2985}
2986
2987bool ValidateUniformMatrix4x2fv(Context *context,
2988 GLint location,
2989 GLsizei count,
2990 GLboolean transpose,
2991 const GLfloat *value)
2992{
2993 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2994}
2995
2996bool ValidateUniformMatrix3x4fv(Context *context,
2997 GLint location,
2998 GLsizei count,
2999 GLboolean transpose,
3000 const GLfloat *value)
3001{
3002 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3003}
3004
3005bool ValidateUniformMatrix4x3fv(Context *context,
3006 GLint location,
3007 GLsizei count,
3008 GLboolean transpose,
3009 const GLfloat *value)
3010{
3011 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3012}
3013
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003014bool ValidateEndTransformFeedback(Context *context)
3015{
3016 if (context->getClientMajorVersion() < 3)
3017 {
3018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3019 return false;
3020 }
3021
3022 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3023 ASSERT(transformFeedback != nullptr);
3024
3025 if (!transformFeedback->isActive())
3026 {
3027 context->handleError(InvalidOperation());
3028 return false;
3029 }
3030
3031 return true;
3032}
3033
3034bool ValidateTransformFeedbackVaryings(Context *context,
3035 GLuint program,
3036 GLsizei count,
3037 const GLchar *const *varyings,
3038 GLenum bufferMode)
3039{
3040 if (context->getClientMajorVersion() < 3)
3041 {
3042 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3043 return false;
3044 }
3045
3046 if (count < 0)
3047 {
3048 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3049 return false;
3050 }
3051
3052 switch (bufferMode)
3053 {
3054 case GL_INTERLEAVED_ATTRIBS:
3055 break;
3056 case GL_SEPARATE_ATTRIBS:
3057 {
3058 const Caps &caps = context->getCaps();
3059 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3060 {
3061 context->handleError(InvalidValue());
3062 return false;
3063 }
3064 break;
3065 }
3066 default:
3067 context->handleError(InvalidEnum());
3068 return false;
3069 }
3070
3071 Program *programObject = GetValidProgram(context, program);
3072 if (!programObject)
3073 {
3074 return false;
3075 }
3076
3077 return true;
3078}
3079
3080bool ValidateGetTransformFeedbackVarying(Context *context,
3081 GLuint program,
3082 GLuint index,
3083 GLsizei bufSize,
3084 GLsizei *length,
3085 GLsizei *size,
3086 GLenum *type,
3087 GLchar *name)
3088{
3089 if (context->getClientMajorVersion() < 3)
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3092 return false;
3093 }
3094
3095 if (bufSize < 0)
3096 {
3097 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3098 return false;
3099 }
3100
3101 Program *programObject = GetValidProgram(context, program);
3102 if (!programObject)
3103 {
3104 return false;
3105 }
3106
3107 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3108 {
3109 context->handleError(InvalidValue());
3110 return false;
3111 }
3112
3113 return true;
3114}
3115
3116bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3117{
3118 if (context->getClientMajorVersion() < 3)
3119 {
3120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3121 return false;
3122 }
3123
3124 switch (target)
3125 {
3126 case GL_TRANSFORM_FEEDBACK:
3127 {
3128 // Cannot bind a transform feedback object if the current one is started and not
3129 // paused (3.0.2 pg 85 section 2.14.1)
3130 TransformFeedback *curTransformFeedback =
3131 context->getGLState().getCurrentTransformFeedback();
3132 if (curTransformFeedback && curTransformFeedback->isActive() &&
3133 !curTransformFeedback->isPaused())
3134 {
3135 context->handleError(InvalidOperation());
3136 return false;
3137 }
3138
3139 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3140 // 2.14.1)
3141 if (!context->isTransformFeedbackGenerated(id))
3142 {
3143 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3144 return false;
3145 }
3146 }
3147 break;
3148
3149 default:
3150 context->handleError(InvalidEnum());
3151 return false;
3152 }
3153
3154 return true;
3155}
3156
3157bool ValidateIsTransformFeedback(Context *context, GLuint id)
3158{
3159 if (context->getClientMajorVersion() < 3)
3160 {
3161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3162 return false;
3163 }
3164
3165 return true;
3166}
3167
3168bool ValidatePauseTransformFeedback(Context *context)
3169{
3170 if (context->getClientMajorVersion() < 3)
3171 {
3172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3173 return false;
3174 }
3175
3176 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3177 ASSERT(transformFeedback != nullptr);
3178
3179 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3180 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3181 {
3182 context->handleError(InvalidOperation());
3183 return false;
3184 }
3185
3186 return true;
3187}
3188
3189bool ValidateResumeTransformFeedback(Context *context)
3190{
3191 if (context->getClientMajorVersion() < 3)
3192 {
3193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3194 return false;
3195 }
3196
3197 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3198 ASSERT(transformFeedback != nullptr);
3199
3200 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3201 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3202 {
3203 context->handleError(InvalidOperation());
3204 return false;
3205 }
3206
3207 return true;
3208}
3209
Jamie Madill12e957f2017-08-26 21:42:26 -04003210bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3211{
3212 if (context->getClientMajorVersion() < 3)
3213 {
3214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3215 return false;
3216 }
3217
3218 return ValidateVertexAttribIndex(context, index);
3219}
3220
3221bool ValidateVertexAttribI4ui(Context *context,
3222 GLuint index,
3223 GLuint x,
3224 GLuint y,
3225 GLuint z,
3226 GLuint w)
3227{
3228 if (context->getClientMajorVersion() < 3)
3229 {
3230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3231 return false;
3232 }
3233
3234 return ValidateVertexAttribIndex(context, index);
3235}
3236
3237bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3238{
3239 if (context->getClientMajorVersion() < 3)
3240 {
3241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3242 return false;
3243 }
3244
3245 return ValidateVertexAttribIndex(context, index);
3246}
3247
3248bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3249{
3250 if (context->getClientMajorVersion() < 3)
3251 {
3252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3253 return false;
3254 }
3255
3256 return ValidateVertexAttribIndex(context, index);
3257}
3258
3259bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3260{
3261 if (context->getClientMajorVersion() < 3)
3262 {
3263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3264 return false;
3265 }
3266
3267 Program *programObject = GetValidProgram(context, program);
3268 if (!programObject)
3269 {
3270 return false;
3271 }
3272
3273 if (!programObject->isLinked())
3274 {
3275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3276 return false;
3277 }
3278
3279 return true;
3280}
3281
3282bool ValidateGetUniformIndices(Context *context,
3283 GLuint program,
3284 GLsizei uniformCount,
3285 const GLchar *const *uniformNames,
3286 GLuint *uniformIndices)
3287{
3288 if (context->getClientMajorVersion() < 3)
3289 {
3290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3291 return false;
3292 }
3293
3294 if (uniformCount < 0)
3295 {
3296 context->handleError(InvalidValue());
3297 return false;
3298 }
3299
3300 Program *programObject = GetValidProgram(context, program);
3301 if (!programObject)
3302 {
3303 return false;
3304 }
3305
3306 return true;
3307}
3308
3309bool ValidateGetActiveUniformsiv(Context *context,
3310 GLuint program,
3311 GLsizei uniformCount,
3312 const GLuint *uniformIndices,
3313 GLenum pname,
3314 GLint *params)
3315{
3316 if (context->getClientMajorVersion() < 3)
3317 {
3318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3319 return false;
3320 }
3321
3322 if (uniformCount < 0)
3323 {
3324 context->handleError(InvalidValue());
3325 return false;
3326 }
3327
3328 Program *programObject = GetValidProgram(context, program);
3329 if (!programObject)
3330 {
3331 return false;
3332 }
3333
3334 switch (pname)
3335 {
3336 case GL_UNIFORM_TYPE:
3337 case GL_UNIFORM_SIZE:
3338 case GL_UNIFORM_NAME_LENGTH:
3339 case GL_UNIFORM_BLOCK_INDEX:
3340 case GL_UNIFORM_OFFSET:
3341 case GL_UNIFORM_ARRAY_STRIDE:
3342 case GL_UNIFORM_MATRIX_STRIDE:
3343 case GL_UNIFORM_IS_ROW_MAJOR:
3344 break;
3345
3346 default:
3347 context->handleError(InvalidEnum());
3348 return false;
3349 }
3350
3351 if (uniformCount > programObject->getActiveUniformCount())
3352 {
3353 context->handleError(InvalidValue());
3354 return false;
3355 }
3356
3357 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3358 {
3359 const GLuint index = uniformIndices[uniformId];
3360
3361 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3362 {
3363 context->handleError(InvalidValue());
3364 return false;
3365 }
3366 }
3367
3368 return true;
3369}
3370
3371bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3372{
3373 if (context->getClientMajorVersion() < 3)
3374 {
3375 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3376 return false;
3377 }
3378
3379 Program *programObject = GetValidProgram(context, program);
3380 if (!programObject)
3381 {
3382 return false;
3383 }
3384
3385 return true;
3386}
3387
3388bool ValidateGetActiveUniformBlockiv(Context *context,
3389 GLuint program,
3390 GLuint uniformBlockIndex,
3391 GLenum pname,
3392 GLint *params)
3393{
3394 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3395}
3396
3397bool ValidateGetActiveUniformBlockName(Context *context,
3398 GLuint program,
3399 GLuint uniformBlockIndex,
3400 GLsizei bufSize,
3401 GLsizei *length,
3402 GLchar *uniformBlockName)
3403{
3404 if (context->getClientMajorVersion() < 3)
3405 {
3406 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3407 return false;
3408 }
3409
3410 Program *programObject = GetValidProgram(context, program);
3411 if (!programObject)
3412 {
3413 return false;
3414 }
3415
3416 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3417 {
3418 context->handleError(InvalidValue());
3419 return false;
3420 }
3421
3422 return true;
3423}
3424
3425bool ValidateUniformBlockBinding(Context *context,
3426 GLuint program,
3427 GLuint uniformBlockIndex,
3428 GLuint uniformBlockBinding)
3429{
3430 if (context->getClientMajorVersion() < 3)
3431 {
3432 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3433 return false;
3434 }
3435
3436 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3437 {
3438 context->handleError(InvalidValue());
3439 return false;
3440 }
3441
3442 Program *programObject = GetValidProgram(context, program);
3443 if (!programObject)
3444 {
3445 return false;
3446 }
3447
3448 // if never linked, there won't be any uniform blocks
3449 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3450 {
3451 context->handleError(InvalidValue());
3452 return false;
3453 }
3454
3455 return true;
3456}
3457
3458bool ValidateDrawArraysInstanced(Context *context,
3459 GLenum mode,
3460 GLint first,
3461 GLsizei count,
3462 GLsizei primcount)
3463{
3464 if (context->getClientMajorVersion() < 3)
3465 {
3466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3467 return false;
3468 }
3469
3470 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3471}
3472
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003473bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3474{
3475 if (context->getClientMajorVersion() < 3)
3476 {
3477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3478 return false;
3479 }
3480
3481 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3482 {
3483 context->handleError(InvalidEnum());
3484 return false;
3485 }
3486
3487 if (flags != 0)
3488 {
3489 context->handleError(InvalidValue());
3490 return false;
3491 }
3492
3493 return true;
3494}
3495
3496bool ValidateIsSync(Context *context, GLsync sync)
3497{
3498 if (context->getClientMajorVersion() < 3)
3499 {
3500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3501 return false;
3502 }
3503
3504 return true;
3505}
3506
3507bool ValidateDeleteSync(Context *context, GLsync sync)
3508{
3509 if (context->getClientMajorVersion() < 3)
3510 {
3511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3512 return false;
3513 }
3514
Jamie Madill70b5bb02017-08-28 13:32:37 -04003515 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003516 {
3517 context->handleError(InvalidValue());
3518 return false;
3519 }
3520
3521 return true;
3522}
3523
3524bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3525{
3526 if (context->getClientMajorVersion() < 3)
3527 {
3528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3529 return false;
3530 }
3531
3532 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3533 {
3534 context->handleError(InvalidValue());
3535 return false;
3536 }
3537
Jamie Madill70b5bb02017-08-28 13:32:37 -04003538 Sync *clientWaitSync = context->getSync(sync);
3539 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003540 {
3541 context->handleError(InvalidValue());
3542 return false;
3543 }
3544
3545 return true;
3546}
3547
3548bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3549{
3550 if (context->getClientMajorVersion() < 3)
3551 {
3552 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3553 return false;
3554 }
3555
3556 if (flags != 0)
3557 {
3558 context->handleError(InvalidValue());
3559 return false;
3560 }
3561
3562 if (timeout != GL_TIMEOUT_IGNORED)
3563 {
3564 context->handleError(InvalidValue());
3565 return false;
3566 }
3567
Jamie Madill70b5bb02017-08-28 13:32:37 -04003568 Sync *waitSync = context->getSync(sync);
3569 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003570 {
3571 context->handleError(InvalidValue());
3572 return false;
3573 }
3574
3575 return true;
3576}
3577
3578bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3579{
3580 if (context->getClientMajorVersion() < 3)
3581 {
3582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3583 return false;
3584 }
3585
3586 GLenum nativeType = GL_NONE;
3587 unsigned int numParams = 0;
3588 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3589 {
3590 return false;
3591 }
3592
3593 return true;
3594}
3595
Jamie Madill3ef140a2017-08-26 23:11:21 -04003596bool ValidateIsSampler(Context *context, GLuint sampler)
3597{
3598 if (context->getClientMajorVersion() < 3)
3599 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003600 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003601 return false;
3602 }
3603
3604 return true;
3605}
3606
3607bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3608{
3609 if (context->getClientMajorVersion() < 3)
3610 {
3611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3612 return false;
3613 }
3614
3615 if (sampler != 0 && !context->isSampler(sampler))
3616 {
3617 context->handleError(InvalidOperation());
3618 return false;
3619 }
3620
3621 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3622 {
3623 context->handleError(InvalidValue());
3624 return false;
3625 }
3626
3627 return true;
3628}
3629
3630bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3631{
3632 if (context->getClientMajorVersion() < 3)
3633 {
3634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3635 return false;
3636 }
3637
3638 return ValidateVertexAttribIndex(context, index);
3639}
3640
3641bool ValidateTexStorage2D(Context *context,
3642 GLenum target,
3643 GLsizei levels,
3644 GLenum internalformat,
3645 GLsizei width,
3646 GLsizei height)
3647{
3648 if (context->getClientMajorVersion() < 3)
3649 {
3650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3651 return false;
3652 }
3653
3654 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3655 1))
3656 {
3657 return false;
3658 }
3659
3660 return true;
3661}
3662
3663bool ValidateTexStorage3D(Context *context,
3664 GLenum target,
3665 GLsizei levels,
3666 GLenum internalformat,
3667 GLsizei width,
3668 GLsizei height,
3669 GLsizei depth)
3670{
3671 if (context->getClientMajorVersion() < 3)
3672 {
3673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3674 return false;
3675 }
3676
3677 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3678 depth))
3679 {
3680 return false;
3681 }
3682
3683 return true;
3684}
3685
Jamie Madill9696d072017-08-26 23:19:57 -04003686bool ValidateGetBufferParameteri64v(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003687 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003688 GLenum pname,
3689 GLint64 *params)
3690{
3691 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3692}
3693
3694bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3695{
3696 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3697}
3698
3699bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3700{
3701 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3702}
3703
3704bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3705{
3706 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3707}
3708
3709bool ValidateSamplerParameterfv(Context *context,
3710 GLuint sampler,
3711 GLenum pname,
3712 const GLfloat *params)
3713{
3714 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3715}
3716
3717bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3718{
3719 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3720}
3721
3722bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3723{
3724 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3725}
3726
3727bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3728{
3729 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3730}
3731
3732bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3733{
3734 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3735}
3736
3737bool ValidateGetInternalformativ(Context *context,
3738 GLenum target,
3739 GLenum internalformat,
3740 GLenum pname,
3741 GLsizei bufSize,
3742 GLint *params)
3743{
3744 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3745 nullptr);
3746}
3747
Jamie Madillc29968b2016-01-20 11:17:23 -05003748} // namespace gl