blob: 514b638570fa002b5a169785a594b79722b77cc6 [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
Jamie Madill513558d2016-06-02 13:04:11 -04001389 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001390 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001391 if (blockSizeOrErr.isError())
1392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001393 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001394 return false;
1395 }
1396 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001398 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001399 return false;
1400 }
1401
1402 // 3D texture target validation
1403 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001406 return false;
1407 }
1408
1409 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001410 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001411 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1412 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001413 {
1414 return false;
1415 }
1416
1417 return true;
1418}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001419
Corentin Wallezb2931602017-04-11 15:58:57 -04001420bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1421 GLenum target,
1422 GLint level,
1423 GLenum internalformat,
1424 GLsizei width,
1425 GLsizei height,
1426 GLsizei depth,
1427 GLint border,
1428 GLsizei imageSize,
1429 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001430 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001431{
1432 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1433 {
1434 return false;
1435 }
1436
1437 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1438 depth, border, imageSize, data);
1439}
1440
Austin Kinrossbc781f32015-10-26 09:27:38 -07001441bool ValidateBindVertexArray(Context *context, GLuint array)
1442{
Martin Radev1be913c2016-07-11 17:59:16 +03001443 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001444 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001445 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001446 return false;
1447 }
1448
1449 return ValidateBindVertexArrayBase(context, array);
1450}
1451
Jamie Madilld7576732017-08-26 18:49:50 -04001452bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001453{
Martin Radev1be913c2016-07-11 17:59:16 +03001454 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001455 {
Jamie Madilld7576732017-08-26 18:49:50 -04001456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001457 return false;
1458 }
1459
1460 return true;
1461}
Geoff Langc5629752015-12-07 16:29:04 -05001462
Jiajia Qin6eafb042016-12-27 17:04:07 +08001463static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001464 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001465 GLuint index,
1466 GLuint buffer,
1467 GLintptr offset,
1468 GLsizeiptr size)
1469{
1470 if (context->getClientMajorVersion() < 3)
1471 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001473 return false;
1474 }
1475
1476 if (buffer != 0 && offset < 0)
1477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001478 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001479 return false;
1480 }
1481
1482 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1483 !context->isBufferGenerated(buffer))
1484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001486 return false;
1487 }
1488
1489 const Caps &caps = context->getCaps();
1490 switch (target)
1491 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001492 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001493 {
1494 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(InvalidValue() << "index is greater than or equal to the "
1497 "number of TRANSFORM_FEEDBACK_BUFFER "
1498 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001499 return false;
1500 }
1501 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 return false;
1505 }
1506
1507 TransformFeedback *curTransformFeedback =
1508 context->getGLState().getCurrentTransformFeedback();
1509 if (curTransformFeedback && curTransformFeedback->isActive())
1510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001511 context->handleError(InvalidOperation()
1512 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1513 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001514 return false;
1515 }
1516 break;
1517 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001518 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001519 {
1520 if (index >= caps.maxUniformBufferBindings)
1521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001522 context->handleError(InvalidValue() << "index is greater than or equal to the "
1523 "number of UNIFORM_BUFFER indexed "
1524 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001525 return false;
1526 }
1527
1528 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1529 {
1530 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001531 InvalidValue()
1532 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001533 return false;
1534 }
1535 break;
1536 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001537 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001538 {
1539 if (context->getClientVersion() < ES_3_1)
1540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidEnum()
1542 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001543 return false;
1544 }
1545 if (index >= caps.maxAtomicCounterBufferBindings)
1546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 context->handleError(InvalidValue() << "index is greater than or equal to the "
1548 "number of ATOMIC_COUNTER_BUFFER "
1549 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001550 return false;
1551 }
1552 if (buffer != 0 && (offset % 4) != 0)
1553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001554 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001555 return false;
1556 }
1557 break;
1558 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001559 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001560 {
1561 if (context->getClientVersion() < ES_3_1)
1562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidEnum()
1564 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001565 return false;
1566 }
1567 if (index >= caps.maxShaderStorageBufferBindings)
1568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001569 context->handleError(InvalidValue() << "index is greater than or equal to the "
1570 "number of SHADER_STORAGE_BUFFER "
1571 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001572 return false;
1573 }
1574 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidValue() << "offset must be multiple of value of "
1577 "SHADER_STORAGE_BUFFER_OFFSET_"
1578 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001579 return false;
1580 }
1581 break;
1582 }
1583 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001584 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001585 return false;
1586 }
1587
1588 return true;
1589}
1590
Corentin Wallez336129f2017-10-17 15:55:40 -04001591bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001592{
1593 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1594}
1595
1596bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001597 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001598 GLuint index,
1599 GLuint buffer,
1600 GLintptr offset,
1601 GLsizeiptr size)
1602{
1603 if (buffer != 0 && size <= 0)
1604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001605 context->handleError(InvalidValue()
1606 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001607 return false;
1608 }
1609 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1610}
1611
Geoff Langc5629752015-12-07 16:29:04 -05001612bool ValidateProgramBinary(Context *context,
1613 GLuint program,
1614 GLenum binaryFormat,
1615 const void *binary,
1616 GLint length)
1617{
Martin Radev1be913c2016-07-11 17:59:16 +03001618 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001619 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001620 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001621 return false;
1622 }
1623
1624 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1625}
1626
1627bool ValidateGetProgramBinary(Context *context,
1628 GLuint program,
1629 GLsizei bufSize,
1630 GLsizei *length,
1631 GLenum *binaryFormat,
1632 void *binary)
1633{
Martin Radev1be913c2016-07-11 17:59:16 +03001634 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001635 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001637 return false;
1638 }
1639
1640 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1641}
1642
Olli Etuahof0fee072016-03-30 15:11:58 +03001643bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001644{
Martin Radev1be913c2016-07-11 17:59:16 +03001645 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001648 return false;
1649 }
1650
1651 if (GetValidProgram(context, program) == nullptr)
1652 {
1653 return false;
1654 }
1655
1656 switch (pname)
1657 {
1658 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001659 if (value != GL_FALSE && value != GL_TRUE)
1660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001661 context->handleError(InvalidValue()
1662 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001663 return false;
1664 }
Geoff Langc5629752015-12-07 16:29:04 -05001665 break;
1666
Yunchao He61afff12017-03-14 15:34:03 +08001667 case GL_PROGRAM_SEPARABLE:
1668 if (context->getClientVersion() < ES_3_1)
1669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidEnum()
1671 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001672 return false;
1673 }
1674
1675 if (value != GL_FALSE && value != GL_TRUE)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidValue()
1678 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001679 return false;
1680 }
1681 break;
1682
Geoff Langc5629752015-12-07 16:29:04 -05001683 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001684 context->handleError(InvalidEnum()
1685 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001686 return false;
1687 }
1688
1689 return true;
1690}
Jamie Madillc29968b2016-01-20 11:17:23 -05001691
1692bool ValidateBlitFramebuffer(Context *context,
1693 GLint srcX0,
1694 GLint srcY0,
1695 GLint srcX1,
1696 GLint srcY1,
1697 GLint dstX0,
1698 GLint dstY0,
1699 GLint dstX1,
1700 GLint dstY1,
1701 GLbitfield mask,
1702 GLenum filter)
1703{
Martin Radev1be913c2016-07-11 17:59:16 +03001704 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001705 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001707 return false;
1708 }
1709
1710 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1711 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001712}
Jamie Madillc29968b2016-01-20 11:17:23 -05001713
1714bool ValidateClearBufferiv(ValidationContext *context,
1715 GLenum buffer,
1716 GLint drawbuffer,
1717 const GLint *value)
1718{
1719 switch (buffer)
1720 {
1721 case GL_COLOR:
1722 if (drawbuffer < 0 ||
1723 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 return false;
1727 }
Geoff Lang76e65652017-03-27 14:58:02 -04001728 if (context->getExtensions().webglCompatibility)
1729 {
1730 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001731 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001732 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1733 {
1734 return false;
1735 }
1736 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 break;
1738
1739 case GL_STENCIL:
1740 if (drawbuffer != 0)
1741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001742 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 return false;
1744 }
1745 break;
1746
1747 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001749 return false;
1750 }
1751
1752 return ValidateClearBuffer(context);
1753}
1754
1755bool ValidateClearBufferuiv(ValidationContext *context,
1756 GLenum buffer,
1757 GLint drawbuffer,
1758 const GLuint *value)
1759{
1760 switch (buffer)
1761 {
1762 case GL_COLOR:
1763 if (drawbuffer < 0 ||
1764 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001767 return false;
1768 }
Geoff Lang76e65652017-03-27 14:58:02 -04001769 if (context->getExtensions().webglCompatibility)
1770 {
1771 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001772 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001773 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1774 {
1775 return false;
1776 }
1777 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001778 break;
1779
1780 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001781 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001782 return false;
1783 }
1784
1785 return ValidateClearBuffer(context);
1786}
1787
1788bool ValidateClearBufferfv(ValidationContext *context,
1789 GLenum buffer,
1790 GLint drawbuffer,
1791 const GLfloat *value)
1792{
1793 switch (buffer)
1794 {
1795 case GL_COLOR:
1796 if (drawbuffer < 0 ||
1797 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001800 return false;
1801 }
Geoff Lang76e65652017-03-27 14:58:02 -04001802 if (context->getExtensions().webglCompatibility)
1803 {
1804 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1805 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001806 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001807 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1808 {
1809 return false;
1810 }
1811 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 break;
1813
1814 case GL_DEPTH:
1815 if (drawbuffer != 0)
1816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001817 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001818 return false;
1819 }
1820 break;
1821
1822 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001823 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 return false;
1825 }
1826
1827 return ValidateClearBuffer(context);
1828}
1829
1830bool ValidateClearBufferfi(ValidationContext *context,
1831 GLenum buffer,
1832 GLint drawbuffer,
1833 GLfloat depth,
1834 GLint stencil)
1835{
1836 switch (buffer)
1837 {
1838 case GL_DEPTH_STENCIL:
1839 if (drawbuffer != 0)
1840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001841 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001842 return false;
1843 }
1844 break;
1845
1846 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001847 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001848 return false;
1849 }
1850
1851 return ValidateClearBuffer(context);
1852}
1853
1854bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1855{
Martin Radev1be913c2016-07-11 17:59:16 +03001856 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001857 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001858 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001859 return false;
1860 }
1861
1862 return ValidateDrawBuffersBase(context, n, bufs);
1863}
1864
1865bool ValidateCopyTexSubImage3D(Context *context,
1866 GLenum target,
1867 GLint level,
1868 GLint xoffset,
1869 GLint yoffset,
1870 GLint zoffset,
1871 GLint x,
1872 GLint y,
1873 GLsizei width,
1874 GLsizei height)
1875{
Martin Radev1be913c2016-07-11 17:59:16 +03001876 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001877 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001878 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001879 return false;
1880 }
1881
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001882 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1883 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001884}
1885
Jamie Madill73a84962016-02-12 09:27:23 -05001886bool ValidateTexImage3D(Context *context,
1887 GLenum target,
1888 GLint level,
1889 GLint internalformat,
1890 GLsizei width,
1891 GLsizei height,
1892 GLsizei depth,
1893 GLint border,
1894 GLenum format,
1895 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001896 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001897{
Martin Radev1be913c2016-07-11 17:59:16 +03001898 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001899 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001900 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001901 return false;
1902 }
1903
1904 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001905 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001906 pixels);
1907}
1908
Geoff Langc52f6f12016-10-14 10:18:00 -04001909bool ValidateTexImage3DRobustANGLE(Context *context,
1910 GLenum target,
1911 GLint level,
1912 GLint internalformat,
1913 GLsizei width,
1914 GLsizei height,
1915 GLsizei depth,
1916 GLint border,
1917 GLenum format,
1918 GLenum type,
1919 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001920 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001921{
1922 if (context->getClientMajorVersion() < 3)
1923 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001925 return false;
1926 }
1927
1928 if (!ValidateRobustEntryPoint(context, bufSize))
1929 {
1930 return false;
1931 }
1932
1933 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1934 0, 0, width, height, depth, border, format, type,
1935 bufSize, pixels);
1936}
1937
Jamie Madill73a84962016-02-12 09:27:23 -05001938bool ValidateTexSubImage3D(Context *context,
1939 GLenum target,
1940 GLint level,
1941 GLint xoffset,
1942 GLint yoffset,
1943 GLint zoffset,
1944 GLsizei width,
1945 GLsizei height,
1946 GLsizei depth,
1947 GLenum format,
1948 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001949 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001950{
Martin Radev1be913c2016-07-11 17:59:16 +03001951 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001952 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001953 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001954 return false;
1955 }
1956
1957 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1958 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001959 -1, pixels);
1960}
1961
1962bool ValidateTexSubImage3DRobustANGLE(Context *context,
1963 GLenum target,
1964 GLint level,
1965 GLint xoffset,
1966 GLint yoffset,
1967 GLint zoffset,
1968 GLsizei width,
1969 GLsizei height,
1970 GLsizei depth,
1971 GLenum format,
1972 GLenum type,
1973 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001974 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001975{
1976 if (context->getClientMajorVersion() < 3)
1977 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001979 return false;
1980 }
1981
1982 if (!ValidateRobustEntryPoint(context, bufSize))
1983 {
1984 return false;
1985 }
1986
1987 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1988 yoffset, zoffset, width, height, depth, 0, format, type,
1989 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001990}
1991
1992bool ValidateCompressedTexSubImage3D(Context *context,
1993 GLenum target,
1994 GLint level,
1995 GLint xoffset,
1996 GLint yoffset,
1997 GLint zoffset,
1998 GLsizei width,
1999 GLsizei height,
2000 GLsizei depth,
2001 GLenum format,
2002 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002003 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002004{
Martin Radev1be913c2016-07-11 17:59:16 +03002005 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002006 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002008 return false;
2009 }
2010
Geoff Langca271392017-04-05 12:30:00 -04002011 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002012 if (!formatInfo.compressed)
2013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002014 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002015 return false;
2016 }
2017
Jamie Madill513558d2016-06-02 13:04:11 -04002018 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002019 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002020 if (blockSizeOrErr.isError())
2021 {
2022 context->handleError(blockSizeOrErr.getError());
2023 return false;
2024 }
2025 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002027 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002028 return false;
2029 }
2030
2031 if (!data)
2032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002033 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002034 return false;
2035 }
2036
Geoff Lang5ca5c652017-10-27 17:29:54 -04002037 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2038 yoffset, zoffset, width, height, depth, 0, format,
2039 GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002040}
Corentin Wallezb2931602017-04-11 15:58:57 -04002041bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2042 GLenum target,
2043 GLint level,
2044 GLint xoffset,
2045 GLint yoffset,
2046 GLint zoffset,
2047 GLsizei width,
2048 GLsizei height,
2049 GLsizei depth,
2050 GLenum format,
2051 GLsizei imageSize,
2052 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002053 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002054{
2055 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2056 {
2057 return false;
2058 }
2059
2060 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2061 height, depth, format, imageSize, data);
2062}
Jamie Madill73a84962016-02-12 09:27:23 -05002063
Olli Etuaho41997e72016-03-10 13:38:39 +02002064bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2065{
2066 return ValidateGenOrDeleteES3(context, n);
2067}
2068
2069bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2070{
2071 return ValidateGenOrDeleteES3(context, n);
2072}
2073
2074bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2075{
2076 return ValidateGenOrDeleteCountES3(context, count);
2077}
2078
2079bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2080{
2081 return ValidateGenOrDeleteCountES3(context, count);
2082}
2083
2084bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2085{
2086 return ValidateGenOrDeleteES3(context, n);
2087}
2088
2089bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2090{
2091 if (!ValidateGenOrDeleteES3(context, n))
2092 {
2093 return false;
2094 }
2095 for (GLint i = 0; i < n; ++i)
2096 {
2097 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2098 if (transformFeedback != nullptr && transformFeedback->isActive())
2099 {
2100 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002101 context->handleError(InvalidOperation()
2102 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002103 return false;
2104 }
2105 }
2106 return true;
2107}
2108
2109bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2110{
2111 return ValidateGenOrDeleteES3(context, n);
2112}
2113
2114bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2115{
2116 return ValidateGenOrDeleteES3(context, n);
2117}
2118
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002119bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2120{
Martin Radev1be913c2016-07-11 17:59:16 +03002121 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002124 return false;
2125 }
2126 switch (primitiveMode)
2127 {
2128 case GL_TRIANGLES:
2129 case GL_LINES:
2130 case GL_POINTS:
2131 break;
2132
2133 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002134 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002135 return false;
2136 }
2137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002138 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002139 ASSERT(transformFeedback != nullptr);
2140
2141 if (transformFeedback->isActive())
2142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002144 return false;
2145 }
Geoff Lang79f71042017-08-14 16:43:43 -04002146
2147 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2148 {
2149 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2150 if (buffer.get() && buffer->isMapped())
2151 {
2152 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2153 return false;
2154 }
2155 }
2156
Olli Etuaho02032bd2017-10-13 18:10:17 +03002157 auto program = context->getGLState().getProgram();
2158
2159 if (!program)
2160 {
2161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2162 return false;
2163 }
2164
2165 if (program->getTransformFeedbackVaryingCount() == 0)
2166 {
2167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2168 return false;
2169 }
2170
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002171 return true;
2172}
2173
Corentin Wallez336129f2017-10-17 15:55:40 -04002174bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002175{
Geoff Lang496c02d2016-10-20 11:38:11 -07002176 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2177}
2178
2179bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002180 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002181 GLenum pname,
2182 GLsizei bufSize,
2183 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002184 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002185{
2186 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002187 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002188 return false;
2189 }
2190
Geoff Lang496c02d2016-10-20 11:38:11 -07002191 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2192 {
2193 return false;
2194 }
2195
2196 if (!ValidateRobustBufferSize(context, bufSize, *length))
2197 {
2198 return false;
2199 }
2200
2201 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002202}
2203
Corentin Wallez336129f2017-10-17 15:55:40 -04002204bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002205{
Martin Radev1be913c2016-07-11 17:59:16 +03002206 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002209 return false;
2210 }
2211
2212 return ValidateUnmapBufferBase(context, target);
2213}
2214
2215bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002216 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002217 GLintptr offset,
2218 GLsizeiptr length,
2219 GLbitfield access)
2220{
Martin Radev1be913c2016-07-11 17:59:16 +03002221 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002222 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002223 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002224 return false;
2225 }
2226
2227 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2228}
2229
2230bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002231 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002232 GLintptr offset,
2233 GLsizeiptr length)
2234{
Martin Radev1be913c2016-07-11 17:59:16 +03002235 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002236 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002238 return false;
2239 }
2240
2241 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2242}
2243
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002244bool ValidateIndexedStateQuery(ValidationContext *context,
2245 GLenum pname,
2246 GLuint index,
2247 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002248{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002249 if (length)
2250 {
2251 *length = 0;
2252 }
2253
Martin Radev66fb8202016-07-28 11:45:20 +03002254 GLenum nativeType;
2255 unsigned int numParams;
2256 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002258 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002259 return false;
2260 }
2261
2262 const Caps &caps = context->getCaps();
2263 switch (pname)
2264 {
2265 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2266 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2267 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2268 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002270 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002271 return false;
2272 }
2273 break;
2274
2275 case GL_UNIFORM_BUFFER_START:
2276 case GL_UNIFORM_BUFFER_SIZE:
2277 case GL_UNIFORM_BUFFER_BINDING:
2278 if (index >= caps.maxUniformBufferBindings)
2279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002280 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002281 return false;
2282 }
2283 break;
Shao80957d92017-02-20 21:25:59 +08002284
Martin Radev66fb8202016-07-28 11:45:20 +03002285 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2286 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2287 if (index >= 3u)
2288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002289 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002290 return false;
2291 }
2292 break;
Shao80957d92017-02-20 21:25:59 +08002293
Jiajia Qin6eafb042016-12-27 17:04:07 +08002294 case GL_ATOMIC_COUNTER_BUFFER_START:
2295 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2296 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2297 if (context->getClientVersion() < ES_3_1)
2298 {
2299 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002300 InvalidEnum()
2301 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002302 return false;
2303 }
2304 if (index >= caps.maxAtomicCounterBufferBindings)
2305 {
2306 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002307 InvalidValue()
2308 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002309 return false;
2310 }
2311 break;
Shao80957d92017-02-20 21:25:59 +08002312
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002313 case GL_SHADER_STORAGE_BUFFER_START:
2314 case GL_SHADER_STORAGE_BUFFER_SIZE:
2315 case GL_SHADER_STORAGE_BUFFER_BINDING:
2316 if (context->getClientVersion() < ES_3_1)
2317 {
2318 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002319 InvalidEnum()
2320 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002321 return false;
2322 }
2323 if (index >= caps.maxShaderStorageBufferBindings)
2324 {
2325 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002326 InvalidValue()
2327 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002328 return false;
2329 }
2330 break;
2331
Shao80957d92017-02-20 21:25:59 +08002332 case GL_VERTEX_BINDING_BUFFER:
2333 case GL_VERTEX_BINDING_DIVISOR:
2334 case GL_VERTEX_BINDING_OFFSET:
2335 case GL_VERTEX_BINDING_STRIDE:
2336 if (context->getClientVersion() < ES_3_1)
2337 {
2338 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002339 InvalidEnum()
2340 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002341 return false;
2342 }
2343 if (index >= caps.maxVertexAttribBindings)
2344 {
2345 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002346 InvalidValue()
2347 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002348 return false;
2349 }
2350 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002351 case GL_SAMPLE_MASK_VALUE:
2352 if (context->getClientVersion() < ES_3_1)
2353 {
2354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2355 return false;
2356 }
2357 if (index >= caps.maxSampleMaskWords)
2358 {
2359 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2360 return false;
2361 }
2362 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002363 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002365 return false;
2366 }
2367
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002368 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002369 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002370 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002371 }
2372
2373 return true;
2374}
2375
2376bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2377{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002378 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002379 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002381 return false;
2382 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002383 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002384}
2385
Geoff Langcf255ea2016-10-20 11:39:09 -07002386bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2387 GLenum target,
2388 GLuint index,
2389 GLsizei bufSize,
2390 GLsizei *length,
2391 GLint *data)
2392{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002393 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002394 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002395 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002396 return false;
2397 }
2398
2399 if (!ValidateRobustEntryPoint(context, bufSize))
2400 {
2401 return false;
2402 }
2403
2404 if (!ValidateIndexedStateQuery(context, target, index, length))
2405 {
2406 return false;
2407 }
2408
2409 if (!ValidateRobustBufferSize(context, bufSize, *length))
2410 {
2411 return false;
2412 }
2413
2414 return true;
2415}
2416
Martin Radev66fb8202016-07-28 11:45:20 +03002417bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2418{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002419 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002420 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002421 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002422 return false;
2423 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002424 return ValidateIndexedStateQuery(context, target, index, nullptr);
2425}
2426
2427bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2428 GLenum target,
2429 GLuint index,
2430 GLsizei bufSize,
2431 GLsizei *length,
2432 GLint64 *data)
2433{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002434 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002437 return false;
2438 }
2439
2440 if (!ValidateRobustEntryPoint(context, bufSize))
2441 {
2442 return false;
2443 }
2444
2445 if (!ValidateIndexedStateQuery(context, target, index, length))
2446 {
2447 return false;
2448 }
2449
2450 if (!ValidateRobustBufferSize(context, bufSize, *length))
2451 {
2452 return false;
2453 }
2454
2455 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002456}
2457
Jamie Madillb0817d12016-11-01 15:48:31 -04002458bool ValidateCopyBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002459 BufferBinding readTarget,
2460 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002461 GLintptr readOffset,
2462 GLintptr writeOffset,
2463 GLsizeiptr size)
2464{
2465 if (context->getClientMajorVersion() < 3)
2466 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002468 return false;
2469 }
2470
Corentin Wallez336129f2017-10-17 15:55:40 -04002471 if (!ValidBufferType(context, readTarget) || !ValidBufferType(context, writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002473 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002474 return false;
2475 }
2476
2477 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2478 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2479
2480 if (!readBuffer || !writeBuffer)
2481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002482 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002483 return false;
2484 }
2485
2486 // Verify that readBuffer and writeBuffer are not currently mapped
2487 if (readBuffer->isMapped() || writeBuffer->isMapped())
2488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002489 context->handleError(InvalidOperation()
2490 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002491 return false;
2492 }
2493
Jamie Madilld2f0c742016-11-02 10:34:41 -04002494 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2495 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2496 CheckedNumeric<GLintptr> checkedSize(size);
2497
2498 auto checkedReadSum = checkedReadOffset + checkedSize;
2499 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2500
2501 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2502 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2503 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002505 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002506 return false;
2507 }
2508
Jamie Madilld2f0c742016-11-02 10:34:41 -04002509 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidValue()
2512 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002513 return false;
2514 }
2515
Jamie Madilld2f0c742016-11-02 10:34:41 -04002516 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2517 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002519 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002520 return false;
2521 }
2522
2523 if (readBuffer == writeBuffer)
2524 {
2525 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2526 if (!checkedOffsetDiff.IsValid())
2527 {
2528 // This shold not be possible.
2529 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002530 context->handleError(InvalidValue()
2531 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002532 return false;
2533 }
2534
2535 if (checkedOffsetDiff.ValueOrDie() < size)
2536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002537 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002538 return false;
2539 }
2540 }
2541
Jamie Madillb0817d12016-11-01 15:48:31 -04002542 return true;
2543}
2544
Geoff Langc339c4e2016-11-29 10:37:36 -05002545bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2546{
2547 if (context->getClientMajorVersion() < 3)
2548 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002550 return false;
2551 }
2552
2553 switch (name)
2554 {
2555 case GL_EXTENSIONS:
2556 if (index >= context->getExtensionStringCount())
2557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002558 context->handleError(InvalidValue()
2559 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002560 return false;
2561 }
2562 break;
2563
2564 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2565 if (!context->getExtensions().requestExtension)
2566 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002568 return false;
2569 }
2570 if (index >= context->getRequestableExtensionStringCount())
2571 {
2572 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002573 InvalidValue()
2574 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002575 return false;
2576 }
2577 break;
2578
2579 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002581 return false;
2582 }
2583
2584 return true;
2585}
2586
Jamie Madille8fb6402017-02-14 17:56:40 -05002587bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2588 GLenum target,
2589 GLsizei samples,
2590 GLenum internalformat,
2591 GLsizei width,
2592 GLsizei height)
2593{
2594 if (context->getClientMajorVersion() < 3)
2595 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002597 return false;
2598 }
2599
2600 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2601 height))
2602 {
2603 return false;
2604 }
2605
2606 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2607 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002608 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002609 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2610 samples > 0)
2611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002612 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002613 return false;
2614 }
2615
2616 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2617 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2618 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2619 {
2620 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002621 InvalidOperation()
2622 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002623 return false;
2624 }
2625
2626 return true;
2627}
2628
Geoff Langaa086d62017-03-23 16:47:21 -04002629bool ValidateVertexAttribIPointer(ValidationContext *context,
2630 GLuint index,
2631 GLint size,
2632 GLenum type,
2633 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002634 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002635{
2636 if (context->getClientMajorVersion() < 3)
2637 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002639 return false;
2640 }
2641
Shao80957d92017-02-20 21:25:59 +08002642 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002643 {
Geoff Langaa086d62017-03-23 16:47:21 -04002644 return false;
2645 }
2646
Geoff Langaa086d62017-03-23 16:47:21 -04002647 if (stride < 0)
2648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002650 return false;
2651 }
2652
Shao80957d92017-02-20 21:25:59 +08002653 const Caps &caps = context->getCaps();
2654 if (context->getClientVersion() >= ES_3_1)
2655 {
2656 if (stride > caps.maxVertexAttribStride)
2657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002658 context->handleError(InvalidValue()
2659 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002660 return false;
2661 }
2662
2663 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2664 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2665 // validation should be inherited.
2666 if (index >= caps.maxVertexAttribBindings)
2667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002668 context->handleError(InvalidValue()
2669 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002670 return false;
2671 }
2672 }
2673
Geoff Langaa086d62017-03-23 16:47:21 -04002674 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2675 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2676 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2677 // and the pointer argument is not NULL.
2678 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002679 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002681 context
2682 ->handleError(InvalidOperation()
2683 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002684 return false;
2685 }
2686
Geoff Lang2d62ab72017-03-23 16:54:40 -04002687 if (context->getExtensions().webglCompatibility)
2688 {
2689 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2690 {
2691 return false;
2692 }
2693 }
2694
Geoff Langaa086d62017-03-23 16:47:21 -04002695 return true;
2696}
2697
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002698bool ValidateGetSynciv(Context *context,
2699 GLsync sync,
2700 GLenum pname,
2701 GLsizei bufSize,
2702 GLsizei *length,
2703 GLint *values)
2704{
2705 if (context->getClientMajorVersion() < 3)
2706 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002708 return false;
2709 }
2710
2711 if (bufSize < 0)
2712 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002713 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002714 return false;
2715 }
2716
Jamie Madill70b5bb02017-08-28 13:32:37 -04002717 Sync *syncObject = context->getSync(sync);
2718 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002720 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002721 return false;
2722 }
2723
2724 switch (pname)
2725 {
2726 case GL_OBJECT_TYPE:
2727 case GL_SYNC_CONDITION:
2728 case GL_SYNC_FLAGS:
2729 case GL_SYNC_STATUS:
2730 break;
2731
2732 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002733 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002734 return false;
2735 }
2736
2737 return true;
2738}
2739
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002740bool ValidateDrawElementsInstanced(ValidationContext *context,
2741 GLenum mode,
2742 GLsizei count,
2743 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002744 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002745 GLsizei instanceCount)
2746{
2747 if (context->getClientMajorVersion() < 3)
2748 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002749 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002750 return false;
2751 }
2752
2753 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2754}
2755
Martin Radev137032d2017-07-13 10:11:12 +03002756bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2757 GLenum target,
2758 GLenum attachment,
2759 GLuint texture,
2760 GLint level,
2761 GLint baseViewIndex,
2762 GLsizei numViews)
2763{
2764
2765 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2766 numViews))
2767 {
2768 return false;
2769 }
2770
Martin Radev137032d2017-07-13 10:11:12 +03002771 if (texture != 0)
2772 {
Martin Radev14b21262017-08-25 13:54:37 +03002773 if (baseViewIndex < 0)
2774 {
2775 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2776 return false;
2777 }
2778
Martin Radev137032d2017-07-13 10:11:12 +03002779 Texture *tex = context->getTexture(texture);
2780 ASSERT(tex);
2781
2782 switch (tex->getTarget())
2783 {
2784 case GL_TEXTURE_2D_ARRAY:
2785 {
2786 const Caps &caps = context->getCaps();
2787 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2788 {
2789 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2790 "greater than "
2791 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2792 return false;
2793 }
2794 }
2795 break;
2796 default:
2797 context->handleError(InvalidOperation()
2798 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2799 return false;
2800 }
2801
2802 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2803 {
2804 return false;
2805 }
2806 }
2807
2808 return true;
2809}
2810
2811bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2812 GLenum target,
2813 GLenum attachment,
2814 GLuint texture,
2815 GLint level,
2816 GLsizei numViews,
2817 const GLint *viewportOffsets)
2818{
2819 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2820 numViews))
2821 {
2822 return false;
2823 }
2824
Martin Radev137032d2017-07-13 10:11:12 +03002825 if (texture != 0)
2826 {
Martin Radev14b21262017-08-25 13:54:37 +03002827 const GLsizei numViewportOffsetValues = numViews * 2;
2828 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2829 {
2830 if (viewportOffsets[i] < 0)
2831 {
2832 context->handleError(InvalidValue()
2833 << "viewportOffsets cannot contain negative values.");
2834 return false;
2835 }
2836 }
2837
Martin Radev137032d2017-07-13 10:11:12 +03002838 Texture *tex = context->getTexture(texture);
2839 ASSERT(tex);
2840
2841 switch (tex->getTarget())
2842 {
2843 case GL_TEXTURE_2D:
2844 break;
2845 default:
2846 context->handleError(InvalidOperation()
2847 << "Texture's target must be GL_TEXTURE_2D.");
2848 return false;
2849 }
2850
2851 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2852 {
2853 return false;
2854 }
2855 }
2856
2857 return true;
2858}
2859
Jamie Madillff325f12017-08-26 15:06:05 -04002860bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2861{
2862 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2863}
2864
2865bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2866{
2867 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2868}
2869
2870bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2871{
2872 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2873}
2874
2875bool ValidateUniform4ui(Context *context,
2876 GLint location,
2877 GLuint v0,
2878 GLuint v1,
2879 GLuint v2,
2880 GLuint v3)
2881{
2882 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2883}
2884
2885bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2886{
2887 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2888}
2889
2890bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2891{
2892 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2893}
2894
2895bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2896{
2897 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2898}
2899
2900bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2901{
2902 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2903}
2904
Jamie Madillf0e04492017-08-26 15:28:42 -04002905bool ValidateIsQuery(Context *context, GLuint id)
2906{
2907 if (context->getClientMajorVersion() < 3)
2908 {
2909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2910 return false;
2911 }
2912
2913 return true;
2914}
2915
Jamie Madillc8c95812017-08-26 18:40:09 -04002916bool ValidateUniformMatrix2x3fv(Context *context,
2917 GLint location,
2918 GLsizei count,
2919 GLboolean transpose,
2920 const GLfloat *value)
2921{
2922 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2923}
2924
2925bool ValidateUniformMatrix3x2fv(Context *context,
2926 GLint location,
2927 GLsizei count,
2928 GLboolean transpose,
2929 const GLfloat *value)
2930{
2931 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2932}
2933
2934bool ValidateUniformMatrix2x4fv(Context *context,
2935 GLint location,
2936 GLsizei count,
2937 GLboolean transpose,
2938 const GLfloat *value)
2939{
2940 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2941}
2942
2943bool ValidateUniformMatrix4x2fv(Context *context,
2944 GLint location,
2945 GLsizei count,
2946 GLboolean transpose,
2947 const GLfloat *value)
2948{
2949 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2950}
2951
2952bool ValidateUniformMatrix3x4fv(Context *context,
2953 GLint location,
2954 GLsizei count,
2955 GLboolean transpose,
2956 const GLfloat *value)
2957{
2958 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2959}
2960
2961bool ValidateUniformMatrix4x3fv(Context *context,
2962 GLint location,
2963 GLsizei count,
2964 GLboolean transpose,
2965 const GLfloat *value)
2966{
2967 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2968}
2969
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002970bool ValidateEndTransformFeedback(Context *context)
2971{
2972 if (context->getClientMajorVersion() < 3)
2973 {
2974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2975 return false;
2976 }
2977
2978 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2979 ASSERT(transformFeedback != nullptr);
2980
2981 if (!transformFeedback->isActive())
2982 {
2983 context->handleError(InvalidOperation());
2984 return false;
2985 }
2986
2987 return true;
2988}
2989
2990bool ValidateTransformFeedbackVaryings(Context *context,
2991 GLuint program,
2992 GLsizei count,
2993 const GLchar *const *varyings,
2994 GLenum bufferMode)
2995{
2996 if (context->getClientMajorVersion() < 3)
2997 {
2998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2999 return false;
3000 }
3001
3002 if (count < 0)
3003 {
3004 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3005 return false;
3006 }
3007
3008 switch (bufferMode)
3009 {
3010 case GL_INTERLEAVED_ATTRIBS:
3011 break;
3012 case GL_SEPARATE_ATTRIBS:
3013 {
3014 const Caps &caps = context->getCaps();
3015 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3016 {
3017 context->handleError(InvalidValue());
3018 return false;
3019 }
3020 break;
3021 }
3022 default:
3023 context->handleError(InvalidEnum());
3024 return false;
3025 }
3026
3027 Program *programObject = GetValidProgram(context, program);
3028 if (!programObject)
3029 {
3030 return false;
3031 }
3032
3033 return true;
3034}
3035
3036bool ValidateGetTransformFeedbackVarying(Context *context,
3037 GLuint program,
3038 GLuint index,
3039 GLsizei bufSize,
3040 GLsizei *length,
3041 GLsizei *size,
3042 GLenum *type,
3043 GLchar *name)
3044{
3045 if (context->getClientMajorVersion() < 3)
3046 {
3047 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3048 return false;
3049 }
3050
3051 if (bufSize < 0)
3052 {
3053 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3054 return false;
3055 }
3056
3057 Program *programObject = GetValidProgram(context, program);
3058 if (!programObject)
3059 {
3060 return false;
3061 }
3062
3063 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3064 {
3065 context->handleError(InvalidValue());
3066 return false;
3067 }
3068
3069 return true;
3070}
3071
3072bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3073{
3074 if (context->getClientMajorVersion() < 3)
3075 {
3076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3077 return false;
3078 }
3079
3080 switch (target)
3081 {
3082 case GL_TRANSFORM_FEEDBACK:
3083 {
3084 // Cannot bind a transform feedback object if the current one is started and not
3085 // paused (3.0.2 pg 85 section 2.14.1)
3086 TransformFeedback *curTransformFeedback =
3087 context->getGLState().getCurrentTransformFeedback();
3088 if (curTransformFeedback && curTransformFeedback->isActive() &&
3089 !curTransformFeedback->isPaused())
3090 {
3091 context->handleError(InvalidOperation());
3092 return false;
3093 }
3094
3095 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3096 // 2.14.1)
3097 if (!context->isTransformFeedbackGenerated(id))
3098 {
3099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3100 return false;
3101 }
3102 }
3103 break;
3104
3105 default:
3106 context->handleError(InvalidEnum());
3107 return false;
3108 }
3109
3110 return true;
3111}
3112
3113bool ValidateIsTransformFeedback(Context *context, GLuint id)
3114{
3115 if (context->getClientMajorVersion() < 3)
3116 {
3117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3118 return false;
3119 }
3120
3121 return true;
3122}
3123
3124bool ValidatePauseTransformFeedback(Context *context)
3125{
3126 if (context->getClientMajorVersion() < 3)
3127 {
3128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3129 return false;
3130 }
3131
3132 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3133 ASSERT(transformFeedback != nullptr);
3134
3135 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3136 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3137 {
3138 context->handleError(InvalidOperation());
3139 return false;
3140 }
3141
3142 return true;
3143}
3144
3145bool ValidateResumeTransformFeedback(Context *context)
3146{
3147 if (context->getClientMajorVersion() < 3)
3148 {
3149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3150 return false;
3151 }
3152
3153 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3154 ASSERT(transformFeedback != nullptr);
3155
3156 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3157 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3158 {
3159 context->handleError(InvalidOperation());
3160 return false;
3161 }
3162
3163 return true;
3164}
3165
Jamie Madill12e957f2017-08-26 21:42:26 -04003166bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3167{
3168 if (context->getClientMajorVersion() < 3)
3169 {
3170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3171 return false;
3172 }
3173
3174 return ValidateVertexAttribIndex(context, index);
3175}
3176
3177bool ValidateVertexAttribI4ui(Context *context,
3178 GLuint index,
3179 GLuint x,
3180 GLuint y,
3181 GLuint z,
3182 GLuint w)
3183{
3184 if (context->getClientMajorVersion() < 3)
3185 {
3186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3187 return false;
3188 }
3189
3190 return ValidateVertexAttribIndex(context, index);
3191}
3192
3193bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3194{
3195 if (context->getClientMajorVersion() < 3)
3196 {
3197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3198 return false;
3199 }
3200
3201 return ValidateVertexAttribIndex(context, index);
3202}
3203
3204bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3205{
3206 if (context->getClientMajorVersion() < 3)
3207 {
3208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3209 return false;
3210 }
3211
3212 return ValidateVertexAttribIndex(context, index);
3213}
3214
3215bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3216{
3217 if (context->getClientMajorVersion() < 3)
3218 {
3219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3220 return false;
3221 }
3222
3223 Program *programObject = GetValidProgram(context, program);
3224 if (!programObject)
3225 {
3226 return false;
3227 }
3228
3229 if (!programObject->isLinked())
3230 {
3231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3232 return false;
3233 }
3234
3235 return true;
3236}
3237
3238bool ValidateGetUniformIndices(Context *context,
3239 GLuint program,
3240 GLsizei uniformCount,
3241 const GLchar *const *uniformNames,
3242 GLuint *uniformIndices)
3243{
3244 if (context->getClientMajorVersion() < 3)
3245 {
3246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3247 return false;
3248 }
3249
3250 if (uniformCount < 0)
3251 {
3252 context->handleError(InvalidValue());
3253 return false;
3254 }
3255
3256 Program *programObject = GetValidProgram(context, program);
3257 if (!programObject)
3258 {
3259 return false;
3260 }
3261
3262 return true;
3263}
3264
3265bool ValidateGetActiveUniformsiv(Context *context,
3266 GLuint program,
3267 GLsizei uniformCount,
3268 const GLuint *uniformIndices,
3269 GLenum pname,
3270 GLint *params)
3271{
3272 if (context->getClientMajorVersion() < 3)
3273 {
3274 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3275 return false;
3276 }
3277
3278 if (uniformCount < 0)
3279 {
3280 context->handleError(InvalidValue());
3281 return false;
3282 }
3283
3284 Program *programObject = GetValidProgram(context, program);
3285 if (!programObject)
3286 {
3287 return false;
3288 }
3289
3290 switch (pname)
3291 {
3292 case GL_UNIFORM_TYPE:
3293 case GL_UNIFORM_SIZE:
3294 case GL_UNIFORM_NAME_LENGTH:
3295 case GL_UNIFORM_BLOCK_INDEX:
3296 case GL_UNIFORM_OFFSET:
3297 case GL_UNIFORM_ARRAY_STRIDE:
3298 case GL_UNIFORM_MATRIX_STRIDE:
3299 case GL_UNIFORM_IS_ROW_MAJOR:
3300 break;
3301
3302 default:
3303 context->handleError(InvalidEnum());
3304 return false;
3305 }
3306
3307 if (uniformCount > programObject->getActiveUniformCount())
3308 {
3309 context->handleError(InvalidValue());
3310 return false;
3311 }
3312
3313 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3314 {
3315 const GLuint index = uniformIndices[uniformId];
3316
3317 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3318 {
3319 context->handleError(InvalidValue());
3320 return false;
3321 }
3322 }
3323
3324 return true;
3325}
3326
3327bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3328{
3329 if (context->getClientMajorVersion() < 3)
3330 {
3331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3332 return false;
3333 }
3334
3335 Program *programObject = GetValidProgram(context, program);
3336 if (!programObject)
3337 {
3338 return false;
3339 }
3340
3341 return true;
3342}
3343
3344bool ValidateGetActiveUniformBlockiv(Context *context,
3345 GLuint program,
3346 GLuint uniformBlockIndex,
3347 GLenum pname,
3348 GLint *params)
3349{
3350 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3351}
3352
3353bool ValidateGetActiveUniformBlockName(Context *context,
3354 GLuint program,
3355 GLuint uniformBlockIndex,
3356 GLsizei bufSize,
3357 GLsizei *length,
3358 GLchar *uniformBlockName)
3359{
3360 if (context->getClientMajorVersion() < 3)
3361 {
3362 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3363 return false;
3364 }
3365
3366 Program *programObject = GetValidProgram(context, program);
3367 if (!programObject)
3368 {
3369 return false;
3370 }
3371
3372 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3373 {
3374 context->handleError(InvalidValue());
3375 return false;
3376 }
3377
3378 return true;
3379}
3380
3381bool ValidateUniformBlockBinding(Context *context,
3382 GLuint program,
3383 GLuint uniformBlockIndex,
3384 GLuint uniformBlockBinding)
3385{
3386 if (context->getClientMajorVersion() < 3)
3387 {
3388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3389 return false;
3390 }
3391
3392 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3393 {
3394 context->handleError(InvalidValue());
3395 return false;
3396 }
3397
3398 Program *programObject = GetValidProgram(context, program);
3399 if (!programObject)
3400 {
3401 return false;
3402 }
3403
3404 // if never linked, there won't be any uniform blocks
3405 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3406 {
3407 context->handleError(InvalidValue());
3408 return false;
3409 }
3410
3411 return true;
3412}
3413
3414bool ValidateDrawArraysInstanced(Context *context,
3415 GLenum mode,
3416 GLint first,
3417 GLsizei count,
3418 GLsizei primcount)
3419{
3420 if (context->getClientMajorVersion() < 3)
3421 {
3422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3423 return false;
3424 }
3425
3426 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3427}
3428
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003429bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3430{
3431 if (context->getClientMajorVersion() < 3)
3432 {
3433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3434 return false;
3435 }
3436
3437 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3438 {
3439 context->handleError(InvalidEnum());
3440 return false;
3441 }
3442
3443 if (flags != 0)
3444 {
3445 context->handleError(InvalidValue());
3446 return false;
3447 }
3448
3449 return true;
3450}
3451
3452bool ValidateIsSync(Context *context, GLsync sync)
3453{
3454 if (context->getClientMajorVersion() < 3)
3455 {
3456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3457 return false;
3458 }
3459
3460 return true;
3461}
3462
3463bool ValidateDeleteSync(Context *context, GLsync sync)
3464{
3465 if (context->getClientMajorVersion() < 3)
3466 {
3467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3468 return false;
3469 }
3470
Jamie Madill70b5bb02017-08-28 13:32:37 -04003471 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003472 {
3473 context->handleError(InvalidValue());
3474 return false;
3475 }
3476
3477 return true;
3478}
3479
3480bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3481{
3482 if (context->getClientMajorVersion() < 3)
3483 {
3484 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3485 return false;
3486 }
3487
3488 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3489 {
3490 context->handleError(InvalidValue());
3491 return false;
3492 }
3493
Jamie Madill70b5bb02017-08-28 13:32:37 -04003494 Sync *clientWaitSync = context->getSync(sync);
3495 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003496 {
3497 context->handleError(InvalidValue());
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
3504bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3505{
3506 if (context->getClientMajorVersion() < 3)
3507 {
3508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3509 return false;
3510 }
3511
3512 if (flags != 0)
3513 {
3514 context->handleError(InvalidValue());
3515 return false;
3516 }
3517
3518 if (timeout != GL_TIMEOUT_IGNORED)
3519 {
3520 context->handleError(InvalidValue());
3521 return false;
3522 }
3523
Jamie Madill70b5bb02017-08-28 13:32:37 -04003524 Sync *waitSync = context->getSync(sync);
3525 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003526 {
3527 context->handleError(InvalidValue());
3528 return false;
3529 }
3530
3531 return true;
3532}
3533
3534bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3535{
3536 if (context->getClientMajorVersion() < 3)
3537 {
3538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3539 return false;
3540 }
3541
3542 GLenum nativeType = GL_NONE;
3543 unsigned int numParams = 0;
3544 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3545 {
3546 return false;
3547 }
3548
3549 return true;
3550}
3551
Jamie Madill3ef140a2017-08-26 23:11:21 -04003552bool ValidateIsSampler(Context *context, GLuint sampler)
3553{
3554 if (context->getClientMajorVersion() < 3)
3555 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003557 return false;
3558 }
3559
3560 return true;
3561}
3562
3563bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3564{
3565 if (context->getClientMajorVersion() < 3)
3566 {
3567 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3568 return false;
3569 }
3570
3571 if (sampler != 0 && !context->isSampler(sampler))
3572 {
3573 context->handleError(InvalidOperation());
3574 return false;
3575 }
3576
3577 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3578 {
3579 context->handleError(InvalidValue());
3580 return false;
3581 }
3582
3583 return true;
3584}
3585
3586bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3587{
3588 if (context->getClientMajorVersion() < 3)
3589 {
3590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3591 return false;
3592 }
3593
3594 return ValidateVertexAttribIndex(context, index);
3595}
3596
3597bool ValidateTexStorage2D(Context *context,
3598 GLenum target,
3599 GLsizei levels,
3600 GLenum internalformat,
3601 GLsizei width,
3602 GLsizei height)
3603{
3604 if (context->getClientMajorVersion() < 3)
3605 {
3606 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3607 return false;
3608 }
3609
3610 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3611 1))
3612 {
3613 return false;
3614 }
3615
3616 return true;
3617}
3618
3619bool ValidateTexStorage3D(Context *context,
3620 GLenum target,
3621 GLsizei levels,
3622 GLenum internalformat,
3623 GLsizei width,
3624 GLsizei height,
3625 GLsizei depth)
3626{
3627 if (context->getClientMajorVersion() < 3)
3628 {
3629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3630 return false;
3631 }
3632
3633 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3634 depth))
3635 {
3636 return false;
3637 }
3638
3639 return true;
3640}
3641
Jamie Madill9696d072017-08-26 23:19:57 -04003642bool ValidateGetBufferParameteri64v(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003643 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003644 GLenum pname,
3645 GLint64 *params)
3646{
3647 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3648}
3649
3650bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3651{
3652 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3653}
3654
3655bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3656{
3657 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3658}
3659
3660bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3661{
3662 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3663}
3664
3665bool ValidateSamplerParameterfv(Context *context,
3666 GLuint sampler,
3667 GLenum pname,
3668 const GLfloat *params)
3669{
3670 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3671}
3672
3673bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3674{
3675 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3676}
3677
3678bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3679{
3680 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3681}
3682
3683bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3684{
3685 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3686}
3687
3688bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3689{
3690 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3691}
3692
3693bool ValidateGetInternalformativ(Context *context,
3694 GLenum target,
3695 GLenum internalformat,
3696 GLenum pname,
3697 GLsizei bufSize,
3698 GLint *params)
3699{
3700 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3701 nullptr);
3702}
3703
Jamie Madillc29968b2016-01-20 11:17:23 -05003704} // namespace gl