blob: 25a64330285f70508d5a5105bcf4069b4d7fcb29 [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
532 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
533 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400534 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500535}
536
Geoff Lang5d601382014-07-22 15:14:06 -0400537struct EffectiveInternalFormatInfo
538{
Jamie Madill76648fe2016-10-05 17:01:41 -0400539 GLenum effectiveFormat;
540 GLenum destFormat;
541 GLuint minRedBits;
542 GLuint maxRedBits;
543 GLuint minGreenBits;
544 GLuint maxGreenBits;
545 GLuint minBlueBits;
546 GLuint maxBlueBits;
547 GLuint minAlphaBits;
548 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400549};
550
Jamie Madill76648fe2016-10-05 17:01:41 -0400551static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
552 GLenum targetFormat,
553 const EffectiveInternalFormatInfo *list,
554 size_t size,
555 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400556{
Jamie Madill76648fe2016-10-05 17:01:41 -0400557 for (size_t curFormat = 0; curFormat < size; ++curFormat)
558 {
559 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
560 if ((formatInfo.destFormat == targetFormat) &&
561 (formatInfo.minRedBits <= srcFormat.redBits &&
562 formatInfo.maxRedBits >= srcFormat.redBits) &&
563 (formatInfo.minGreenBits <= srcFormat.greenBits &&
564 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
565 (formatInfo.minBlueBits <= srcFormat.blueBits &&
566 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
567 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
568 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
569 {
570 *outEffectiveFormat = formatInfo.effectiveFormat;
571 return true;
572 }
573 }
Geoff Lang5d601382014-07-22 15:14:06 -0400574
Jamie Madill76648fe2016-10-05 17:01:41 -0400575 *outEffectiveFormat = GL_NONE;
576 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400577}
578
Jamie Madill76648fe2016-10-05 17:01:41 -0400579bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
580 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400581{
Jamie Madill76648fe2016-10-05 17:01:41 -0400582 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
583 // Effective internal format coresponding to destination internal format and linear source
584 // buffer component sizes.
585 // | Source channel min/max sizes |
586 // Effective Internal Format | N/A | R | G | B | A |
587 // clang-format off
588 constexpr EffectiveInternalFormatInfo list[] = {
589 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
590 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
591 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
592 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
593 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
594 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
595 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
596 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
597 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
598 };
599 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400600
Jamie Madill76648fe2016-10-05 17:01:41 -0400601 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
602}
Geoff Lang5d601382014-07-22 15:14:06 -0400603
Jamie Madill76648fe2016-10-05 17:01:41 -0400604bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
605 const InternalFormat &destFormat,
606 GLenum *outEffectiveFormat)
607{
608 constexpr GLuint umax = UINT_MAX;
609
610 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
611 // Effective internal format coresponding to destination internal format andlinear source buffer
612 // component sizes.
613 // | Source channel min/max sizes |
614 // Effective Internal Format | Dest Format | R | G | B | A |
615 // clang-format off
616 constexpr EffectiveInternalFormatInfo list[] = {
617 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
618 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
619 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
620 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
621 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
622 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
623 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
624 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
625 };
626 // clang-format on
627
628 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
629 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400630}
631
He Yunchaoced53ae2016-11-29 15:00:51 +0800632static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
633 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400634 GLenum *outEffectiveFormat)
635{
Geoff Langca271392017-04-05 12:30:00 -0400636 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400637 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400638 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400639 }
640 else
641 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400642 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400643 }
Geoff Lang5d601382014-07-22 15:14:06 -0400644}
645
Corentin Wallez76287682016-04-25 09:23:38 -0400646static bool EqualOrFirstZero(GLuint first, GLuint second)
647{
648 return first == 0 || first == second;
649}
650
Geoff Langca271392017-04-05 12:30:00 -0400651static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
652 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400653 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400654{
Jamie Madill21b786b2016-11-01 17:41:31 -0400655 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400656 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400657 return false;
658 }
Geoff Lang5d601382014-07-22 15:14:06 -0400659
Jamie Madill21b786b2016-11-01 17:41:31 -0400660 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
661 // must both be signed, unsigned, or fixed point and both source and destinations
662 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
663 // conversion between fixed and floating point.
664
665 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
666 (framebufferFormatInfo.colorEncoding == GL_SRGB))
667 {
668 return false;
669 }
670
671 if (((textureFormatInfo.componentType == GL_INT) !=
672 (framebufferFormatInfo.componentType == GL_INT)) ||
673 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
674 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
675 {
676 return false;
677 }
678
679 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
680 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
681 textureFormatInfo.componentType == GL_FLOAT) &&
682 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
683 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
684 framebufferFormatInfo.componentType == GL_FLOAT))
685 {
686 return false;
687 }
688
689 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
690 // The effective internal format of the source buffer is determined with the following rules
691 // applied in order:
692 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
693 // format then the effective internal format is the source buffer's sized internal format.
694 // * If the source buffer is a texture that was created with an unsized base internal format,
695 // then the effective internal format is the source image array's effective internal
696 // format, as specified by table 3.12, which is determined from the <format> and <type>
697 // that were used when the source image array was specified by TexImage*.
698 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
699 // where Destination Internal Format matches internalformat and where the [source channel
700 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
701 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
702 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800703 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400704 if (readBufferHandle != 0)
705 {
706 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
707 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400708 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400709 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400710 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400711 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400712 else
Geoff Lang5d601382014-07-22 15:14:06 -0400713 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400714 // Renderbuffers cannot be created with an unsized internal format, so this must be an
715 // unsized-format texture. We can use the same table we use when creating textures to
716 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400717 sourceEffectiveFormat =
718 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400719 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400720 }
721 else
722 {
723 // The effective internal format must be derived from the source framebuffer's channel
724 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
725 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400726 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400727 GLenum effectiveFormat;
728 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
729 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400730 {
Geoff Langca271392017-04-05 12:30:00 -0400731 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400732 }
733 else
734 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400735 return false;
736 }
737 }
738 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
739 {
740 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400741 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400742 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
743 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
744 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
745 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
746 {
Geoff Langca271392017-04-05 12:30:00 -0400747 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400748 }
749 else
750 {
751 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400752 }
753 }
754 else
755 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400756 UNREACHABLE();
757 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400758 }
Geoff Lang5d601382014-07-22 15:14:06 -0400759 }
760
Geoff Langca271392017-04-05 12:30:00 -0400761 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400762 {
763 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
764 // sized, component sizes of the source and destination formats must exactly match if the
765 // destination format exists.
766 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
767 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
768 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
769 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
770 {
771 return false;
772 }
773 }
774
775 return true; // A conversion function exists, and no rule in the specification has precluded
776 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400777}
778
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500779bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
780 GLenum target,
781 GLint level,
782 GLenum internalformat,
783 bool isSubImage,
784 GLint xoffset,
785 GLint yoffset,
786 GLint zoffset,
787 GLint x,
788 GLint y,
789 GLsizei width,
790 GLsizei height,
791 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400793 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400794 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400795 xoffset, yoffset, zoffset, x, y, width, height, border,
796 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400797 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400798 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400799 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801
Jamie Madill51f40ec2016-06-15 14:06:00 -0400802 const auto &state = context->getGLState();
803 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
804 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400805
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400806 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500808 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400809 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400810 }
811
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400812 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500814 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400815 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400816 }
817
Jamie Madill0c8abca2016-07-22 20:21:26 -0400818 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819
820 if (isSubImage)
821 {
Geoff Langca271392017-04-05 12:30:00 -0400822 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500823 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500825 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400826 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 }
828 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400829 else
830 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400831 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400832 const InternalFormat &framebufferFormat = *source->getFormat().info;
833 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400834 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500836 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400838 }
839 }
840
Geoff Lang784a8fd2013-09-24 12:33:16 -0400841 // If width or height is zero, it is a no-op. Return false without setting an error.
842 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843}
844
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500845bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
846 GLenum target,
847 GLint level,
848 GLenum internalformat,
849 bool isSubImage,
850 GLint xoffset,
851 GLint yoffset,
852 GLint zoffset,
853 GLint x,
854 GLint y,
855 GLsizei width,
856 GLsizei height,
857 GLint border)
858{
859 if (!ValidTexture2DDestinationTarget(context, target))
860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500861 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500862 return false;
863 }
864
865 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
866 xoffset, yoffset, zoffset, x, y, width, height,
867 border);
868}
869
870bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
871 GLenum target,
872 GLint level,
873 GLenum internalformat,
874 bool isSubImage,
875 GLint xoffset,
876 GLint yoffset,
877 GLint zoffset,
878 GLint x,
879 GLint y,
880 GLsizei width,
881 GLsizei height,
882 GLint border)
883{
884 if (!ValidTexture3DDestinationTarget(context, target))
885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500886 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500887 return false;
888 }
889
890 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
891 xoffset, yoffset, zoffset, x, y, width, height,
892 border);
893}
894
895bool ValidateES3TexStorageParametersBase(Context *context,
896 GLenum target,
897 GLsizei levels,
898 GLenum internalformat,
899 GLsizei width,
900 GLsizei height,
901 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902{
903 if (width < 1 || height < 1 || depth < 1 || levels < 1)
904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500905 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400906 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 }
908
Geoff Langb92c1332015-09-04 12:54:55 -0400909 GLsizei maxDim = std::max(width, height);
910 if (target != GL_TEXTURE_2D_ARRAY)
911 {
912 maxDim = std::max(maxDim, depth);
913 }
914
915 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500917 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400918 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 }
920
Geoff Langaae65a42014-05-26 12:43:44 -0400921 const gl::Caps &caps = context->getCaps();
922
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923 switch (target)
924 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800925 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 {
Geoff Langaae65a42014-05-26 12:43:44 -0400927 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
928 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500930 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 }
933 }
934 break;
935
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400936 case GL_TEXTURE_RECTANGLE_ANGLE:
937 {
938 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
939 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
940 {
941 context->handleError(InvalidValue());
942 return false;
943 }
944 }
945 break;
946
He Yunchaoced53ae2016-11-29 15:00:51 +0800947 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400949 if (width != height)
950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500951 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400952 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 }
954
Geoff Langaae65a42014-05-26 12:43:44 -0400955 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500957 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400958 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 }
960 }
961 break;
962
He Yunchaoced53ae2016-11-29 15:00:51 +0800963 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 {
Geoff Langaae65a42014-05-26 12:43:44 -0400965 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
966 static_cast<GLuint>(height) > caps.max3DTextureSize ||
967 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500969 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400970 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 }
972 }
973 break;
974
He Yunchaoced53ae2016-11-29 15:00:51 +0800975 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976 {
Geoff Langaae65a42014-05-26 12:43:44 -0400977 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
978 static_cast<GLuint>(height) > caps.max2DTextureSize ||
979 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500981 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 }
984 }
985 break;
986
He Yunchaoced53ae2016-11-29 15:00:51 +0800987 default:
988 UNREACHABLE();
989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 }
991
Geoff Lang691e58c2014-12-19 17:03:25 -0500992 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 if (!texture || texture->id() == 0)
994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500995 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400996 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997 }
998
Geoff Lang69cce582015-09-17 13:20:36 -0400999 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001001 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001002 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003 }
1004
Geoff Langca271392017-04-05 12:30:00 -04001005 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001006 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidEnum());
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 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001014 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001015 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 }
1017
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001018 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1019 {
1020 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1021 return false;
1022 }
1023
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 return true;
1025}
1026
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001027bool ValidateES3TexStorage2DParameters(Context *context,
1028 GLenum target,
1029 GLsizei levels,
1030 GLenum internalformat,
1031 GLsizei width,
1032 GLsizei height,
1033 GLsizei depth)
1034{
1035 if (!ValidTexture2DTarget(context, target))
1036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001037 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001038 return false;
1039 }
1040
1041 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1042 height, depth);
1043}
1044
1045bool ValidateES3TexStorage3DParameters(Context *context,
1046 GLenum target,
1047 GLsizei levels,
1048 GLenum internalformat,
1049 GLsizei width,
1050 GLsizei height,
1051 GLsizei depth)
1052{
1053 if (!ValidTexture3DTarget(context, target))
1054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001055 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001056 return false;
1057 }
1058
1059 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1060 height, depth);
1061}
1062
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001063bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1064{
Martin Radev1be913c2016-07-11 17:59:16 +03001065 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001066 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001068 return false;
1069 }
1070
1071 return ValidateBeginQueryBase(context, target, id);
1072}
1073
1074bool ValidateEndQuery(gl::Context *context, GLenum target)
1075{
Martin Radev1be913c2016-07-11 17:59:16 +03001076 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001077 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001079 return false;
1080 }
1081
1082 return ValidateEndQueryBase(context, target);
1083}
1084
1085bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1086{
Martin Radev1be913c2016-07-11 17:59:16 +03001087 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001088 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001090 return false;
1091 }
1092
Geoff Lang2186c382016-10-14 10:54:54 -04001093 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001094}
1095
1096bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1097{
Martin Radev1be913c2016-07-11 17:59:16 +03001098 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001099 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001101 return false;
1102 }
1103
Geoff Lang2186c382016-10-14 10:54:54 -04001104 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001105}
1106
He Yunchaoced53ae2016-11-29 15:00:51 +08001107bool ValidateFramebufferTextureLayer(Context *context,
1108 GLenum target,
1109 GLenum attachment,
1110 GLuint texture,
1111 GLint level,
1112 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001113{
Martin Radev1be913c2016-07-11 17:59:16 +03001114 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001115 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001117 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001118 }
1119
Jamie Madill55ec3b12014-07-03 10:38:57 -04001120 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1121 {
1122 return false;
1123 }
1124
1125 const gl::Caps &caps = context->getCaps();
1126 if (texture != 0)
1127 {
Geoff Lang23e02842017-10-17 13:24:09 -04001128 if (layer < 0)
1129 {
1130 context->handleError(InvalidValue());
1131 return false;
1132 }
1133
Jamie Madill55ec3b12014-07-03 10:38:57 -04001134 gl::Texture *tex = context->getTexture(texture);
1135 ASSERT(tex);
1136
1137 switch (tex->getTarget())
1138 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001139 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001140 {
1141 if (level > gl::log2(caps.max2DTextureSize))
1142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001143 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001145 }
1146
1147 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001149 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001150 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001151 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001152 }
1153 break;
1154
He Yunchaoced53ae2016-11-29 15:00:51 +08001155 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001156 {
1157 if (level > gl::log2(caps.max3DTextureSize))
1158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001159 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001160 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001161 }
1162
1163 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001165 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001167 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001168 }
1169 break;
1170
He Yunchaoced53ae2016-11-29 15:00:51 +08001171 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001172 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001173 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001174 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001175
Jamie Madilla3944d42016-07-22 22:13:26 -04001176 const auto &format = tex->getFormat(tex->getTarget(), level);
1177 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001179 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001180 return false;
1181 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001182 }
1183
1184 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001185}
1186
He Yunchaoced53ae2016-11-29 15:00:51 +08001187bool ValidateInvalidateFramebuffer(Context *context,
1188 GLenum target,
1189 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001190 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191{
Martin Radev1be913c2016-07-11 17:59:16 +03001192 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001195 return false;
1196 }
1197
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001198 bool defaultFramebuffer = false;
1199
1200 switch (target)
1201 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 case GL_DRAW_FRAMEBUFFER:
1203 case GL_FRAMEBUFFER:
1204 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1205 break;
1206 case GL_READ_FRAMEBUFFER:
1207 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1208 break;
1209 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001212 }
1213
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1215 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001216}
1217
Jamie Madill3ef140a2017-08-26 23:11:21 -04001218bool ValidateInvalidateSubFramebuffer(Context *context,
1219 GLenum target,
1220 GLsizei numAttachments,
1221 const GLenum *attachments,
1222 GLint x,
1223 GLint y,
1224 GLsizei width,
1225 GLsizei height)
1226{
1227 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1228}
1229
Jamie Madillc29968b2016-01-20 11:17:23 -05001230bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001231{
Martin Radev1be913c2016-07-11 17:59:16 +03001232 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001233 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001236 }
1237
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001238 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001240 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001241 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001242 }
1243
1244 return true;
1245}
1246
Olli Etuaho71dfb362016-03-10 14:04:27 +02001247bool ValidateDrawRangeElements(Context *context,
1248 GLenum mode,
1249 GLuint start,
1250 GLuint end,
1251 GLsizei count,
1252 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001253 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001254{
Martin Radev1be913c2016-07-11 17:59:16 +03001255 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001256 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001258 return false;
1259 }
1260
1261 if (end < start)
1262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001263 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001264 return false;
1265 }
1266
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001267 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001268 {
1269 return false;
1270 }
1271
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001272 // Use the parameter buffer to retrieve and cache the index range.
1273 const auto &params = context->getParams<HasIndexRange>();
1274 const auto &indexRangeOpt = params.getIndexRange();
1275 if (!indexRangeOpt.valid())
1276 {
1277 // Unexpected error.
1278 return false;
1279 }
1280
1281 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001282 {
1283 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001284 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001285 return false;
1286 }
1287 return true;
1288}
1289
He Yunchaoced53ae2016-11-29 15:00:51 +08001290bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001291{
Martin Radev1be913c2016-07-11 17:59:16 +03001292 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001293 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001295 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001296 }
1297
Jamie Madill78f41802014-08-25 15:47:55 -04001298 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001299}
1300
Jamie Madillb885e572015-02-03 16:16:04 -05001301bool ValidateReadBuffer(Context *context, GLenum src)
1302{
Martin Radev1be913c2016-07-11 17:59:16 +03001303 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001304 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001306 return false;
1307 }
1308
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001309 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001310
1311 if (readFBO == nullptr)
1312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001313 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001314 return false;
1315 }
1316
1317 if (src == GL_NONE)
1318 {
1319 return true;
1320 }
1321
Olli Etuaho84c9f592016-03-09 14:37:25 +02001322 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001325 return false;
1326 }
1327
1328 if (readFBO->id() == 0)
1329 {
1330 if (src != GL_BACK)
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(
1333 InvalidOperation()
1334 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001335 return false;
1336 }
1337 }
1338 else
1339 {
1340 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1341
1342 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001344 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001345 return false;
1346 }
1347 }
1348
1349 return true;
1350}
1351
Jamie Madill86af3d22015-07-21 15:14:07 -04001352bool ValidateCompressedTexImage3D(Context *context,
1353 GLenum target,
1354 GLint level,
1355 GLenum internalformat,
1356 GLsizei width,
1357 GLsizei height,
1358 GLsizei depth,
1359 GLint border,
1360 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001361 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001362{
Martin Radev1be913c2016-07-11 17:59:16 +03001363 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001364 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001365 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001366 return false;
1367 }
1368
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001369 if (!ValidTextureTarget(context, target))
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001372 return false;
1373 }
1374
Jamie Madille2e406c2016-06-02 13:04:10 -04001375 // Validate image size
1376 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001379 return false;
1380 }
1381
Geoff Langca271392017-04-05 12:30:00 -04001382 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001383 if (!formatInfo.compressed)
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001386 return false;
1387 }
1388
Jeff Gilbert48590352017-11-07 16:03:38 -08001389 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001390 if (blockSizeOrErr.isError())
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001393 return false;
1394 }
1395 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001398 return false;
1399 }
1400
1401 // 3D texture target validation
1402 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001405 return false;
1406 }
1407
1408 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001409 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001410 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1411 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001412 {
1413 return false;
1414 }
1415
1416 return true;
1417}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001418
Corentin Wallezb2931602017-04-11 15:58:57 -04001419bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1420 GLenum target,
1421 GLint level,
1422 GLenum internalformat,
1423 GLsizei width,
1424 GLsizei height,
1425 GLsizei depth,
1426 GLint border,
1427 GLsizei imageSize,
1428 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001429 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001430{
1431 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1432 {
1433 return false;
1434 }
1435
1436 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1437 depth, border, imageSize, data);
1438}
1439
Austin Kinrossbc781f32015-10-26 09:27:38 -07001440bool ValidateBindVertexArray(Context *context, GLuint array)
1441{
Martin Radev1be913c2016-07-11 17:59:16 +03001442 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001443 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001445 return false;
1446 }
1447
1448 return ValidateBindVertexArrayBase(context, array);
1449}
1450
Jamie Madilld7576732017-08-26 18:49:50 -04001451bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001452{
Martin Radev1be913c2016-07-11 17:59:16 +03001453 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001454 {
Jamie Madilld7576732017-08-26 18:49:50 -04001455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001456 return false;
1457 }
1458
1459 return true;
1460}
Geoff Langc5629752015-12-07 16:29:04 -05001461
Jiajia Qin6eafb042016-12-27 17:04:07 +08001462static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001463 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001464 GLuint index,
1465 GLuint buffer,
1466 GLintptr offset,
1467 GLsizeiptr size)
1468{
1469 if (context->getClientMajorVersion() < 3)
1470 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001472 return false;
1473 }
1474
1475 if (buffer != 0 && offset < 0)
1476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001478 return false;
1479 }
1480
1481 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1482 !context->isBufferGenerated(buffer))
1483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001484 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001485 return false;
1486 }
1487
1488 const Caps &caps = context->getCaps();
1489 switch (target)
1490 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001491 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001492 {
1493 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001495 context->handleError(InvalidValue() << "index is greater than or equal to the "
1496 "number of TRANSFORM_FEEDBACK_BUFFER "
1497 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001498 return false;
1499 }
1500 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001503 return false;
1504 }
1505
1506 TransformFeedback *curTransformFeedback =
1507 context->getGLState().getCurrentTransformFeedback();
1508 if (curTransformFeedback && curTransformFeedback->isActive())
1509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidOperation()
1511 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1512 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001513 return false;
1514 }
1515 break;
1516 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001517 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001518 {
1519 if (index >= caps.maxUniformBufferBindings)
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidValue() << "index is greater than or equal to the "
1522 "number of UNIFORM_BUFFER indexed "
1523 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001524 return false;
1525 }
1526
1527 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1528 {
1529 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 InvalidValue()
1531 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 return false;
1533 }
1534 break;
1535 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001536 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001537 {
1538 if (context->getClientVersion() < ES_3_1)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidEnum()
1541 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001542 return false;
1543 }
1544 if (index >= caps.maxAtomicCounterBufferBindings)
1545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001546 context->handleError(InvalidValue() << "index is greater than or equal to the "
1547 "number of ATOMIC_COUNTER_BUFFER "
1548 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001549 return false;
1550 }
1551 if (buffer != 0 && (offset % 4) != 0)
1552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001554 return false;
1555 }
1556 break;
1557 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001558 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001559 {
1560 if (context->getClientVersion() < ES_3_1)
1561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001562 context->handleError(InvalidEnum()
1563 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001564 return false;
1565 }
1566 if (index >= caps.maxShaderStorageBufferBindings)
1567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001568 context->handleError(InvalidValue() << "index is greater than or equal to the "
1569 "number of SHADER_STORAGE_BUFFER "
1570 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001571 return false;
1572 }
1573 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001575 context->handleError(InvalidValue() << "offset must be multiple of value of "
1576 "SHADER_STORAGE_BUFFER_OFFSET_"
1577 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001578 return false;
1579 }
1580 break;
1581 }
1582 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001583 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001584 return false;
1585 }
1586
1587 return true;
1588}
1589
Corentin Wallez336129f2017-10-17 15:55:40 -04001590bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001591{
1592 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1593}
1594
1595bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001596 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001597 GLuint index,
1598 GLuint buffer,
1599 GLintptr offset,
1600 GLsizeiptr size)
1601{
1602 if (buffer != 0 && size <= 0)
1603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidValue()
1605 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001606 return false;
1607 }
1608 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1609}
1610
Geoff Langc5629752015-12-07 16:29:04 -05001611bool ValidateProgramBinary(Context *context,
1612 GLuint program,
1613 GLenum binaryFormat,
1614 const void *binary,
1615 GLint length)
1616{
Martin Radev1be913c2016-07-11 17:59:16 +03001617 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001618 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001620 return false;
1621 }
1622
1623 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1624}
1625
1626bool ValidateGetProgramBinary(Context *context,
1627 GLuint program,
1628 GLsizei bufSize,
1629 GLsizei *length,
1630 GLenum *binaryFormat,
1631 void *binary)
1632{
Martin Radev1be913c2016-07-11 17:59:16 +03001633 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001634 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001636 return false;
1637 }
1638
1639 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1640}
1641
Olli Etuahof0fee072016-03-30 15:11:58 +03001642bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001643{
Martin Radev1be913c2016-07-11 17:59:16 +03001644 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001647 return false;
1648 }
1649
1650 if (GetValidProgram(context, program) == nullptr)
1651 {
1652 return false;
1653 }
1654
1655 switch (pname)
1656 {
1657 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001658 if (value != GL_FALSE && value != GL_TRUE)
1659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidValue()
1661 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001662 return false;
1663 }
Geoff Langc5629752015-12-07 16:29:04 -05001664 break;
1665
Yunchao He61afff12017-03-14 15:34:03 +08001666 case GL_PROGRAM_SEPARABLE:
1667 if (context->getClientVersion() < ES_3_1)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidEnum()
1670 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001671 return false;
1672 }
1673
1674 if (value != GL_FALSE && value != GL_TRUE)
1675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidValue()
1677 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001678 return false;
1679 }
1680 break;
1681
Geoff Langc5629752015-12-07 16:29:04 -05001682 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001683 context->handleError(InvalidEnum()
1684 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001685 return false;
1686 }
1687
1688 return true;
1689}
Jamie Madillc29968b2016-01-20 11:17:23 -05001690
1691bool ValidateBlitFramebuffer(Context *context,
1692 GLint srcX0,
1693 GLint srcY0,
1694 GLint srcX1,
1695 GLint srcY1,
1696 GLint dstX0,
1697 GLint dstY0,
1698 GLint dstX1,
1699 GLint dstY1,
1700 GLbitfield mask,
1701 GLenum filter)
1702{
Martin Radev1be913c2016-07-11 17:59:16 +03001703 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001704 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001706 return false;
1707 }
1708
1709 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1710 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001711}
Jamie Madillc29968b2016-01-20 11:17:23 -05001712
1713bool ValidateClearBufferiv(ValidationContext *context,
1714 GLenum buffer,
1715 GLint drawbuffer,
1716 const GLint *value)
1717{
1718 switch (buffer)
1719 {
1720 case GL_COLOR:
1721 if (drawbuffer < 0 ||
1722 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
Geoff Lang76e65652017-03-27 14:58:02 -04001727 if (context->getExtensions().webglCompatibility)
1728 {
1729 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001730 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001731 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1732 {
1733 return false;
1734 }
1735 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001736 break;
1737
1738 case GL_STENCIL:
1739 if (drawbuffer != 0)
1740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001741 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 return false;
1743 }
1744 break;
1745
1746 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001747 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750
1751 return ValidateClearBuffer(context);
1752}
1753
1754bool ValidateClearBufferuiv(ValidationContext *context,
1755 GLenum buffer,
1756 GLint drawbuffer,
1757 const GLuint *value)
1758{
1759 switch (buffer)
1760 {
1761 case GL_COLOR:
1762 if (drawbuffer < 0 ||
1763 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001766 return false;
1767 }
Geoff Lang76e65652017-03-27 14:58:02 -04001768 if (context->getExtensions().webglCompatibility)
1769 {
1770 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001771 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001772 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1773 {
1774 return false;
1775 }
1776 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001777 break;
1778
1779 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 return ValidateClearBuffer(context);
1785}
1786
1787bool ValidateClearBufferfv(ValidationContext *context,
1788 GLenum buffer,
1789 GLint drawbuffer,
1790 const GLfloat *value)
1791{
1792 switch (buffer)
1793 {
1794 case GL_COLOR:
1795 if (drawbuffer < 0 ||
1796 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001798 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001799 return false;
1800 }
Geoff Lang76e65652017-03-27 14:58:02 -04001801 if (context->getExtensions().webglCompatibility)
1802 {
1803 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1804 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001805 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001806 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1807 {
1808 return false;
1809 }
1810 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001811 break;
1812
1813 case GL_DEPTH:
1814 if (drawbuffer != 0)
1815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001816 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819 break;
1820
1821 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001822 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001823 return false;
1824 }
1825
1826 return ValidateClearBuffer(context);
1827}
1828
1829bool ValidateClearBufferfi(ValidationContext *context,
1830 GLenum buffer,
1831 GLint drawbuffer,
1832 GLfloat depth,
1833 GLint stencil)
1834{
1835 switch (buffer)
1836 {
1837 case GL_DEPTH_STENCIL:
1838 if (drawbuffer != 0)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001841 return false;
1842 }
1843 break;
1844
1845 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001846 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001847 return false;
1848 }
1849
1850 return ValidateClearBuffer(context);
1851}
1852
1853bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1854{
Martin Radev1be913c2016-07-11 17:59:16 +03001855 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860
1861 return ValidateDrawBuffersBase(context, n, bufs);
1862}
1863
1864bool ValidateCopyTexSubImage3D(Context *context,
1865 GLenum target,
1866 GLint level,
1867 GLint xoffset,
1868 GLint yoffset,
1869 GLint zoffset,
1870 GLint x,
1871 GLint y,
1872 GLsizei width,
1873 GLsizei height)
1874{
Martin Radev1be913c2016-07-11 17:59:16 +03001875 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001877 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 return false;
1879 }
1880
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001881 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1882 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001883}
1884
Jamie Madill73a84962016-02-12 09:27:23 -05001885bool ValidateTexImage3D(Context *context,
1886 GLenum target,
1887 GLint level,
1888 GLint internalformat,
1889 GLsizei width,
1890 GLsizei height,
1891 GLsizei depth,
1892 GLint border,
1893 GLenum format,
1894 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001895 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001896{
Martin Radev1be913c2016-07-11 17:59:16 +03001897 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001898 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001900 return false;
1901 }
1902
1903 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001904 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001905 pixels);
1906}
1907
Geoff Langc52f6f12016-10-14 10:18:00 -04001908bool ValidateTexImage3DRobustANGLE(Context *context,
1909 GLenum target,
1910 GLint level,
1911 GLint internalformat,
1912 GLsizei width,
1913 GLsizei height,
1914 GLsizei depth,
1915 GLint border,
1916 GLenum format,
1917 GLenum type,
1918 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001919 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001920{
1921 if (context->getClientMajorVersion() < 3)
1922 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001924 return false;
1925 }
1926
1927 if (!ValidateRobustEntryPoint(context, bufSize))
1928 {
1929 return false;
1930 }
1931
1932 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1933 0, 0, width, height, depth, border, format, type,
1934 bufSize, pixels);
1935}
1936
Jamie Madill73a84962016-02-12 09:27:23 -05001937bool ValidateTexSubImage3D(Context *context,
1938 GLenum target,
1939 GLint level,
1940 GLint xoffset,
1941 GLint yoffset,
1942 GLint zoffset,
1943 GLsizei width,
1944 GLsizei height,
1945 GLsizei depth,
1946 GLenum format,
1947 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001948 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001949{
Martin Radev1be913c2016-07-11 17:59:16 +03001950 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001951 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001952 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001953 return false;
1954 }
1955
1956 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1957 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001958 -1, pixels);
1959}
1960
1961bool ValidateTexSubImage3DRobustANGLE(Context *context,
1962 GLenum target,
1963 GLint level,
1964 GLint xoffset,
1965 GLint yoffset,
1966 GLint zoffset,
1967 GLsizei width,
1968 GLsizei height,
1969 GLsizei depth,
1970 GLenum format,
1971 GLenum type,
1972 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001973 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001974{
1975 if (context->getClientMajorVersion() < 3)
1976 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001978 return false;
1979 }
1980
1981 if (!ValidateRobustEntryPoint(context, bufSize))
1982 {
1983 return false;
1984 }
1985
1986 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1987 yoffset, zoffset, width, height, depth, 0, format, type,
1988 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001989}
1990
1991bool ValidateCompressedTexSubImage3D(Context *context,
1992 GLenum target,
1993 GLint level,
1994 GLint xoffset,
1995 GLint yoffset,
1996 GLint zoffset,
1997 GLsizei width,
1998 GLsizei height,
1999 GLsizei depth,
2000 GLenum format,
2001 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002002 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002003{
Martin Radev1be913c2016-07-11 17:59:16 +03002004 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002005 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002007 return false;
2008 }
2009
Geoff Langca271392017-04-05 12:30:00 -04002010 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002011 if (!formatInfo.compressed)
2012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002013 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002014 return false;
2015 }
2016
Jeff Gilbert48590352017-11-07 16:03:38 -08002017 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002018 if (blockSizeOrErr.isError())
2019 {
2020 context->handleError(blockSizeOrErr.getError());
2021 return false;
2022 }
2023 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002025 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002026 return false;
2027 }
2028
2029 if (!data)
2030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002031 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002032 return false;
2033 }
2034
Geoff Lang5ca5c652017-10-27 17:29:54 -04002035 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2036 yoffset, zoffset, width, height, depth, 0, format,
2037 GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002038}
Corentin Wallezb2931602017-04-11 15:58:57 -04002039bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2040 GLenum target,
2041 GLint level,
2042 GLint xoffset,
2043 GLint yoffset,
2044 GLint zoffset,
2045 GLsizei width,
2046 GLsizei height,
2047 GLsizei depth,
2048 GLenum format,
2049 GLsizei imageSize,
2050 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002051 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002052{
2053 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2054 {
2055 return false;
2056 }
2057
2058 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2059 height, depth, format, imageSize, data);
2060}
Jamie Madill73a84962016-02-12 09:27:23 -05002061
Olli Etuaho41997e72016-03-10 13:38:39 +02002062bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2063{
2064 return ValidateGenOrDeleteES3(context, n);
2065}
2066
2067bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2068{
2069 return ValidateGenOrDeleteES3(context, n);
2070}
2071
2072bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2073{
2074 return ValidateGenOrDeleteCountES3(context, count);
2075}
2076
2077bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2078{
2079 return ValidateGenOrDeleteCountES3(context, count);
2080}
2081
2082bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2083{
2084 return ValidateGenOrDeleteES3(context, n);
2085}
2086
2087bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2088{
2089 if (!ValidateGenOrDeleteES3(context, n))
2090 {
2091 return false;
2092 }
2093 for (GLint i = 0; i < n; ++i)
2094 {
2095 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2096 if (transformFeedback != nullptr && transformFeedback->isActive())
2097 {
2098 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002099 context->handleError(InvalidOperation()
2100 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002101 return false;
2102 }
2103 }
2104 return true;
2105}
2106
2107bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2108{
2109 return ValidateGenOrDeleteES3(context, n);
2110}
2111
2112bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2113{
2114 return ValidateGenOrDeleteES3(context, n);
2115}
2116
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002117bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2118{
Martin Radev1be913c2016-07-11 17:59:16 +03002119 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002120 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002122 return false;
2123 }
2124 switch (primitiveMode)
2125 {
2126 case GL_TRIANGLES:
2127 case GL_LINES:
2128 case GL_POINTS:
2129 break;
2130
2131 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002132 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002133 return false;
2134 }
2135
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002136 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002137 ASSERT(transformFeedback != nullptr);
2138
2139 if (transformFeedback->isActive())
2140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002142 return false;
2143 }
Geoff Lang79f71042017-08-14 16:43:43 -04002144
2145 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2146 {
2147 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2148 if (buffer.get() && buffer->isMapped())
2149 {
2150 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2151 return false;
2152 }
2153 }
2154
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002155 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002156
2157 if (!program)
2158 {
2159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2160 return false;
2161 }
2162
2163 if (program->getTransformFeedbackVaryingCount() == 0)
2164 {
2165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2166 return false;
2167 }
2168
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002169 return true;
2170}
2171
Corentin Wallez336129f2017-10-17 15:55:40 -04002172bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002173{
Geoff Lang496c02d2016-10-20 11:38:11 -07002174 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2175}
2176
2177bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002178 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002179 GLenum pname,
2180 GLsizei bufSize,
2181 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002182 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002183{
2184 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002185 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002186 return false;
2187 }
2188
Geoff Lang496c02d2016-10-20 11:38:11 -07002189 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2190 {
2191 return false;
2192 }
2193
2194 if (!ValidateRobustBufferSize(context, bufSize, *length))
2195 {
2196 return false;
2197 }
2198
2199 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002200}
2201
Corentin Wallez336129f2017-10-17 15:55:40 -04002202bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002203{
Martin Radev1be913c2016-07-11 17:59:16 +03002204 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002205 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 return false;
2208 }
2209
2210 return ValidateUnmapBufferBase(context, target);
2211}
2212
2213bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002214 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002215 GLintptr offset,
2216 GLsizeiptr length,
2217 GLbitfield access)
2218{
Martin Radev1be913c2016-07-11 17:59:16 +03002219 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002220 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002222 return false;
2223 }
2224
2225 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2226}
2227
2228bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002229 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002230 GLintptr offset,
2231 GLsizeiptr length)
2232{
Martin Radev1be913c2016-07-11 17:59:16 +03002233 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002234 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002236 return false;
2237 }
2238
2239 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2240}
2241
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002242bool ValidateIndexedStateQuery(ValidationContext *context,
2243 GLenum pname,
2244 GLuint index,
2245 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002246{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002247 if (length)
2248 {
2249 *length = 0;
2250 }
2251
Martin Radev66fb8202016-07-28 11:45:20 +03002252 GLenum nativeType;
2253 unsigned int numParams;
2254 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002256 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002257 return false;
2258 }
2259
2260 const Caps &caps = context->getCaps();
2261 switch (pname)
2262 {
2263 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2264 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2265 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2266 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002268 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002269 return false;
2270 }
2271 break;
2272
2273 case GL_UNIFORM_BUFFER_START:
2274 case GL_UNIFORM_BUFFER_SIZE:
2275 case GL_UNIFORM_BUFFER_BINDING:
2276 if (index >= caps.maxUniformBufferBindings)
2277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002278 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002279 return false;
2280 }
2281 break;
Shao80957d92017-02-20 21:25:59 +08002282
Martin Radev66fb8202016-07-28 11:45:20 +03002283 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2284 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2285 if (index >= 3u)
2286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002287 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002288 return false;
2289 }
2290 break;
Shao80957d92017-02-20 21:25:59 +08002291
Jiajia Qin6eafb042016-12-27 17:04:07 +08002292 case GL_ATOMIC_COUNTER_BUFFER_START:
2293 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2294 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2295 if (context->getClientVersion() < ES_3_1)
2296 {
2297 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002298 InvalidEnum()
2299 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002300 return false;
2301 }
2302 if (index >= caps.maxAtomicCounterBufferBindings)
2303 {
2304 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002305 InvalidValue()
2306 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002307 return false;
2308 }
2309 break;
Shao80957d92017-02-20 21:25:59 +08002310
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002311 case GL_SHADER_STORAGE_BUFFER_START:
2312 case GL_SHADER_STORAGE_BUFFER_SIZE:
2313 case GL_SHADER_STORAGE_BUFFER_BINDING:
2314 if (context->getClientVersion() < ES_3_1)
2315 {
2316 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002317 InvalidEnum()
2318 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002319 return false;
2320 }
2321 if (index >= caps.maxShaderStorageBufferBindings)
2322 {
2323 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002324 InvalidValue()
2325 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002326 return false;
2327 }
2328 break;
2329
Shao80957d92017-02-20 21:25:59 +08002330 case GL_VERTEX_BINDING_BUFFER:
2331 case GL_VERTEX_BINDING_DIVISOR:
2332 case GL_VERTEX_BINDING_OFFSET:
2333 case GL_VERTEX_BINDING_STRIDE:
2334 if (context->getClientVersion() < ES_3_1)
2335 {
2336 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002337 InvalidEnum()
2338 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002339 return false;
2340 }
2341 if (index >= caps.maxVertexAttribBindings)
2342 {
2343 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002344 InvalidValue()
2345 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002346 return false;
2347 }
2348 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002349 case GL_SAMPLE_MASK_VALUE:
2350 if (context->getClientVersion() < ES_3_1)
2351 {
2352 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2353 return false;
2354 }
2355 if (index >= caps.maxSampleMaskWords)
2356 {
2357 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2358 return false;
2359 }
2360 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002361 case GL_IMAGE_BINDING_NAME:
2362 case GL_IMAGE_BINDING_LEVEL:
2363 case GL_IMAGE_BINDING_LAYERED:
2364 case GL_IMAGE_BINDING_LAYER:
2365 case GL_IMAGE_BINDING_ACCESS:
2366 case GL_IMAGE_BINDING_FORMAT:
2367 if (context->getClientVersion() < ES_3_1)
2368 {
2369 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2370 return false;
2371 }
2372 if (index >= caps.maxImageUnits)
2373 {
2374 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2375 return false;
2376 }
2377 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002378 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002379 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002380 return false;
2381 }
2382
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002383 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002384 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002385 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002386 }
2387
2388 return true;
2389}
2390
2391bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2392{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002393 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002394 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002395 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002396 return false;
2397 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002398 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002399}
2400
Geoff Langcf255ea2016-10-20 11:39:09 -07002401bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2402 GLenum target,
2403 GLuint index,
2404 GLsizei bufSize,
2405 GLsizei *length,
2406 GLint *data)
2407{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002408 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002409 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002410 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002411 return false;
2412 }
2413
2414 if (!ValidateRobustEntryPoint(context, bufSize))
2415 {
2416 return false;
2417 }
2418
2419 if (!ValidateIndexedStateQuery(context, target, index, length))
2420 {
2421 return false;
2422 }
2423
2424 if (!ValidateRobustBufferSize(context, bufSize, *length))
2425 {
2426 return false;
2427 }
2428
2429 return true;
2430}
2431
Martin Radev66fb8202016-07-28 11:45:20 +03002432bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2433{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002434 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002437 return false;
2438 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002439 return ValidateIndexedStateQuery(context, target, index, nullptr);
2440}
2441
2442bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2443 GLenum target,
2444 GLuint index,
2445 GLsizei bufSize,
2446 GLsizei *length,
2447 GLint64 *data)
2448{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002449 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002450 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002452 return false;
2453 }
2454
2455 if (!ValidateRobustEntryPoint(context, bufSize))
2456 {
2457 return false;
2458 }
2459
2460 if (!ValidateIndexedStateQuery(context, target, index, length))
2461 {
2462 return false;
2463 }
2464
2465 if (!ValidateRobustBufferSize(context, bufSize, *length))
2466 {
2467 return false;
2468 }
2469
2470 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002471}
2472
Jamie Madillb0817d12016-11-01 15:48:31 -04002473bool ValidateCopyBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002474 BufferBinding readTarget,
2475 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002476 GLintptr readOffset,
2477 GLintptr writeOffset,
2478 GLsizeiptr size)
2479{
2480 if (context->getClientMajorVersion() < 3)
2481 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002483 return false;
2484 }
2485
Corentin Walleze4477002017-12-01 14:39:58 -05002486 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002489 return false;
2490 }
2491
2492 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2493 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2494
2495 if (!readBuffer || !writeBuffer)
2496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002497 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002498 return false;
2499 }
2500
2501 // Verify that readBuffer and writeBuffer are not currently mapped
2502 if (readBuffer->isMapped() || writeBuffer->isMapped())
2503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidOperation()
2505 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002506 return false;
2507 }
2508
Jamie Madilld2f0c742016-11-02 10:34:41 -04002509 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2510 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2511 CheckedNumeric<GLintptr> checkedSize(size);
2512
2513 auto checkedReadSum = checkedReadOffset + checkedSize;
2514 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2515
2516 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2517 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2518 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002520 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002521 return false;
2522 }
2523
Jamie Madilld2f0c742016-11-02 10:34:41 -04002524 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002526 context->handleError(InvalidValue()
2527 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002528 return false;
2529 }
2530
Jamie Madilld2f0c742016-11-02 10:34:41 -04002531 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2532 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002534 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002535 return false;
2536 }
2537
2538 if (readBuffer == writeBuffer)
2539 {
2540 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2541 if (!checkedOffsetDiff.IsValid())
2542 {
2543 // This shold not be possible.
2544 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue()
2546 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002547 return false;
2548 }
2549
2550 if (checkedOffsetDiff.ValueOrDie() < size)
2551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002552 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002553 return false;
2554 }
2555 }
2556
Jamie Madillb0817d12016-11-01 15:48:31 -04002557 return true;
2558}
2559
Geoff Langc339c4e2016-11-29 10:37:36 -05002560bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2561{
2562 if (context->getClientMajorVersion() < 3)
2563 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002565 return false;
2566 }
2567
2568 switch (name)
2569 {
2570 case GL_EXTENSIONS:
2571 if (index >= context->getExtensionStringCount())
2572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002573 context->handleError(InvalidValue()
2574 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002575 return false;
2576 }
2577 break;
2578
2579 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2580 if (!context->getExtensions().requestExtension)
2581 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002583 return false;
2584 }
2585 if (index >= context->getRequestableExtensionStringCount())
2586 {
2587 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002588 InvalidValue()
2589 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002590 return false;
2591 }
2592 break;
2593
2594 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002596 return false;
2597 }
2598
2599 return true;
2600}
2601
Jamie Madille8fb6402017-02-14 17:56:40 -05002602bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2603 GLenum target,
2604 GLsizei samples,
2605 GLenum internalformat,
2606 GLsizei width,
2607 GLsizei height)
2608{
2609 if (context->getClientMajorVersion() < 3)
2610 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002612 return false;
2613 }
2614
2615 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2616 height))
2617 {
2618 return false;
2619 }
2620
2621 // 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 +08002622 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2623 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002624 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002625 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002626 {
Yunchao Hec0810202018-01-22 09:48:48 +08002627 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2628 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2629 {
2630 context->handleError(InvalidOperation());
2631 return false;
2632 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002633 }
2634
2635 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2636 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2637 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2638 {
2639 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002640 InvalidOperation()
2641 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002642 return false;
2643 }
2644
2645 return true;
2646}
2647
Geoff Langaa086d62017-03-23 16:47:21 -04002648bool ValidateVertexAttribIPointer(ValidationContext *context,
2649 GLuint index,
2650 GLint size,
2651 GLenum type,
2652 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002653 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002654{
2655 if (context->getClientMajorVersion() < 3)
2656 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002658 return false;
2659 }
2660
Shao80957d92017-02-20 21:25:59 +08002661 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002662 {
Geoff Langaa086d62017-03-23 16:47:21 -04002663 return false;
2664 }
2665
Geoff Langaa086d62017-03-23 16:47:21 -04002666 if (stride < 0)
2667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002668 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002669 return false;
2670 }
2671
Shao80957d92017-02-20 21:25:59 +08002672 const Caps &caps = context->getCaps();
2673 if (context->getClientVersion() >= ES_3_1)
2674 {
2675 if (stride > caps.maxVertexAttribStride)
2676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002677 context->handleError(InvalidValue()
2678 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002679 return false;
2680 }
2681
2682 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2683 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2684 // validation should be inherited.
2685 if (index >= caps.maxVertexAttribBindings)
2686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002687 context->handleError(InvalidValue()
2688 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002689 return false;
2690 }
2691 }
2692
Geoff Langaa086d62017-03-23 16:47:21 -04002693 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2694 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2695 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2696 // and the pointer argument is not NULL.
2697 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002698 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002700 context
2701 ->handleError(InvalidOperation()
2702 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002703 return false;
2704 }
2705
Geoff Lang2d62ab72017-03-23 16:54:40 -04002706 if (context->getExtensions().webglCompatibility)
2707 {
2708 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2709 {
2710 return false;
2711 }
2712 }
2713
Geoff Langaa086d62017-03-23 16:47:21 -04002714 return true;
2715}
2716
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002717bool ValidateGetSynciv(Context *context,
2718 GLsync sync,
2719 GLenum pname,
2720 GLsizei bufSize,
2721 GLsizei *length,
2722 GLint *values)
2723{
2724 if (context->getClientMajorVersion() < 3)
2725 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002727 return false;
2728 }
2729
2730 if (bufSize < 0)
2731 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002732 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002733 return false;
2734 }
2735
Jamie Madill70b5bb02017-08-28 13:32:37 -04002736 Sync *syncObject = context->getSync(sync);
2737 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002739 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002740 return false;
2741 }
2742
2743 switch (pname)
2744 {
2745 case GL_OBJECT_TYPE:
2746 case GL_SYNC_CONDITION:
2747 case GL_SYNC_FLAGS:
2748 case GL_SYNC_STATUS:
2749 break;
2750
2751 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002753 return false;
2754 }
2755
2756 return true;
2757}
2758
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002759bool ValidateDrawElementsInstanced(ValidationContext *context,
2760 GLenum mode,
2761 GLsizei count,
2762 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002763 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002764 GLsizei instanceCount)
2765{
2766 if (context->getClientMajorVersion() < 3)
2767 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002768 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002769 return false;
2770 }
2771
2772 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2773}
2774
Martin Radev137032d2017-07-13 10:11:12 +03002775bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2776 GLenum target,
2777 GLenum attachment,
2778 GLuint texture,
2779 GLint level,
2780 GLint baseViewIndex,
2781 GLsizei numViews)
2782{
2783
2784 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2785 numViews))
2786 {
2787 return false;
2788 }
2789
Martin Radev137032d2017-07-13 10:11:12 +03002790 if (texture != 0)
2791 {
Martin Radev14b21262017-08-25 13:54:37 +03002792 if (baseViewIndex < 0)
2793 {
2794 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2795 return false;
2796 }
2797
Martin Radev137032d2017-07-13 10:11:12 +03002798 Texture *tex = context->getTexture(texture);
2799 ASSERT(tex);
2800
2801 switch (tex->getTarget())
2802 {
2803 case GL_TEXTURE_2D_ARRAY:
2804 {
2805 const Caps &caps = context->getCaps();
2806 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2807 {
2808 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2809 "greater than "
2810 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2811 return false;
2812 }
2813 }
2814 break;
2815 default:
2816 context->handleError(InvalidOperation()
2817 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2818 return false;
2819 }
2820
2821 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2822 {
2823 return false;
2824 }
2825 }
2826
2827 return true;
2828}
2829
2830bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2831 GLenum target,
2832 GLenum attachment,
2833 GLuint texture,
2834 GLint level,
2835 GLsizei numViews,
2836 const GLint *viewportOffsets)
2837{
2838 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2839 numViews))
2840 {
2841 return false;
2842 }
2843
Martin Radev137032d2017-07-13 10:11:12 +03002844 if (texture != 0)
2845 {
Martin Radev14b21262017-08-25 13:54:37 +03002846 const GLsizei numViewportOffsetValues = numViews * 2;
2847 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2848 {
2849 if (viewportOffsets[i] < 0)
2850 {
2851 context->handleError(InvalidValue()
2852 << "viewportOffsets cannot contain negative values.");
2853 return false;
2854 }
2855 }
2856
Martin Radev137032d2017-07-13 10:11:12 +03002857 Texture *tex = context->getTexture(texture);
2858 ASSERT(tex);
2859
2860 switch (tex->getTarget())
2861 {
2862 case GL_TEXTURE_2D:
2863 break;
2864 default:
2865 context->handleError(InvalidOperation()
2866 << "Texture's target must be GL_TEXTURE_2D.");
2867 return false;
2868 }
2869
2870 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2871 {
2872 return false;
2873 }
2874 }
2875
2876 return true;
2877}
2878
Jamie Madillff325f12017-08-26 15:06:05 -04002879bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2880{
2881 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2882}
2883
2884bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2885{
2886 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2887}
2888
2889bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2890{
2891 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2892}
2893
2894bool ValidateUniform4ui(Context *context,
2895 GLint location,
2896 GLuint v0,
2897 GLuint v1,
2898 GLuint v2,
2899 GLuint v3)
2900{
2901 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2902}
2903
2904bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2905{
2906 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2907}
2908
2909bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2910{
2911 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2912}
2913
2914bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2915{
2916 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2917}
2918
2919bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2920{
2921 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2922}
2923
Jamie Madillf0e04492017-08-26 15:28:42 -04002924bool ValidateIsQuery(Context *context, GLuint id)
2925{
2926 if (context->getClientMajorVersion() < 3)
2927 {
2928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2929 return false;
2930 }
2931
2932 return true;
2933}
2934
Jamie Madillc8c95812017-08-26 18:40:09 -04002935bool ValidateUniformMatrix2x3fv(Context *context,
2936 GLint location,
2937 GLsizei count,
2938 GLboolean transpose,
2939 const GLfloat *value)
2940{
2941 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2942}
2943
2944bool ValidateUniformMatrix3x2fv(Context *context,
2945 GLint location,
2946 GLsizei count,
2947 GLboolean transpose,
2948 const GLfloat *value)
2949{
2950 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2951}
2952
2953bool ValidateUniformMatrix2x4fv(Context *context,
2954 GLint location,
2955 GLsizei count,
2956 GLboolean transpose,
2957 const GLfloat *value)
2958{
2959 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2960}
2961
2962bool ValidateUniformMatrix4x2fv(Context *context,
2963 GLint location,
2964 GLsizei count,
2965 GLboolean transpose,
2966 const GLfloat *value)
2967{
2968 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2969}
2970
2971bool ValidateUniformMatrix3x4fv(Context *context,
2972 GLint location,
2973 GLsizei count,
2974 GLboolean transpose,
2975 const GLfloat *value)
2976{
2977 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2978}
2979
2980bool ValidateUniformMatrix4x3fv(Context *context,
2981 GLint location,
2982 GLsizei count,
2983 GLboolean transpose,
2984 const GLfloat *value)
2985{
2986 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2987}
2988
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002989bool ValidateEndTransformFeedback(Context *context)
2990{
2991 if (context->getClientMajorVersion() < 3)
2992 {
2993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2994 return false;
2995 }
2996
2997 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2998 ASSERT(transformFeedback != nullptr);
2999
3000 if (!transformFeedback->isActive())
3001 {
3002 context->handleError(InvalidOperation());
3003 return false;
3004 }
3005
3006 return true;
3007}
3008
3009bool ValidateTransformFeedbackVaryings(Context *context,
3010 GLuint program,
3011 GLsizei count,
3012 const GLchar *const *varyings,
3013 GLenum bufferMode)
3014{
3015 if (context->getClientMajorVersion() < 3)
3016 {
3017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3018 return false;
3019 }
3020
3021 if (count < 0)
3022 {
3023 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3024 return false;
3025 }
3026
3027 switch (bufferMode)
3028 {
3029 case GL_INTERLEAVED_ATTRIBS:
3030 break;
3031 case GL_SEPARATE_ATTRIBS:
3032 {
3033 const Caps &caps = context->getCaps();
3034 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3035 {
3036 context->handleError(InvalidValue());
3037 return false;
3038 }
3039 break;
3040 }
3041 default:
3042 context->handleError(InvalidEnum());
3043 return false;
3044 }
3045
3046 Program *programObject = GetValidProgram(context, program);
3047 if (!programObject)
3048 {
3049 return false;
3050 }
3051
3052 return true;
3053}
3054
3055bool ValidateGetTransformFeedbackVarying(Context *context,
3056 GLuint program,
3057 GLuint index,
3058 GLsizei bufSize,
3059 GLsizei *length,
3060 GLsizei *size,
3061 GLenum *type,
3062 GLchar *name)
3063{
3064 if (context->getClientMajorVersion() < 3)
3065 {
3066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3067 return false;
3068 }
3069
3070 if (bufSize < 0)
3071 {
3072 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3073 return false;
3074 }
3075
3076 Program *programObject = GetValidProgram(context, program);
3077 if (!programObject)
3078 {
3079 return false;
3080 }
3081
3082 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3083 {
3084 context->handleError(InvalidValue());
3085 return false;
3086 }
3087
3088 return true;
3089}
3090
3091bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3092{
3093 if (context->getClientMajorVersion() < 3)
3094 {
3095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3096 return false;
3097 }
3098
3099 switch (target)
3100 {
3101 case GL_TRANSFORM_FEEDBACK:
3102 {
3103 // Cannot bind a transform feedback object if the current one is started and not
3104 // paused (3.0.2 pg 85 section 2.14.1)
3105 TransformFeedback *curTransformFeedback =
3106 context->getGLState().getCurrentTransformFeedback();
3107 if (curTransformFeedback && curTransformFeedback->isActive() &&
3108 !curTransformFeedback->isPaused())
3109 {
3110 context->handleError(InvalidOperation());
3111 return false;
3112 }
3113
3114 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3115 // 2.14.1)
3116 if (!context->isTransformFeedbackGenerated(id))
3117 {
3118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3119 return false;
3120 }
3121 }
3122 break;
3123
3124 default:
3125 context->handleError(InvalidEnum());
3126 return false;
3127 }
3128
3129 return true;
3130}
3131
3132bool ValidateIsTransformFeedback(Context *context, GLuint id)
3133{
3134 if (context->getClientMajorVersion() < 3)
3135 {
3136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3137 return false;
3138 }
3139
3140 return true;
3141}
3142
3143bool ValidatePauseTransformFeedback(Context *context)
3144{
3145 if (context->getClientMajorVersion() < 3)
3146 {
3147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3148 return false;
3149 }
3150
3151 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3152 ASSERT(transformFeedback != nullptr);
3153
3154 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3155 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3156 {
3157 context->handleError(InvalidOperation());
3158 return false;
3159 }
3160
3161 return true;
3162}
3163
3164bool ValidateResumeTransformFeedback(Context *context)
3165{
3166 if (context->getClientMajorVersion() < 3)
3167 {
3168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3169 return false;
3170 }
3171
3172 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3173 ASSERT(transformFeedback != nullptr);
3174
3175 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3176 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3177 {
3178 context->handleError(InvalidOperation());
3179 return false;
3180 }
3181
3182 return true;
3183}
3184
Jamie Madill12e957f2017-08-26 21:42:26 -04003185bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3186{
3187 if (context->getClientMajorVersion() < 3)
3188 {
3189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3190 return false;
3191 }
3192
3193 return ValidateVertexAttribIndex(context, index);
3194}
3195
3196bool ValidateVertexAttribI4ui(Context *context,
3197 GLuint index,
3198 GLuint x,
3199 GLuint y,
3200 GLuint z,
3201 GLuint w)
3202{
3203 if (context->getClientMajorVersion() < 3)
3204 {
3205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3206 return false;
3207 }
3208
3209 return ValidateVertexAttribIndex(context, index);
3210}
3211
3212bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3213{
3214 if (context->getClientMajorVersion() < 3)
3215 {
3216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3217 return false;
3218 }
3219
3220 return ValidateVertexAttribIndex(context, index);
3221}
3222
3223bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3224{
3225 if (context->getClientMajorVersion() < 3)
3226 {
3227 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3228 return false;
3229 }
3230
3231 return ValidateVertexAttribIndex(context, index);
3232}
3233
3234bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3235{
3236 if (context->getClientMajorVersion() < 3)
3237 {
3238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3239 return false;
3240 }
3241
3242 Program *programObject = GetValidProgram(context, program);
3243 if (!programObject)
3244 {
3245 return false;
3246 }
3247
3248 if (!programObject->isLinked())
3249 {
3250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3251 return false;
3252 }
3253
3254 return true;
3255}
3256
3257bool ValidateGetUniformIndices(Context *context,
3258 GLuint program,
3259 GLsizei uniformCount,
3260 const GLchar *const *uniformNames,
3261 GLuint *uniformIndices)
3262{
3263 if (context->getClientMajorVersion() < 3)
3264 {
3265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3266 return false;
3267 }
3268
3269 if (uniformCount < 0)
3270 {
3271 context->handleError(InvalidValue());
3272 return false;
3273 }
3274
3275 Program *programObject = GetValidProgram(context, program);
3276 if (!programObject)
3277 {
3278 return false;
3279 }
3280
3281 return true;
3282}
3283
3284bool ValidateGetActiveUniformsiv(Context *context,
3285 GLuint program,
3286 GLsizei uniformCount,
3287 const GLuint *uniformIndices,
3288 GLenum pname,
3289 GLint *params)
3290{
3291 if (context->getClientMajorVersion() < 3)
3292 {
3293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3294 return false;
3295 }
3296
3297 if (uniformCount < 0)
3298 {
3299 context->handleError(InvalidValue());
3300 return false;
3301 }
3302
3303 Program *programObject = GetValidProgram(context, program);
3304 if (!programObject)
3305 {
3306 return false;
3307 }
3308
3309 switch (pname)
3310 {
3311 case GL_UNIFORM_TYPE:
3312 case GL_UNIFORM_SIZE:
3313 case GL_UNIFORM_NAME_LENGTH:
3314 case GL_UNIFORM_BLOCK_INDEX:
3315 case GL_UNIFORM_OFFSET:
3316 case GL_UNIFORM_ARRAY_STRIDE:
3317 case GL_UNIFORM_MATRIX_STRIDE:
3318 case GL_UNIFORM_IS_ROW_MAJOR:
3319 break;
3320
3321 default:
3322 context->handleError(InvalidEnum());
3323 return false;
3324 }
3325
3326 if (uniformCount > programObject->getActiveUniformCount())
3327 {
3328 context->handleError(InvalidValue());
3329 return false;
3330 }
3331
3332 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3333 {
3334 const GLuint index = uniformIndices[uniformId];
3335
3336 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3337 {
3338 context->handleError(InvalidValue());
3339 return false;
3340 }
3341 }
3342
3343 return true;
3344}
3345
3346bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3347{
3348 if (context->getClientMajorVersion() < 3)
3349 {
3350 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3351 return false;
3352 }
3353
3354 Program *programObject = GetValidProgram(context, program);
3355 if (!programObject)
3356 {
3357 return false;
3358 }
3359
3360 return true;
3361}
3362
3363bool ValidateGetActiveUniformBlockiv(Context *context,
3364 GLuint program,
3365 GLuint uniformBlockIndex,
3366 GLenum pname,
3367 GLint *params)
3368{
3369 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3370}
3371
3372bool ValidateGetActiveUniformBlockName(Context *context,
3373 GLuint program,
3374 GLuint uniformBlockIndex,
3375 GLsizei bufSize,
3376 GLsizei *length,
3377 GLchar *uniformBlockName)
3378{
3379 if (context->getClientMajorVersion() < 3)
3380 {
3381 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3382 return false;
3383 }
3384
3385 Program *programObject = GetValidProgram(context, program);
3386 if (!programObject)
3387 {
3388 return false;
3389 }
3390
3391 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3392 {
3393 context->handleError(InvalidValue());
3394 return false;
3395 }
3396
3397 return true;
3398}
3399
3400bool ValidateUniformBlockBinding(Context *context,
3401 GLuint program,
3402 GLuint uniformBlockIndex,
3403 GLuint uniformBlockBinding)
3404{
3405 if (context->getClientMajorVersion() < 3)
3406 {
3407 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3408 return false;
3409 }
3410
3411 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3412 {
3413 context->handleError(InvalidValue());
3414 return false;
3415 }
3416
3417 Program *programObject = GetValidProgram(context, program);
3418 if (!programObject)
3419 {
3420 return false;
3421 }
3422
3423 // if never linked, there won't be any uniform blocks
3424 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3425 {
3426 context->handleError(InvalidValue());
3427 return false;
3428 }
3429
3430 return true;
3431}
3432
3433bool ValidateDrawArraysInstanced(Context *context,
3434 GLenum mode,
3435 GLint first,
3436 GLsizei count,
3437 GLsizei primcount)
3438{
3439 if (context->getClientMajorVersion() < 3)
3440 {
3441 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3442 return false;
3443 }
3444
3445 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3446}
3447
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003448bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3449{
3450 if (context->getClientMajorVersion() < 3)
3451 {
3452 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3453 return false;
3454 }
3455
3456 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3457 {
3458 context->handleError(InvalidEnum());
3459 return false;
3460 }
3461
3462 if (flags != 0)
3463 {
3464 context->handleError(InvalidValue());
3465 return false;
3466 }
3467
3468 return true;
3469}
3470
3471bool ValidateIsSync(Context *context, GLsync sync)
3472{
3473 if (context->getClientMajorVersion() < 3)
3474 {
3475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3476 return false;
3477 }
3478
3479 return true;
3480}
3481
3482bool ValidateDeleteSync(Context *context, GLsync sync)
3483{
3484 if (context->getClientMajorVersion() < 3)
3485 {
3486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3487 return false;
3488 }
3489
Jamie Madill70b5bb02017-08-28 13:32:37 -04003490 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003491 {
3492 context->handleError(InvalidValue());
3493 return false;
3494 }
3495
3496 return true;
3497}
3498
3499bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3500{
3501 if (context->getClientMajorVersion() < 3)
3502 {
3503 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3504 return false;
3505 }
3506
3507 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3508 {
3509 context->handleError(InvalidValue());
3510 return false;
3511 }
3512
Jamie Madill70b5bb02017-08-28 13:32:37 -04003513 Sync *clientWaitSync = context->getSync(sync);
3514 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003515 {
3516 context->handleError(InvalidValue());
3517 return false;
3518 }
3519
3520 return true;
3521}
3522
3523bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3524{
3525 if (context->getClientMajorVersion() < 3)
3526 {
3527 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3528 return false;
3529 }
3530
3531 if (flags != 0)
3532 {
3533 context->handleError(InvalidValue());
3534 return false;
3535 }
3536
3537 if (timeout != GL_TIMEOUT_IGNORED)
3538 {
3539 context->handleError(InvalidValue());
3540 return false;
3541 }
3542
Jamie Madill70b5bb02017-08-28 13:32:37 -04003543 Sync *waitSync = context->getSync(sync);
3544 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003545 {
3546 context->handleError(InvalidValue());
3547 return false;
3548 }
3549
3550 return true;
3551}
3552
3553bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3554{
3555 if (context->getClientMajorVersion() < 3)
3556 {
3557 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3558 return false;
3559 }
3560
3561 GLenum nativeType = GL_NONE;
3562 unsigned int numParams = 0;
3563 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3564 {
3565 return false;
3566 }
3567
3568 return true;
3569}
3570
Jamie Madill3ef140a2017-08-26 23:11:21 -04003571bool ValidateIsSampler(Context *context, GLuint sampler)
3572{
3573 if (context->getClientMajorVersion() < 3)
3574 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003575 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003576 return false;
3577 }
3578
3579 return true;
3580}
3581
3582bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3583{
3584 if (context->getClientMajorVersion() < 3)
3585 {
3586 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3587 return false;
3588 }
3589
3590 if (sampler != 0 && !context->isSampler(sampler))
3591 {
3592 context->handleError(InvalidOperation());
3593 return false;
3594 }
3595
3596 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3597 {
3598 context->handleError(InvalidValue());
3599 return false;
3600 }
3601
3602 return true;
3603}
3604
3605bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3606{
3607 if (context->getClientMajorVersion() < 3)
3608 {
3609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3610 return false;
3611 }
3612
3613 return ValidateVertexAttribIndex(context, index);
3614}
3615
3616bool ValidateTexStorage2D(Context *context,
3617 GLenum target,
3618 GLsizei levels,
3619 GLenum internalformat,
3620 GLsizei width,
3621 GLsizei height)
3622{
3623 if (context->getClientMajorVersion() < 3)
3624 {
3625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3626 return false;
3627 }
3628
3629 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3630 1))
3631 {
3632 return false;
3633 }
3634
3635 return true;
3636}
3637
3638bool ValidateTexStorage3D(Context *context,
3639 GLenum target,
3640 GLsizei levels,
3641 GLenum internalformat,
3642 GLsizei width,
3643 GLsizei height,
3644 GLsizei depth)
3645{
3646 if (context->getClientMajorVersion() < 3)
3647 {
3648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3649 return false;
3650 }
3651
3652 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3653 depth))
3654 {
3655 return false;
3656 }
3657
3658 return true;
3659}
3660
Jamie Madill9696d072017-08-26 23:19:57 -04003661bool ValidateGetBufferParameteri64v(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003662 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003663 GLenum pname,
3664 GLint64 *params)
3665{
3666 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3667}
3668
3669bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3670{
3671 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3672}
3673
3674bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3675{
3676 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3677}
3678
3679bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3680{
3681 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3682}
3683
3684bool ValidateSamplerParameterfv(Context *context,
3685 GLuint sampler,
3686 GLenum pname,
3687 const GLfloat *params)
3688{
3689 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3690}
3691
3692bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3693{
3694 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3695}
3696
3697bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3698{
3699 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3700}
3701
3702bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3703{
3704 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3705}
3706
3707bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3708{
3709 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3710}
3711
3712bool ValidateGetInternalformativ(Context *context,
3713 GLenum target,
3714 GLenum internalformat,
3715 GLenum pname,
3716 GLsizei bufSize,
3717 GLint *params)
3718{
3719 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3720 nullptr);
3721}
3722
Jamie Madillc29968b2016-01-20 11:17:23 -05003723} // namespace gl