blob: 1b1387a9662f3e6fa8885dcba7b7dbb4dc03ba57 [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 }
431 }
432
Geoff Langdbcced82017-06-06 15:55:54 -0400433 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
434 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
435 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400436 {
437 return false;
438 }
439
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400440 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700441 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400442 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400443 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800444 // ...data is not evenly divisible into the number of bytes needed to store in memory a
445 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400446 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400447 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400448 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400449 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400450 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
451
Geoff Langff5b2d52016-09-07 11:32:23 -0400452 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500454 context->handleError(InvalidOperation()
455 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400456 return false;
457 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400458 }
459
Jamie Madill7a5f7382014-03-05 15:01:24 -0500460 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700461 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500463 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400464 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500465 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400466 }
467
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 return true;
469}
470
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500471bool ValidateES3TexImage2DParameters(Context *context,
472 GLenum target,
473 GLint level,
474 GLenum internalformat,
475 bool isCompressed,
476 bool isSubImage,
477 GLint xoffset,
478 GLint yoffset,
479 GLint zoffset,
480 GLsizei width,
481 GLsizei height,
482 GLsizei depth,
483 GLint border,
484 GLenum format,
485 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400486 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400487 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500488{
489 if (!ValidTexture2DDestinationTarget(context, target))
490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500491 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500492 return false;
493 }
494
495 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
496 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400497 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500498}
499
500bool ValidateES3TexImage3DParameters(Context *context,
501 GLenum target,
502 GLint level,
503 GLenum internalformat,
504 bool isCompressed,
505 bool isSubImage,
506 GLint xoffset,
507 GLint yoffset,
508 GLint zoffset,
509 GLsizei width,
510 GLsizei height,
511 GLsizei depth,
512 GLint border,
513 GLenum format,
514 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400515 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400516 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500517{
518 if (!ValidTexture3DDestinationTarget(context, target))
519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500520 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500521 return false;
522 }
523
524 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
525 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400526 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500527}
528
Geoff Lang5d601382014-07-22 15:14:06 -0400529struct EffectiveInternalFormatInfo
530{
Jamie Madill76648fe2016-10-05 17:01:41 -0400531 GLenum effectiveFormat;
532 GLenum destFormat;
533 GLuint minRedBits;
534 GLuint maxRedBits;
535 GLuint minGreenBits;
536 GLuint maxGreenBits;
537 GLuint minBlueBits;
538 GLuint maxBlueBits;
539 GLuint minAlphaBits;
540 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400541};
542
Jamie Madill76648fe2016-10-05 17:01:41 -0400543static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
544 GLenum targetFormat,
545 const EffectiveInternalFormatInfo *list,
546 size_t size,
547 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400548{
Jamie Madill76648fe2016-10-05 17:01:41 -0400549 for (size_t curFormat = 0; curFormat < size; ++curFormat)
550 {
551 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
552 if ((formatInfo.destFormat == targetFormat) &&
553 (formatInfo.minRedBits <= srcFormat.redBits &&
554 formatInfo.maxRedBits >= srcFormat.redBits) &&
555 (formatInfo.minGreenBits <= srcFormat.greenBits &&
556 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
557 (formatInfo.minBlueBits <= srcFormat.blueBits &&
558 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
559 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
560 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
561 {
562 *outEffectiveFormat = formatInfo.effectiveFormat;
563 return true;
564 }
565 }
Geoff Lang5d601382014-07-22 15:14:06 -0400566
Jamie Madill76648fe2016-10-05 17:01:41 -0400567 *outEffectiveFormat = GL_NONE;
568 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400569}
570
Jamie Madill76648fe2016-10-05 17:01:41 -0400571bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
572 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400573{
Jamie Madill76648fe2016-10-05 17:01:41 -0400574 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
575 // Effective internal format coresponding to destination internal format and linear source
576 // buffer component sizes.
577 // | Source channel min/max sizes |
578 // Effective Internal Format | N/A | R | G | B | A |
579 // clang-format off
580 constexpr EffectiveInternalFormatInfo list[] = {
581 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
582 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
583 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
584 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
585 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
586 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
587 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
588 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
589 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
590 };
591 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400592
Jamie Madill76648fe2016-10-05 17:01:41 -0400593 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
594}
Geoff Lang5d601382014-07-22 15:14:06 -0400595
Jamie Madill76648fe2016-10-05 17:01:41 -0400596bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
597 const InternalFormat &destFormat,
598 GLenum *outEffectiveFormat)
599{
600 constexpr GLuint umax = UINT_MAX;
601
602 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
603 // Effective internal format coresponding to destination internal format andlinear source buffer
604 // component sizes.
605 // | Source channel min/max sizes |
606 // Effective Internal Format | Dest Format | R | G | B | A |
607 // clang-format off
608 constexpr EffectiveInternalFormatInfo list[] = {
609 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
610 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
611 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
612 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
613 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
614 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
615 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
616 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
617 };
618 // clang-format on
619
620 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
621 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400622}
623
He Yunchaoced53ae2016-11-29 15:00:51 +0800624static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
625 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400626 GLenum *outEffectiveFormat)
627{
Geoff Langca271392017-04-05 12:30:00 -0400628 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400629 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400630 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400631 }
632 else
633 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400634 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400635 }
Geoff Lang5d601382014-07-22 15:14:06 -0400636}
637
Corentin Wallez76287682016-04-25 09:23:38 -0400638static bool EqualOrFirstZero(GLuint first, GLuint second)
639{
640 return first == 0 || first == second;
641}
642
Geoff Langca271392017-04-05 12:30:00 -0400643static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
644 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400645 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400646{
Jamie Madill21b786b2016-11-01 17:41:31 -0400647 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400648 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400649 return false;
650 }
Geoff Lang5d601382014-07-22 15:14:06 -0400651
Jamie Madill21b786b2016-11-01 17:41:31 -0400652 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
653 // must both be signed, unsigned, or fixed point and both source and destinations
654 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
655 // conversion between fixed and floating point.
656
657 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
658 (framebufferFormatInfo.colorEncoding == GL_SRGB))
659 {
660 return false;
661 }
662
663 if (((textureFormatInfo.componentType == GL_INT) !=
664 (framebufferFormatInfo.componentType == GL_INT)) ||
665 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
666 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
667 {
668 return false;
669 }
670
671 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
672 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
673 textureFormatInfo.componentType == GL_FLOAT) &&
674 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
675 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
676 framebufferFormatInfo.componentType == GL_FLOAT))
677 {
678 return false;
679 }
680
681 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
682 // The effective internal format of the source buffer is determined with the following rules
683 // applied in order:
684 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
685 // format then the effective internal format is the source buffer's sized internal format.
686 // * If the source buffer is a texture that was created with an unsized base internal format,
687 // then the effective internal format is the source image array's effective internal
688 // format, as specified by table 3.12, which is determined from the <format> and <type>
689 // that were used when the source image array was specified by TexImage*.
690 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
691 // where Destination Internal Format matches internalformat and where the [source channel
692 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
693 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
694 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800695 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400696 if (readBufferHandle != 0)
697 {
698 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
699 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400700 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400701 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400702 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400703 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400704 else
Geoff Lang5d601382014-07-22 15:14:06 -0400705 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400706 // Renderbuffers cannot be created with an unsized internal format, so this must be an
707 // unsized-format texture. We can use the same table we use when creating textures to
708 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400709 sourceEffectiveFormat =
710 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400711 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400712 }
713 else
714 {
715 // The effective internal format must be derived from the source framebuffer's channel
716 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
717 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400718 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 GLenum effectiveFormat;
720 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
721 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400722 {
Geoff Langca271392017-04-05 12:30:00 -0400723 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400724 }
725 else
726 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400727 return false;
728 }
729 }
730 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
731 {
732 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400733 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400734 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
735 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
736 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
737 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
738 {
Geoff Langca271392017-04-05 12:30:00 -0400739 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400740 }
741 else
742 {
743 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400744 }
745 }
746 else
747 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400748 UNREACHABLE();
749 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400750 }
Geoff Lang5d601382014-07-22 15:14:06 -0400751 }
752
Geoff Langca271392017-04-05 12:30:00 -0400753 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400754 {
755 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
756 // sized, component sizes of the source and destination formats must exactly match if the
757 // destination format exists.
758 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
759 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
760 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
761 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
762 {
763 return false;
764 }
765 }
766
767 return true; // A conversion function exists, and no rule in the specification has precluded
768 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400769}
770
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500771bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
772 GLenum target,
773 GLint level,
774 GLenum internalformat,
775 bool isSubImage,
776 GLint xoffset,
777 GLint yoffset,
778 GLint zoffset,
779 GLint x,
780 GLint y,
781 GLsizei width,
782 GLsizei height,
783 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400785 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400786 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400787 xoffset, yoffset, zoffset, x, y, width, height, border,
788 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400789 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400792 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793
Jamie Madill51f40ec2016-06-15 14:06:00 -0400794 const auto &state = context->getGLState();
795 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
796 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400797
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400798 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500800 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400802 }
803
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400804 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500806 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400807 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400808 }
809
Jamie Madill0c8abca2016-07-22 20:21:26 -0400810 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811
812 if (isSubImage)
813 {
Geoff Langca271392017-04-05 12:30:00 -0400814 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500815 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500817 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400821 else
822 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400823 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400824 const InternalFormat &framebufferFormat = *source->getFormat().info;
825 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400826 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400830 }
831 }
832
Geoff Lang784a8fd2013-09-24 12:33:16 -0400833 // If width or height is zero, it is a no-op. Return false without setting an error.
834 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835}
836
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500837bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
838 GLenum target,
839 GLint level,
840 GLenum internalformat,
841 bool isSubImage,
842 GLint xoffset,
843 GLint yoffset,
844 GLint zoffset,
845 GLint x,
846 GLint y,
847 GLsizei width,
848 GLsizei height,
849 GLint border)
850{
851 if (!ValidTexture2DDestinationTarget(context, target))
852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500853 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500854 return false;
855 }
856
857 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
858 xoffset, yoffset, zoffset, x, y, width, height,
859 border);
860}
861
862bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
863 GLenum target,
864 GLint level,
865 GLenum internalformat,
866 bool isSubImage,
867 GLint xoffset,
868 GLint yoffset,
869 GLint zoffset,
870 GLint x,
871 GLint y,
872 GLsizei width,
873 GLsizei height,
874 GLint border)
875{
876 if (!ValidTexture3DDestinationTarget(context, target))
877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500879 return false;
880 }
881
882 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
883 xoffset, yoffset, zoffset, x, y, width, height,
884 border);
885}
886
887bool ValidateES3TexStorageParametersBase(Context *context,
888 GLenum target,
889 GLsizei levels,
890 GLenum internalformat,
891 GLsizei width,
892 GLsizei height,
893 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894{
895 if (width < 1 || height < 1 || depth < 1 || levels < 1)
896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500897 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400898 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400899 }
900
Geoff Langb92c1332015-09-04 12:54:55 -0400901 GLsizei maxDim = std::max(width, height);
902 if (target != GL_TEXTURE_2D_ARRAY)
903 {
904 maxDim = std::max(maxDim, depth);
905 }
906
907 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500909 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400910 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911 }
912
Geoff Langaae65a42014-05-26 12:43:44 -0400913 const gl::Caps &caps = context->getCaps();
914
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 switch (target)
916 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800917 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 {
Geoff Langaae65a42014-05-26 12:43:44 -0400919 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
920 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500922 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925 }
926 break;
927
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400928 case GL_TEXTURE_RECTANGLE_ANGLE:
929 {
930 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
931 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
932 {
933 context->handleError(InvalidValue());
934 return false;
935 }
936 }
937 break;
938
He Yunchaoced53ae2016-11-29 15:00:51 +0800939 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400941 if (width != height)
942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500943 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400944 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 }
946
Geoff Langaae65a42014-05-26 12:43:44 -0400947 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500949 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952 }
953 break;
954
He Yunchaoced53ae2016-11-29 15:00:51 +0800955 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 {
Geoff Langaae65a42014-05-26 12:43:44 -0400957 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
958 static_cast<GLuint>(height) > caps.max3DTextureSize ||
959 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500961 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 }
964 }
965 break;
966
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 {
Geoff Langaae65a42014-05-26 12:43:44 -0400969 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
970 static_cast<GLuint>(height) > caps.max2DTextureSize ||
971 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500973 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 }
976 }
977 break;
978
He Yunchaoced53ae2016-11-29 15:00:51 +0800979 default:
980 UNREACHABLE();
981 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 }
983
Geoff Lang691e58c2014-12-19 17:03:25 -0500984 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985 if (!texture || texture->id() == 0)
986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500987 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 }
990
Geoff Lang69cce582015-09-17 13:20:36 -0400991 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500993 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400995 }
996
Geoff Langca271392017-04-05 12:30:00 -0400997 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400998 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Geoff Langca271392017-04-05 12:30:00 -04001004 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001010 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1011 {
1012 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1013 return false;
1014 }
1015
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 return true;
1017}
1018
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001019bool ValidateES3TexStorage2DParameters(Context *context,
1020 GLenum target,
1021 GLsizei levels,
1022 GLenum internalformat,
1023 GLsizei width,
1024 GLsizei height,
1025 GLsizei depth)
1026{
1027 if (!ValidTexture2DTarget(context, target))
1028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001029 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001030 return false;
1031 }
1032
1033 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1034 height, depth);
1035}
1036
1037bool ValidateES3TexStorage3DParameters(Context *context,
1038 GLenum target,
1039 GLsizei levels,
1040 GLenum internalformat,
1041 GLsizei width,
1042 GLsizei height,
1043 GLsizei depth)
1044{
1045 if (!ValidTexture3DTarget(context, target))
1046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001047 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001048 return false;
1049 }
1050
1051 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1052 height, depth);
1053}
1054
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001055bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1056{
Martin Radev1be913c2016-07-11 17:59:16 +03001057 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001058 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001060 return false;
1061 }
1062
1063 return ValidateBeginQueryBase(context, target, id);
1064}
1065
1066bool ValidateEndQuery(gl::Context *context, GLenum target)
1067{
Martin Radev1be913c2016-07-11 17:59:16 +03001068 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001069 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001071 return false;
1072 }
1073
1074 return ValidateEndQueryBase(context, target);
1075}
1076
1077bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1078{
Martin Radev1be913c2016-07-11 17:59:16 +03001079 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001080 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001082 return false;
1083 }
1084
Geoff Lang2186c382016-10-14 10:54:54 -04001085 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086}
1087
1088bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1089{
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001091 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093 return false;
1094 }
1095
Geoff Lang2186c382016-10-14 10:54:54 -04001096 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097}
1098
He Yunchaoced53ae2016-11-29 15:00:51 +08001099bool ValidateFramebufferTextureLayer(Context *context,
1100 GLenum target,
1101 GLenum attachment,
1102 GLuint texture,
1103 GLint level,
1104 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001105{
Martin Radev1be913c2016-07-11 17:59:16 +03001106 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001107 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001110 }
1111
Jamie Madill55ec3b12014-07-03 10:38:57 -04001112 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1113 {
1114 return false;
1115 }
1116
1117 const gl::Caps &caps = context->getCaps();
1118 if (texture != 0)
1119 {
Geoff Lang23e02842017-10-17 13:24:09 -04001120 if (layer < 0)
1121 {
1122 context->handleError(InvalidValue());
1123 return false;
1124 }
1125
Jamie Madill55ec3b12014-07-03 10:38:57 -04001126 gl::Texture *tex = context->getTexture(texture);
1127 ASSERT(tex);
1128
1129 switch (tex->getTarget())
1130 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001131 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001132 {
1133 if (level > gl::log2(caps.max2DTextureSize))
1134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001135 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001137 }
1138
1139 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001143 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001144 }
1145 break;
1146
He Yunchaoced53ae2016-11-29 15:00:51 +08001147 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001148 {
1149 if (level > gl::log2(caps.max3DTextureSize))
1150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001151 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001153 }
1154
1155 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001157 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001158 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001159 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001160 }
1161 break;
1162
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001166 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001167
Jamie Madilla3944d42016-07-22 22:13:26 -04001168 const auto &format = tex->getFormat(tex->getTarget(), level);
1169 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001172 return false;
1173 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001174 }
1175
1176 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001177}
1178
He Yunchaoced53ae2016-11-29 15:00:51 +08001179bool ValidateInvalidateFramebuffer(Context *context,
1180 GLenum target,
1181 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001182 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183{
Martin Radev1be913c2016-07-11 17:59:16 +03001184 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001185 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001187 return false;
1188 }
1189
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001190 bool defaultFramebuffer = false;
1191
1192 switch (target)
1193 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 case GL_DRAW_FRAMEBUFFER:
1195 case GL_FRAMEBUFFER:
1196 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1197 break;
1198 case GL_READ_FRAMEBUFFER:
1199 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1200 break;
1201 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001204 }
1205
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1207 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001208}
1209
Jamie Madill3ef140a2017-08-26 23:11:21 -04001210bool ValidateInvalidateSubFramebuffer(Context *context,
1211 GLenum target,
1212 GLsizei numAttachments,
1213 const GLenum *attachments,
1214 GLint x,
1215 GLint y,
1216 GLsizei width,
1217 GLsizei height)
1218{
1219 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1220}
1221
Jamie Madillc29968b2016-01-20 11:17:23 -05001222bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001223{
Martin Radev1be913c2016-07-11 17:59:16 +03001224 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001225 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001228 }
1229
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001230 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001232 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001233 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001234 }
1235
1236 return true;
1237}
1238
Olli Etuaho71dfb362016-03-10 14:04:27 +02001239bool ValidateDrawRangeElements(Context *context,
1240 GLenum mode,
1241 GLuint start,
1242 GLuint end,
1243 GLsizei count,
1244 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001245 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001246{
Martin Radev1be913c2016-07-11 17:59:16 +03001247 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001248 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001250 return false;
1251 }
1252
1253 if (end < start)
1254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001256 return false;
1257 }
1258
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001259 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001260 {
1261 return false;
1262 }
1263
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001264 // Use the parameter buffer to retrieve and cache the index range.
1265 const auto &params = context->getParams<HasIndexRange>();
1266 const auto &indexRangeOpt = params.getIndexRange();
1267 if (!indexRangeOpt.valid())
1268 {
1269 // Unexpected error.
1270 return false;
1271 }
1272
1273 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001274 {
1275 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001276 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001277 return false;
1278 }
1279 return true;
1280}
1281
He Yunchaoced53ae2016-11-29 15:00:51 +08001282bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001283{
Martin Radev1be913c2016-07-11 17:59:16 +03001284 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001285 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001287 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001288 }
1289
Jamie Madill78f41802014-08-25 15:47:55 -04001290 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001291}
1292
Jamie Madillb885e572015-02-03 16:16:04 -05001293bool ValidateReadBuffer(Context *context, GLenum src)
1294{
Martin Radev1be913c2016-07-11 17:59:16 +03001295 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001296 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001298 return false;
1299 }
1300
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001301 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001302
1303 if (readFBO == nullptr)
1304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001306 return false;
1307 }
1308
1309 if (src == GL_NONE)
1310 {
1311 return true;
1312 }
1313
Olli Etuaho84c9f592016-03-09 14:37:25 +02001314 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001315 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001316 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001317 return false;
1318 }
1319
1320 if (readFBO->id() == 0)
1321 {
1322 if (src != GL_BACK)
1323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(
1325 InvalidOperation()
1326 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001327 return false;
1328 }
1329 }
1330 else
1331 {
1332 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1333
1334 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001337 return false;
1338 }
1339 }
1340
1341 return true;
1342}
1343
Jamie Madill86af3d22015-07-21 15:14:07 -04001344bool ValidateCompressedTexImage3D(Context *context,
1345 GLenum target,
1346 GLint level,
1347 GLenum internalformat,
1348 GLsizei width,
1349 GLsizei height,
1350 GLsizei depth,
1351 GLint border,
1352 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001353 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001354{
Martin Radev1be913c2016-07-11 17:59:16 +03001355 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001356 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001357 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001358 return false;
1359 }
1360
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001361 if (!ValidTextureTarget(context, target))
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001364 return false;
1365 }
1366
Jamie Madille2e406c2016-06-02 13:04:10 -04001367 // Validate image size
1368 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001371 return false;
1372 }
1373
Geoff Langca271392017-04-05 12:30:00 -04001374 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001375 if (!formatInfo.compressed)
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001378 return false;
1379 }
1380
Jamie Madill513558d2016-06-02 13:04:11 -04001381 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001382 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001383 if (blockSizeOrErr.isError())
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001386 return false;
1387 }
1388 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001391 return false;
1392 }
1393
1394 // 3D texture target validation
1395 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001398 return false;
1399 }
1400
1401 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001402 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001403 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1404 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001405 {
1406 return false;
1407 }
1408
1409 return true;
1410}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001411
Corentin Wallezb2931602017-04-11 15:58:57 -04001412bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1413 GLenum target,
1414 GLint level,
1415 GLenum internalformat,
1416 GLsizei width,
1417 GLsizei height,
1418 GLsizei depth,
1419 GLint border,
1420 GLsizei imageSize,
1421 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001422 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001423{
1424 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1425 {
1426 return false;
1427 }
1428
1429 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1430 depth, border, imageSize, data);
1431}
1432
Austin Kinrossbc781f32015-10-26 09:27:38 -07001433bool ValidateBindVertexArray(Context *context, GLuint array)
1434{
Martin Radev1be913c2016-07-11 17:59:16 +03001435 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001436 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001437 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001438 return false;
1439 }
1440
1441 return ValidateBindVertexArrayBase(context, array);
1442}
1443
Jamie Madilld7576732017-08-26 18:49:50 -04001444bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001445{
Martin Radev1be913c2016-07-11 17:59:16 +03001446 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001447 {
Jamie Madilld7576732017-08-26 18:49:50 -04001448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001449 return false;
1450 }
1451
1452 return true;
1453}
Geoff Langc5629752015-12-07 16:29:04 -05001454
Jiajia Qin6eafb042016-12-27 17:04:07 +08001455static bool ValidateBindBufferCommon(Context *context,
1456 GLenum target,
1457 GLuint index,
1458 GLuint buffer,
1459 GLintptr offset,
1460 GLsizeiptr size)
1461{
1462 if (context->getClientMajorVersion() < 3)
1463 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001465 return false;
1466 }
1467
1468 if (buffer != 0 && offset < 0)
1469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001470 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001471 return false;
1472 }
1473
1474 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1475 !context->isBufferGenerated(buffer))
1476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001478 return false;
1479 }
1480
1481 const Caps &caps = context->getCaps();
1482 switch (target)
1483 {
1484 case GL_TRANSFORM_FEEDBACK_BUFFER:
1485 {
1486 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001488 context->handleError(InvalidValue() << "index is greater than or equal to the "
1489 "number of TRANSFORM_FEEDBACK_BUFFER "
1490 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001491 return false;
1492 }
1493 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001495 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001496 return false;
1497 }
1498
1499 TransformFeedback *curTransformFeedback =
1500 context->getGLState().getCurrentTransformFeedback();
1501 if (curTransformFeedback && curTransformFeedback->isActive())
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidOperation()
1504 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1505 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001506 return false;
1507 }
1508 break;
1509 }
1510 case GL_UNIFORM_BUFFER:
1511 {
1512 if (index >= caps.maxUniformBufferBindings)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidValue() << "index is greater than or equal to the "
1515 "number of UNIFORM_BUFFER indexed "
1516 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001517 return false;
1518 }
1519
1520 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1521 {
1522 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 InvalidValue()
1524 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001525 return false;
1526 }
1527 break;
1528 }
1529 case GL_ATOMIC_COUNTER_BUFFER:
1530 {
1531 if (context->getClientVersion() < ES_3_1)
1532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(InvalidEnum()
1534 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001535 return false;
1536 }
1537 if (index >= caps.maxAtomicCounterBufferBindings)
1538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001539 context->handleError(InvalidValue() << "index is greater than or equal to the "
1540 "number of ATOMIC_COUNTER_BUFFER "
1541 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001542 return false;
1543 }
1544 if (buffer != 0 && (offset % 4) != 0)
1545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001546 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001547 return false;
1548 }
1549 break;
1550 }
1551 case GL_SHADER_STORAGE_BUFFER:
1552 {
1553 if (context->getClientVersion() < ES_3_1)
1554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001555 context->handleError(InvalidEnum()
1556 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001557 return false;
1558 }
1559 if (index >= caps.maxShaderStorageBufferBindings)
1560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidValue() << "index is greater than or equal to the "
1562 "number of SHADER_STORAGE_BUFFER "
1563 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001564 return false;
1565 }
1566 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001568 context->handleError(InvalidValue() << "offset must be multiple of value of "
1569 "SHADER_STORAGE_BUFFER_OFFSET_"
1570 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001571 return false;
1572 }
1573 break;
1574 }
1575 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001577 return false;
1578 }
1579
1580 return true;
1581}
1582
1583bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1584{
1585 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1586}
1587
1588bool ValidateBindBufferRange(Context *context,
1589 GLenum target,
1590 GLuint index,
1591 GLuint buffer,
1592 GLintptr offset,
1593 GLsizeiptr size)
1594{
1595 if (buffer != 0 && size <= 0)
1596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidValue()
1598 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001599 return false;
1600 }
1601 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1602}
1603
Geoff Langc5629752015-12-07 16:29:04 -05001604bool ValidateProgramBinary(Context *context,
1605 GLuint program,
1606 GLenum binaryFormat,
1607 const void *binary,
1608 GLint length)
1609{
Martin Radev1be913c2016-07-11 17:59:16 +03001610 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001611 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001612 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001613 return false;
1614 }
1615
1616 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1617}
1618
1619bool ValidateGetProgramBinary(Context *context,
1620 GLuint program,
1621 GLsizei bufSize,
1622 GLsizei *length,
1623 GLenum *binaryFormat,
1624 void *binary)
1625{
Martin Radev1be913c2016-07-11 17:59:16 +03001626 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001627 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001629 return false;
1630 }
1631
1632 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1633}
1634
Olli Etuahof0fee072016-03-30 15:11:58 +03001635bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001636{
Martin Radev1be913c2016-07-11 17:59:16 +03001637 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001640 return false;
1641 }
1642
1643 if (GetValidProgram(context, program) == nullptr)
1644 {
1645 return false;
1646 }
1647
1648 switch (pname)
1649 {
1650 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001651 if (value != GL_FALSE && value != GL_TRUE)
1652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidValue()
1654 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001655 return false;
1656 }
Geoff Langc5629752015-12-07 16:29:04 -05001657 break;
1658
Yunchao He61afff12017-03-14 15:34:03 +08001659 case GL_PROGRAM_SEPARABLE:
1660 if (context->getClientVersion() < ES_3_1)
1661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001662 context->handleError(InvalidEnum()
1663 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001664 return false;
1665 }
1666
1667 if (value != GL_FALSE && value != GL_TRUE)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidValue()
1670 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001671 return false;
1672 }
1673 break;
1674
Geoff Langc5629752015-12-07 16:29:04 -05001675 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidEnum()
1677 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001678 return false;
1679 }
1680
1681 return true;
1682}
Jamie Madillc29968b2016-01-20 11:17:23 -05001683
1684bool ValidateBlitFramebuffer(Context *context,
1685 GLint srcX0,
1686 GLint srcY0,
1687 GLint srcX1,
1688 GLint srcY1,
1689 GLint dstX0,
1690 GLint dstY0,
1691 GLint dstX1,
1692 GLint dstY1,
1693 GLbitfield mask,
1694 GLenum filter)
1695{
Martin Radev1be913c2016-07-11 17:59:16 +03001696 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001697 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001699 return false;
1700 }
1701
1702 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1703 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001704}
Jamie Madillc29968b2016-01-20 11:17:23 -05001705
1706bool ValidateClearBufferiv(ValidationContext *context,
1707 GLenum buffer,
1708 GLint drawbuffer,
1709 const GLint *value)
1710{
1711 switch (buffer)
1712 {
1713 case GL_COLOR:
1714 if (drawbuffer < 0 ||
1715 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001718 return false;
1719 }
Geoff Lang76e65652017-03-27 14:58:02 -04001720 if (context->getExtensions().webglCompatibility)
1721 {
1722 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001723 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001724 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1725 {
1726 return false;
1727 }
1728 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001729 break;
1730
1731 case GL_STENCIL:
1732 if (drawbuffer != 0)
1733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001734 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001735 return false;
1736 }
1737 break;
1738
1739 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001741 return false;
1742 }
1743
1744 return ValidateClearBuffer(context);
1745}
1746
1747bool ValidateClearBufferuiv(ValidationContext *context,
1748 GLenum buffer,
1749 GLint drawbuffer,
1750 const GLuint *value)
1751{
1752 switch (buffer)
1753 {
1754 case GL_COLOR:
1755 if (drawbuffer < 0 ||
1756 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001759 return false;
1760 }
Geoff Lang76e65652017-03-27 14:58:02 -04001761 if (context->getExtensions().webglCompatibility)
1762 {
1763 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001764 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001765 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1766 {
1767 return false;
1768 }
1769 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001770 break;
1771
1772 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001773 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001774 return false;
1775 }
1776
1777 return ValidateClearBuffer(context);
1778}
1779
1780bool ValidateClearBufferfv(ValidationContext *context,
1781 GLenum buffer,
1782 GLint drawbuffer,
1783 const GLfloat *value)
1784{
1785 switch (buffer)
1786 {
1787 case GL_COLOR:
1788 if (drawbuffer < 0 ||
1789 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001791 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 return false;
1793 }
Geoff Lang76e65652017-03-27 14:58:02 -04001794 if (context->getExtensions().webglCompatibility)
1795 {
1796 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1797 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001798 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001799 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1800 {
1801 return false;
1802 }
1803 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 break;
1805
1806 case GL_DEPTH:
1807 if (drawbuffer != 0)
1808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001809 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 return false;
1811 }
1812 break;
1813
1814 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001815 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 return false;
1817 }
1818
1819 return ValidateClearBuffer(context);
1820}
1821
1822bool ValidateClearBufferfi(ValidationContext *context,
1823 GLenum buffer,
1824 GLint drawbuffer,
1825 GLfloat depth,
1826 GLint stencil)
1827{
1828 switch (buffer)
1829 {
1830 case GL_DEPTH_STENCIL:
1831 if (drawbuffer != 0)
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836 break;
1837
1838 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 return false;
1841 }
1842
1843 return ValidateClearBuffer(context);
1844}
1845
1846bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1847{
Martin Radev1be913c2016-07-11 17:59:16 +03001848 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 return false;
1852 }
1853
1854 return ValidateDrawBuffersBase(context, n, bufs);
1855}
1856
1857bool ValidateCopyTexSubImage3D(Context *context,
1858 GLenum target,
1859 GLint level,
1860 GLint xoffset,
1861 GLint yoffset,
1862 GLint zoffset,
1863 GLint x,
1864 GLint y,
1865 GLsizei width,
1866 GLsizei height)
1867{
Martin Radev1be913c2016-07-11 17:59:16 +03001868 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001871 return false;
1872 }
1873
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001874 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1875 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001876}
1877
Jamie Madill73a84962016-02-12 09:27:23 -05001878bool ValidateTexImage3D(Context *context,
1879 GLenum target,
1880 GLint level,
1881 GLint internalformat,
1882 GLsizei width,
1883 GLsizei height,
1884 GLsizei depth,
1885 GLint border,
1886 GLenum format,
1887 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001888 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001889{
Martin Radev1be913c2016-07-11 17:59:16 +03001890 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001891 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001893 return false;
1894 }
1895
1896 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001897 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001898 pixels);
1899}
1900
Geoff Langc52f6f12016-10-14 10:18:00 -04001901bool ValidateTexImage3DRobustANGLE(Context *context,
1902 GLenum target,
1903 GLint level,
1904 GLint internalformat,
1905 GLsizei width,
1906 GLsizei height,
1907 GLsizei depth,
1908 GLint border,
1909 GLenum format,
1910 GLenum type,
1911 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001912 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001913{
1914 if (context->getClientMajorVersion() < 3)
1915 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001917 return false;
1918 }
1919
1920 if (!ValidateRobustEntryPoint(context, bufSize))
1921 {
1922 return false;
1923 }
1924
1925 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1926 0, 0, width, height, depth, border, format, type,
1927 bufSize, pixels);
1928}
1929
Jamie Madill73a84962016-02-12 09:27:23 -05001930bool ValidateTexSubImage3D(Context *context,
1931 GLenum target,
1932 GLint level,
1933 GLint xoffset,
1934 GLint yoffset,
1935 GLint zoffset,
1936 GLsizei width,
1937 GLsizei height,
1938 GLsizei depth,
1939 GLenum format,
1940 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001941 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001942{
Martin Radev1be913c2016-07-11 17:59:16 +03001943 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001944 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001945 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001946 return false;
1947 }
1948
1949 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1950 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001951 -1, pixels);
1952}
1953
1954bool ValidateTexSubImage3DRobustANGLE(Context *context,
1955 GLenum target,
1956 GLint level,
1957 GLint xoffset,
1958 GLint yoffset,
1959 GLint zoffset,
1960 GLsizei width,
1961 GLsizei height,
1962 GLsizei depth,
1963 GLenum format,
1964 GLenum type,
1965 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001966 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001967{
1968 if (context->getClientMajorVersion() < 3)
1969 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001971 return false;
1972 }
1973
1974 if (!ValidateRobustEntryPoint(context, bufSize))
1975 {
1976 return false;
1977 }
1978
1979 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1980 yoffset, zoffset, width, height, depth, 0, format, type,
1981 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001982}
1983
1984bool ValidateCompressedTexSubImage3D(Context *context,
1985 GLenum target,
1986 GLint level,
1987 GLint xoffset,
1988 GLint yoffset,
1989 GLint zoffset,
1990 GLsizei width,
1991 GLsizei height,
1992 GLsizei depth,
1993 GLenum format,
1994 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001995 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001996{
Martin Radev1be913c2016-07-11 17:59:16 +03001997 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001998 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001999 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002000 return false;
2001 }
2002
Geoff Langca271392017-04-05 12:30:00 -04002003 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002004 if (!formatInfo.compressed)
2005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002006 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002007 return false;
2008 }
2009
Jamie Madill513558d2016-06-02 13:04:11 -04002010 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002011 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002012 if (blockSizeOrErr.isError())
2013 {
2014 context->handleError(blockSizeOrErr.getError());
2015 return false;
2016 }
2017 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002019 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002020 return false;
2021 }
2022
2023 if (!data)
2024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002025 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002026 return false;
2027 }
2028
Geoff Lang5ca5c652017-10-27 17:29:54 -04002029 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2030 yoffset, zoffset, width, height, depth, 0, format,
2031 GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002032}
Corentin Wallezb2931602017-04-11 15:58:57 -04002033bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2034 GLenum target,
2035 GLint level,
2036 GLint xoffset,
2037 GLint yoffset,
2038 GLint zoffset,
2039 GLsizei width,
2040 GLsizei height,
2041 GLsizei depth,
2042 GLenum format,
2043 GLsizei imageSize,
2044 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002045 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002046{
2047 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2048 {
2049 return false;
2050 }
2051
2052 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2053 height, depth, format, imageSize, data);
2054}
Jamie Madill73a84962016-02-12 09:27:23 -05002055
Olli Etuaho41997e72016-03-10 13:38:39 +02002056bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2057{
2058 return ValidateGenOrDeleteES3(context, n);
2059}
2060
2061bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2062{
2063 return ValidateGenOrDeleteES3(context, n);
2064}
2065
2066bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2067{
2068 return ValidateGenOrDeleteCountES3(context, count);
2069}
2070
2071bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2072{
2073 return ValidateGenOrDeleteCountES3(context, count);
2074}
2075
2076bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2077{
2078 return ValidateGenOrDeleteES3(context, n);
2079}
2080
2081bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2082{
2083 if (!ValidateGenOrDeleteES3(context, n))
2084 {
2085 return false;
2086 }
2087 for (GLint i = 0; i < n; ++i)
2088 {
2089 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2090 if (transformFeedback != nullptr && transformFeedback->isActive())
2091 {
2092 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002093 context->handleError(InvalidOperation()
2094 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002095 return false;
2096 }
2097 }
2098 return true;
2099}
2100
2101bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2102{
2103 return ValidateGenOrDeleteES3(context, n);
2104}
2105
2106bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2107{
2108 return ValidateGenOrDeleteES3(context, n);
2109}
2110
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002111bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2112{
Martin Radev1be913c2016-07-11 17:59:16 +03002113 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002114 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002116 return false;
2117 }
2118 switch (primitiveMode)
2119 {
2120 case GL_TRIANGLES:
2121 case GL_LINES:
2122 case GL_POINTS:
2123 break;
2124
2125 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002126 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002127 return false;
2128 }
2129
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002130 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002131 ASSERT(transformFeedback != nullptr);
2132
2133 if (transformFeedback->isActive())
2134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002135 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002136 return false;
2137 }
Geoff Lang79f71042017-08-14 16:43:43 -04002138
2139 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2140 {
2141 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2142 if (buffer.get() && buffer->isMapped())
2143 {
2144 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2145 return false;
2146 }
2147 }
2148
Olli Etuaho02032bd2017-10-13 18:10:17 +03002149 auto program = context->getGLState().getProgram();
2150
2151 if (!program)
2152 {
2153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2154 return false;
2155 }
2156
2157 if (program->getTransformFeedbackVaryingCount() == 0)
2158 {
2159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2160 return false;
2161 }
2162
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002163 return true;
2164}
2165
Jamie Madill876429b2017-04-20 15:46:24 -04002166bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002167{
Geoff Lang496c02d2016-10-20 11:38:11 -07002168 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2169}
2170
2171bool ValidateGetBufferPointervRobustANGLE(Context *context,
2172 GLenum target,
2173 GLenum pname,
2174 GLsizei bufSize,
2175 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002176 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002177{
2178 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002179 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002180 return false;
2181 }
2182
Geoff Lang496c02d2016-10-20 11:38:11 -07002183 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2184 {
2185 return false;
2186 }
2187
2188 if (!ValidateRobustBufferSize(context, bufSize, *length))
2189 {
2190 return false;
2191 }
2192
2193 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002194}
2195
2196bool ValidateUnmapBuffer(Context *context, GLenum target)
2197{
Martin Radev1be913c2016-07-11 17:59:16 +03002198 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002199 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002201 return false;
2202 }
2203
2204 return ValidateUnmapBufferBase(context, target);
2205}
2206
2207bool ValidateMapBufferRange(Context *context,
2208 GLenum target,
2209 GLintptr offset,
2210 GLsizeiptr length,
2211 GLbitfield access)
2212{
Martin Radev1be913c2016-07-11 17:59:16 +03002213 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002214 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002216 return false;
2217 }
2218
2219 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2220}
2221
2222bool ValidateFlushMappedBufferRange(Context *context,
2223 GLenum target,
2224 GLintptr offset,
2225 GLsizeiptr length)
2226{
Martin Radev1be913c2016-07-11 17:59:16 +03002227 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002228 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002230 return false;
2231 }
2232
2233 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2234}
2235
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002236bool ValidateIndexedStateQuery(ValidationContext *context,
2237 GLenum pname,
2238 GLuint index,
2239 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002240{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002241 if (length)
2242 {
2243 *length = 0;
2244 }
2245
Martin Radev66fb8202016-07-28 11:45:20 +03002246 GLenum nativeType;
2247 unsigned int numParams;
2248 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002250 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002251 return false;
2252 }
2253
2254 const Caps &caps = context->getCaps();
2255 switch (pname)
2256 {
2257 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2258 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2259 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2260 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002262 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002263 return false;
2264 }
2265 break;
2266
2267 case GL_UNIFORM_BUFFER_START:
2268 case GL_UNIFORM_BUFFER_SIZE:
2269 case GL_UNIFORM_BUFFER_BINDING:
2270 if (index >= caps.maxUniformBufferBindings)
2271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002272 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002273 return false;
2274 }
2275 break;
Shao80957d92017-02-20 21:25:59 +08002276
Martin Radev66fb8202016-07-28 11:45:20 +03002277 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2278 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2279 if (index >= 3u)
2280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002281 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002282 return false;
2283 }
2284 break;
Shao80957d92017-02-20 21:25:59 +08002285
Jiajia Qin6eafb042016-12-27 17:04:07 +08002286 case GL_ATOMIC_COUNTER_BUFFER_START:
2287 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2288 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2289 if (context->getClientVersion() < ES_3_1)
2290 {
2291 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002292 InvalidEnum()
2293 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002294 return false;
2295 }
2296 if (index >= caps.maxAtomicCounterBufferBindings)
2297 {
2298 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002299 InvalidValue()
2300 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002301 return false;
2302 }
2303 break;
Shao80957d92017-02-20 21:25:59 +08002304
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002305 case GL_SHADER_STORAGE_BUFFER_START:
2306 case GL_SHADER_STORAGE_BUFFER_SIZE:
2307 case GL_SHADER_STORAGE_BUFFER_BINDING:
2308 if (context->getClientVersion() < ES_3_1)
2309 {
2310 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002311 InvalidEnum()
2312 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002313 return false;
2314 }
2315 if (index >= caps.maxShaderStorageBufferBindings)
2316 {
2317 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002318 InvalidValue()
2319 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002320 return false;
2321 }
2322 break;
2323
Shao80957d92017-02-20 21:25:59 +08002324 case GL_VERTEX_BINDING_BUFFER:
2325 case GL_VERTEX_BINDING_DIVISOR:
2326 case GL_VERTEX_BINDING_OFFSET:
2327 case GL_VERTEX_BINDING_STRIDE:
2328 if (context->getClientVersion() < ES_3_1)
2329 {
2330 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002331 InvalidEnum()
2332 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002333 return false;
2334 }
2335 if (index >= caps.maxVertexAttribBindings)
2336 {
2337 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002338 InvalidValue()
2339 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002340 return false;
2341 }
2342 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002343 case GL_SAMPLE_MASK_VALUE:
2344 if (context->getClientVersion() < ES_3_1)
2345 {
2346 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2347 return false;
2348 }
2349 if (index >= caps.maxSampleMaskWords)
2350 {
2351 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2352 return false;
2353 }
2354 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002355 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002356 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002357 return false;
2358 }
2359
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002360 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002361 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002362 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002363 }
2364
2365 return true;
2366}
2367
2368bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2369{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002370 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002371 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002372 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002373 return false;
2374 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002375 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002376}
2377
Geoff Langcf255ea2016-10-20 11:39:09 -07002378bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2379 GLenum target,
2380 GLuint index,
2381 GLsizei bufSize,
2382 GLsizei *length,
2383 GLint *data)
2384{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002385 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002386 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002388 return false;
2389 }
2390
2391 if (!ValidateRobustEntryPoint(context, bufSize))
2392 {
2393 return false;
2394 }
2395
2396 if (!ValidateIndexedStateQuery(context, target, index, length))
2397 {
2398 return false;
2399 }
2400
2401 if (!ValidateRobustBufferSize(context, bufSize, *length))
2402 {
2403 return false;
2404 }
2405
2406 return true;
2407}
2408
Martin Radev66fb8202016-07-28 11:45:20 +03002409bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2410{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002411 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002412 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002414 return false;
2415 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002416 return ValidateIndexedStateQuery(context, target, index, nullptr);
2417}
2418
2419bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2420 GLenum target,
2421 GLuint index,
2422 GLsizei bufSize,
2423 GLsizei *length,
2424 GLint64 *data)
2425{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002426 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002427 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002429 return false;
2430 }
2431
2432 if (!ValidateRobustEntryPoint(context, bufSize))
2433 {
2434 return false;
2435 }
2436
2437 if (!ValidateIndexedStateQuery(context, target, index, length))
2438 {
2439 return false;
2440 }
2441
2442 if (!ValidateRobustBufferSize(context, bufSize, *length))
2443 {
2444 return false;
2445 }
2446
2447 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002448}
2449
Jamie Madillb0817d12016-11-01 15:48:31 -04002450bool ValidateCopyBufferSubData(ValidationContext *context,
2451 GLenum readTarget,
2452 GLenum writeTarget,
2453 GLintptr readOffset,
2454 GLintptr writeOffset,
2455 GLsizeiptr size)
2456{
2457 if (context->getClientMajorVersion() < 3)
2458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002460 return false;
2461 }
2462
2463 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002465 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002466 return false;
2467 }
2468
2469 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2470 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2471
2472 if (!readBuffer || !writeBuffer)
2473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002474 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002475 return false;
2476 }
2477
2478 // Verify that readBuffer and writeBuffer are not currently mapped
2479 if (readBuffer->isMapped() || writeBuffer->isMapped())
2480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidOperation()
2482 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002483 return false;
2484 }
2485
Jamie Madilld2f0c742016-11-02 10:34:41 -04002486 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2487 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2488 CheckedNumeric<GLintptr> checkedSize(size);
2489
2490 auto checkedReadSum = checkedReadOffset + checkedSize;
2491 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2492
2493 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2494 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2495 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002497 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002498 return false;
2499 }
2500
Jamie Madilld2f0c742016-11-02 10:34:41 -04002501 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002503 context->handleError(InvalidValue()
2504 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002505 return false;
2506 }
2507
Jamie Madilld2f0c742016-11-02 10:34:41 -04002508 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2509 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002512 return false;
2513 }
2514
2515 if (readBuffer == writeBuffer)
2516 {
2517 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2518 if (!checkedOffsetDiff.IsValid())
2519 {
2520 // This shold not be possible.
2521 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidValue()
2523 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002524 return false;
2525 }
2526
2527 if (checkedOffsetDiff.ValueOrDie() < size)
2528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002530 return false;
2531 }
2532 }
2533
Jamie Madillb0817d12016-11-01 15:48:31 -04002534 return true;
2535}
2536
Geoff Langc339c4e2016-11-29 10:37:36 -05002537bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2538{
2539 if (context->getClientMajorVersion() < 3)
2540 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002541 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002542 return false;
2543 }
2544
2545 switch (name)
2546 {
2547 case GL_EXTENSIONS:
2548 if (index >= context->getExtensionStringCount())
2549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002550 context->handleError(InvalidValue()
2551 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002552 return false;
2553 }
2554 break;
2555
2556 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2557 if (!context->getExtensions().requestExtension)
2558 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002560 return false;
2561 }
2562 if (index >= context->getRequestableExtensionStringCount())
2563 {
2564 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 InvalidValue()
2566 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002567 return false;
2568 }
2569 break;
2570
2571 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002572 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002573 return false;
2574 }
2575
2576 return true;
2577}
2578
Jamie Madille8fb6402017-02-14 17:56:40 -05002579bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2580 GLenum target,
2581 GLsizei samples,
2582 GLenum internalformat,
2583 GLsizei width,
2584 GLsizei height)
2585{
2586 if (context->getClientMajorVersion() < 3)
2587 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002588 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002589 return false;
2590 }
2591
2592 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2593 height))
2594 {
2595 return false;
2596 }
2597
2598 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2599 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002600 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002601 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2602 samples > 0)
2603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002604 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002605 return false;
2606 }
2607
2608 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2609 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2610 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2611 {
2612 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002613 InvalidOperation()
2614 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002615 return false;
2616 }
2617
2618 return true;
2619}
2620
Geoff Langaa086d62017-03-23 16:47:21 -04002621bool ValidateVertexAttribIPointer(ValidationContext *context,
2622 GLuint index,
2623 GLint size,
2624 GLenum type,
2625 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002626 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002627{
2628 if (context->getClientMajorVersion() < 3)
2629 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002631 return false;
2632 }
2633
Shao80957d92017-02-20 21:25:59 +08002634 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002635 {
Geoff Langaa086d62017-03-23 16:47:21 -04002636 return false;
2637 }
2638
Geoff Langaa086d62017-03-23 16:47:21 -04002639 if (stride < 0)
2640 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002641 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002642 return false;
2643 }
2644
Shao80957d92017-02-20 21:25:59 +08002645 const Caps &caps = context->getCaps();
2646 if (context->getClientVersion() >= ES_3_1)
2647 {
2648 if (stride > caps.maxVertexAttribStride)
2649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002650 context->handleError(InvalidValue()
2651 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002652 return false;
2653 }
2654
2655 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2656 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2657 // validation should be inherited.
2658 if (index >= caps.maxVertexAttribBindings)
2659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002660 context->handleError(InvalidValue()
2661 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002662 return false;
2663 }
2664 }
2665
Geoff Langaa086d62017-03-23 16:47:21 -04002666 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2667 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2668 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2669 // and the pointer argument is not NULL.
2670 if (context->getGLState().getVertexArrayId() != 0 &&
2671 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002673 context
2674 ->handleError(InvalidOperation()
2675 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002676 return false;
2677 }
2678
Geoff Lang2d62ab72017-03-23 16:54:40 -04002679 if (context->getExtensions().webglCompatibility)
2680 {
2681 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2682 {
2683 return false;
2684 }
2685 }
2686
Geoff Langaa086d62017-03-23 16:47:21 -04002687 return true;
2688}
2689
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002690bool ValidateGetSynciv(Context *context,
2691 GLsync sync,
2692 GLenum pname,
2693 GLsizei bufSize,
2694 GLsizei *length,
2695 GLint *values)
2696{
2697 if (context->getClientMajorVersion() < 3)
2698 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002700 return false;
2701 }
2702
2703 if (bufSize < 0)
2704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002705 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002706 return false;
2707 }
2708
Jamie Madill70b5bb02017-08-28 13:32:37 -04002709 Sync *syncObject = context->getSync(sync);
2710 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002712 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002713 return false;
2714 }
2715
2716 switch (pname)
2717 {
2718 case GL_OBJECT_TYPE:
2719 case GL_SYNC_CONDITION:
2720 case GL_SYNC_FLAGS:
2721 case GL_SYNC_STATUS:
2722 break;
2723
2724 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002725 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002726 return false;
2727 }
2728
2729 return true;
2730}
2731
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002732bool ValidateDrawElementsInstanced(ValidationContext *context,
2733 GLenum mode,
2734 GLsizei count,
2735 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002736 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002737 GLsizei instanceCount)
2738{
2739 if (context->getClientMajorVersion() < 3)
2740 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002741 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002742 return false;
2743 }
2744
2745 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2746}
2747
Martin Radev137032d2017-07-13 10:11:12 +03002748bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2749 GLenum target,
2750 GLenum attachment,
2751 GLuint texture,
2752 GLint level,
2753 GLint baseViewIndex,
2754 GLsizei numViews)
2755{
2756
2757 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2758 numViews))
2759 {
2760 return false;
2761 }
2762
Martin Radev137032d2017-07-13 10:11:12 +03002763 if (texture != 0)
2764 {
Martin Radev14b21262017-08-25 13:54:37 +03002765 if (baseViewIndex < 0)
2766 {
2767 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2768 return false;
2769 }
2770
Martin Radev137032d2017-07-13 10:11:12 +03002771 Texture *tex = context->getTexture(texture);
2772 ASSERT(tex);
2773
2774 switch (tex->getTarget())
2775 {
2776 case GL_TEXTURE_2D_ARRAY:
2777 {
2778 const Caps &caps = context->getCaps();
2779 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2780 {
2781 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2782 "greater than "
2783 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2784 return false;
2785 }
2786 }
2787 break;
2788 default:
2789 context->handleError(InvalidOperation()
2790 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2791 return false;
2792 }
2793
2794 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2795 {
2796 return false;
2797 }
2798 }
2799
2800 return true;
2801}
2802
2803bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2804 GLenum target,
2805 GLenum attachment,
2806 GLuint texture,
2807 GLint level,
2808 GLsizei numViews,
2809 const GLint *viewportOffsets)
2810{
2811 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2812 numViews))
2813 {
2814 return false;
2815 }
2816
Martin Radev137032d2017-07-13 10:11:12 +03002817 if (texture != 0)
2818 {
Martin Radev14b21262017-08-25 13:54:37 +03002819 const GLsizei numViewportOffsetValues = numViews * 2;
2820 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2821 {
2822 if (viewportOffsets[i] < 0)
2823 {
2824 context->handleError(InvalidValue()
2825 << "viewportOffsets cannot contain negative values.");
2826 return false;
2827 }
2828 }
2829
Martin Radev137032d2017-07-13 10:11:12 +03002830 Texture *tex = context->getTexture(texture);
2831 ASSERT(tex);
2832
2833 switch (tex->getTarget())
2834 {
2835 case GL_TEXTURE_2D:
2836 break;
2837 default:
2838 context->handleError(InvalidOperation()
2839 << "Texture's target must be GL_TEXTURE_2D.");
2840 return false;
2841 }
2842
2843 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2844 {
2845 return false;
2846 }
2847 }
2848
2849 return true;
2850}
2851
Jamie Madillff325f12017-08-26 15:06:05 -04002852bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2853{
2854 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2855}
2856
2857bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2858{
2859 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2860}
2861
2862bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2863{
2864 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2865}
2866
2867bool ValidateUniform4ui(Context *context,
2868 GLint location,
2869 GLuint v0,
2870 GLuint v1,
2871 GLuint v2,
2872 GLuint v3)
2873{
2874 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2875}
2876
2877bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2878{
2879 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2880}
2881
2882bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2883{
2884 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2885}
2886
2887bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2888{
2889 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2890}
2891
2892bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2893{
2894 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2895}
2896
Jamie Madillf0e04492017-08-26 15:28:42 -04002897bool ValidateIsQuery(Context *context, GLuint id)
2898{
2899 if (context->getClientMajorVersion() < 3)
2900 {
2901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2902 return false;
2903 }
2904
2905 return true;
2906}
2907
Jamie Madillc8c95812017-08-26 18:40:09 -04002908bool ValidateUniformMatrix2x3fv(Context *context,
2909 GLint location,
2910 GLsizei count,
2911 GLboolean transpose,
2912 const GLfloat *value)
2913{
2914 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2915}
2916
2917bool ValidateUniformMatrix3x2fv(Context *context,
2918 GLint location,
2919 GLsizei count,
2920 GLboolean transpose,
2921 const GLfloat *value)
2922{
2923 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2924}
2925
2926bool ValidateUniformMatrix2x4fv(Context *context,
2927 GLint location,
2928 GLsizei count,
2929 GLboolean transpose,
2930 const GLfloat *value)
2931{
2932 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2933}
2934
2935bool ValidateUniformMatrix4x2fv(Context *context,
2936 GLint location,
2937 GLsizei count,
2938 GLboolean transpose,
2939 const GLfloat *value)
2940{
2941 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2942}
2943
2944bool ValidateUniformMatrix3x4fv(Context *context,
2945 GLint location,
2946 GLsizei count,
2947 GLboolean transpose,
2948 const GLfloat *value)
2949{
2950 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2951}
2952
2953bool ValidateUniformMatrix4x3fv(Context *context,
2954 GLint location,
2955 GLsizei count,
2956 GLboolean transpose,
2957 const GLfloat *value)
2958{
2959 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2960}
2961
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002962bool ValidateEndTransformFeedback(Context *context)
2963{
2964 if (context->getClientMajorVersion() < 3)
2965 {
2966 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2967 return false;
2968 }
2969
2970 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2971 ASSERT(transformFeedback != nullptr);
2972
2973 if (!transformFeedback->isActive())
2974 {
2975 context->handleError(InvalidOperation());
2976 return false;
2977 }
2978
2979 return true;
2980}
2981
2982bool ValidateTransformFeedbackVaryings(Context *context,
2983 GLuint program,
2984 GLsizei count,
2985 const GLchar *const *varyings,
2986 GLenum bufferMode)
2987{
2988 if (context->getClientMajorVersion() < 3)
2989 {
2990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2991 return false;
2992 }
2993
2994 if (count < 0)
2995 {
2996 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2997 return false;
2998 }
2999
3000 switch (bufferMode)
3001 {
3002 case GL_INTERLEAVED_ATTRIBS:
3003 break;
3004 case GL_SEPARATE_ATTRIBS:
3005 {
3006 const Caps &caps = context->getCaps();
3007 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3008 {
3009 context->handleError(InvalidValue());
3010 return false;
3011 }
3012 break;
3013 }
3014 default:
3015 context->handleError(InvalidEnum());
3016 return false;
3017 }
3018
3019 Program *programObject = GetValidProgram(context, program);
3020 if (!programObject)
3021 {
3022 return false;
3023 }
3024
3025 return true;
3026}
3027
3028bool ValidateGetTransformFeedbackVarying(Context *context,
3029 GLuint program,
3030 GLuint index,
3031 GLsizei bufSize,
3032 GLsizei *length,
3033 GLsizei *size,
3034 GLenum *type,
3035 GLchar *name)
3036{
3037 if (context->getClientMajorVersion() < 3)
3038 {
3039 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3040 return false;
3041 }
3042
3043 if (bufSize < 0)
3044 {
3045 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3046 return false;
3047 }
3048
3049 Program *programObject = GetValidProgram(context, program);
3050 if (!programObject)
3051 {
3052 return false;
3053 }
3054
3055 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3056 {
3057 context->handleError(InvalidValue());
3058 return false;
3059 }
3060
3061 return true;
3062}
3063
3064bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3065{
3066 if (context->getClientMajorVersion() < 3)
3067 {
3068 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3069 return false;
3070 }
3071
3072 switch (target)
3073 {
3074 case GL_TRANSFORM_FEEDBACK:
3075 {
3076 // Cannot bind a transform feedback object if the current one is started and not
3077 // paused (3.0.2 pg 85 section 2.14.1)
3078 TransformFeedback *curTransformFeedback =
3079 context->getGLState().getCurrentTransformFeedback();
3080 if (curTransformFeedback && curTransformFeedback->isActive() &&
3081 !curTransformFeedback->isPaused())
3082 {
3083 context->handleError(InvalidOperation());
3084 return false;
3085 }
3086
3087 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3088 // 2.14.1)
3089 if (!context->isTransformFeedbackGenerated(id))
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3092 return false;
3093 }
3094 }
3095 break;
3096
3097 default:
3098 context->handleError(InvalidEnum());
3099 return false;
3100 }
3101
3102 return true;
3103}
3104
3105bool ValidateIsTransformFeedback(Context *context, GLuint id)
3106{
3107 if (context->getClientMajorVersion() < 3)
3108 {
3109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3110 return false;
3111 }
3112
3113 return true;
3114}
3115
3116bool ValidatePauseTransformFeedback(Context *context)
3117{
3118 if (context->getClientMajorVersion() < 3)
3119 {
3120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3121 return false;
3122 }
3123
3124 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3125 ASSERT(transformFeedback != nullptr);
3126
3127 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3128 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3129 {
3130 context->handleError(InvalidOperation());
3131 return false;
3132 }
3133
3134 return true;
3135}
3136
3137bool ValidateResumeTransformFeedback(Context *context)
3138{
3139 if (context->getClientMajorVersion() < 3)
3140 {
3141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3142 return false;
3143 }
3144
3145 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3146 ASSERT(transformFeedback != nullptr);
3147
3148 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3149 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3150 {
3151 context->handleError(InvalidOperation());
3152 return false;
3153 }
3154
3155 return true;
3156}
3157
Jamie Madill12e957f2017-08-26 21:42:26 -04003158bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3159{
3160 if (context->getClientMajorVersion() < 3)
3161 {
3162 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3163 return false;
3164 }
3165
3166 return ValidateVertexAttribIndex(context, index);
3167}
3168
3169bool ValidateVertexAttribI4ui(Context *context,
3170 GLuint index,
3171 GLuint x,
3172 GLuint y,
3173 GLuint z,
3174 GLuint w)
3175{
3176 if (context->getClientMajorVersion() < 3)
3177 {
3178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3179 return false;
3180 }
3181
3182 return ValidateVertexAttribIndex(context, index);
3183}
3184
3185bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3186{
3187 if (context->getClientMajorVersion() < 3)
3188 {
3189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3190 return false;
3191 }
3192
3193 return ValidateVertexAttribIndex(context, index);
3194}
3195
3196bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3197{
3198 if (context->getClientMajorVersion() < 3)
3199 {
3200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3201 return false;
3202 }
3203
3204 return ValidateVertexAttribIndex(context, index);
3205}
3206
3207bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3208{
3209 if (context->getClientMajorVersion() < 3)
3210 {
3211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3212 return false;
3213 }
3214
3215 Program *programObject = GetValidProgram(context, program);
3216 if (!programObject)
3217 {
3218 return false;
3219 }
3220
3221 if (!programObject->isLinked())
3222 {
3223 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3224 return false;
3225 }
3226
3227 return true;
3228}
3229
3230bool ValidateGetUniformIndices(Context *context,
3231 GLuint program,
3232 GLsizei uniformCount,
3233 const GLchar *const *uniformNames,
3234 GLuint *uniformIndices)
3235{
3236 if (context->getClientMajorVersion() < 3)
3237 {
3238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3239 return false;
3240 }
3241
3242 if (uniformCount < 0)
3243 {
3244 context->handleError(InvalidValue());
3245 return false;
3246 }
3247
3248 Program *programObject = GetValidProgram(context, program);
3249 if (!programObject)
3250 {
3251 return false;
3252 }
3253
3254 return true;
3255}
3256
3257bool ValidateGetActiveUniformsiv(Context *context,
3258 GLuint program,
3259 GLsizei uniformCount,
3260 const GLuint *uniformIndices,
3261 GLenum pname,
3262 GLint *params)
3263{
3264 if (context->getClientMajorVersion() < 3)
3265 {
3266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3267 return false;
3268 }
3269
3270 if (uniformCount < 0)
3271 {
3272 context->handleError(InvalidValue());
3273 return false;
3274 }
3275
3276 Program *programObject = GetValidProgram(context, program);
3277 if (!programObject)
3278 {
3279 return false;
3280 }
3281
3282 switch (pname)
3283 {
3284 case GL_UNIFORM_TYPE:
3285 case GL_UNIFORM_SIZE:
3286 case GL_UNIFORM_NAME_LENGTH:
3287 case GL_UNIFORM_BLOCK_INDEX:
3288 case GL_UNIFORM_OFFSET:
3289 case GL_UNIFORM_ARRAY_STRIDE:
3290 case GL_UNIFORM_MATRIX_STRIDE:
3291 case GL_UNIFORM_IS_ROW_MAJOR:
3292 break;
3293
3294 default:
3295 context->handleError(InvalidEnum());
3296 return false;
3297 }
3298
3299 if (uniformCount > programObject->getActiveUniformCount())
3300 {
3301 context->handleError(InvalidValue());
3302 return false;
3303 }
3304
3305 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3306 {
3307 const GLuint index = uniformIndices[uniformId];
3308
3309 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3310 {
3311 context->handleError(InvalidValue());
3312 return false;
3313 }
3314 }
3315
3316 return true;
3317}
3318
3319bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3320{
3321 if (context->getClientMajorVersion() < 3)
3322 {
3323 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3324 return false;
3325 }
3326
3327 Program *programObject = GetValidProgram(context, program);
3328 if (!programObject)
3329 {
3330 return false;
3331 }
3332
3333 return true;
3334}
3335
3336bool ValidateGetActiveUniformBlockiv(Context *context,
3337 GLuint program,
3338 GLuint uniformBlockIndex,
3339 GLenum pname,
3340 GLint *params)
3341{
3342 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3343}
3344
3345bool ValidateGetActiveUniformBlockName(Context *context,
3346 GLuint program,
3347 GLuint uniformBlockIndex,
3348 GLsizei bufSize,
3349 GLsizei *length,
3350 GLchar *uniformBlockName)
3351{
3352 if (context->getClientMajorVersion() < 3)
3353 {
3354 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3355 return false;
3356 }
3357
3358 Program *programObject = GetValidProgram(context, program);
3359 if (!programObject)
3360 {
3361 return false;
3362 }
3363
3364 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3365 {
3366 context->handleError(InvalidValue());
3367 return false;
3368 }
3369
3370 return true;
3371}
3372
3373bool ValidateUniformBlockBinding(Context *context,
3374 GLuint program,
3375 GLuint uniformBlockIndex,
3376 GLuint uniformBlockBinding)
3377{
3378 if (context->getClientMajorVersion() < 3)
3379 {
3380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3381 return false;
3382 }
3383
3384 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3385 {
3386 context->handleError(InvalidValue());
3387 return false;
3388 }
3389
3390 Program *programObject = GetValidProgram(context, program);
3391 if (!programObject)
3392 {
3393 return false;
3394 }
3395
3396 // if never linked, there won't be any uniform blocks
3397 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3398 {
3399 context->handleError(InvalidValue());
3400 return false;
3401 }
3402
3403 return true;
3404}
3405
3406bool ValidateDrawArraysInstanced(Context *context,
3407 GLenum mode,
3408 GLint first,
3409 GLsizei count,
3410 GLsizei primcount)
3411{
3412 if (context->getClientMajorVersion() < 3)
3413 {
3414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3415 return false;
3416 }
3417
3418 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3419}
3420
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003421bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3422{
3423 if (context->getClientMajorVersion() < 3)
3424 {
3425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3426 return false;
3427 }
3428
3429 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3430 {
3431 context->handleError(InvalidEnum());
3432 return false;
3433 }
3434
3435 if (flags != 0)
3436 {
3437 context->handleError(InvalidValue());
3438 return false;
3439 }
3440
3441 return true;
3442}
3443
3444bool ValidateIsSync(Context *context, GLsync sync)
3445{
3446 if (context->getClientMajorVersion() < 3)
3447 {
3448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3449 return false;
3450 }
3451
3452 return true;
3453}
3454
3455bool ValidateDeleteSync(Context *context, GLsync sync)
3456{
3457 if (context->getClientMajorVersion() < 3)
3458 {
3459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3460 return false;
3461 }
3462
Jamie Madill70b5bb02017-08-28 13:32:37 -04003463 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003464 {
3465 context->handleError(InvalidValue());
3466 return false;
3467 }
3468
3469 return true;
3470}
3471
3472bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3473{
3474 if (context->getClientMajorVersion() < 3)
3475 {
3476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3477 return false;
3478 }
3479
3480 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3481 {
3482 context->handleError(InvalidValue());
3483 return false;
3484 }
3485
Jamie Madill70b5bb02017-08-28 13:32:37 -04003486 Sync *clientWaitSync = context->getSync(sync);
3487 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003488 {
3489 context->handleError(InvalidValue());
3490 return false;
3491 }
3492
3493 return true;
3494}
3495
3496bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3497{
3498 if (context->getClientMajorVersion() < 3)
3499 {
3500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3501 return false;
3502 }
3503
3504 if (flags != 0)
3505 {
3506 context->handleError(InvalidValue());
3507 return false;
3508 }
3509
3510 if (timeout != GL_TIMEOUT_IGNORED)
3511 {
3512 context->handleError(InvalidValue());
3513 return false;
3514 }
3515
Jamie Madill70b5bb02017-08-28 13:32:37 -04003516 Sync *waitSync = context->getSync(sync);
3517 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003518 {
3519 context->handleError(InvalidValue());
3520 return false;
3521 }
3522
3523 return true;
3524}
3525
3526bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3527{
3528 if (context->getClientMajorVersion() < 3)
3529 {
3530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3531 return false;
3532 }
3533
3534 GLenum nativeType = GL_NONE;
3535 unsigned int numParams = 0;
3536 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3537 {
3538 return false;
3539 }
3540
3541 return true;
3542}
3543
Jamie Madill3ef140a2017-08-26 23:11:21 -04003544bool ValidateIsSampler(Context *context, GLuint sampler)
3545{
3546 if (context->getClientMajorVersion() < 3)
3547 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003549 return false;
3550 }
3551
3552 return true;
3553}
3554
3555bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3556{
3557 if (context->getClientMajorVersion() < 3)
3558 {
3559 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3560 return false;
3561 }
3562
3563 if (sampler != 0 && !context->isSampler(sampler))
3564 {
3565 context->handleError(InvalidOperation());
3566 return false;
3567 }
3568
3569 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3570 {
3571 context->handleError(InvalidValue());
3572 return false;
3573 }
3574
3575 return true;
3576}
3577
3578bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3579{
3580 if (context->getClientMajorVersion() < 3)
3581 {
3582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3583 return false;
3584 }
3585
3586 return ValidateVertexAttribIndex(context, index);
3587}
3588
3589bool ValidateTexStorage2D(Context *context,
3590 GLenum target,
3591 GLsizei levels,
3592 GLenum internalformat,
3593 GLsizei width,
3594 GLsizei height)
3595{
3596 if (context->getClientMajorVersion() < 3)
3597 {
3598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3599 return false;
3600 }
3601
3602 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3603 1))
3604 {
3605 return false;
3606 }
3607
3608 return true;
3609}
3610
3611bool ValidateTexStorage3D(Context *context,
3612 GLenum target,
3613 GLsizei levels,
3614 GLenum internalformat,
3615 GLsizei width,
3616 GLsizei height,
3617 GLsizei depth)
3618{
3619 if (context->getClientMajorVersion() < 3)
3620 {
3621 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3622 return false;
3623 }
3624
3625 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3626 depth))
3627 {
3628 return false;
3629 }
3630
3631 return true;
3632}
3633
Jamie Madill9696d072017-08-26 23:19:57 -04003634bool ValidateGetBufferParameteri64v(ValidationContext *context,
3635 GLenum target,
3636 GLenum pname,
3637 GLint64 *params)
3638{
3639 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3640}
3641
3642bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3643{
3644 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3645}
3646
3647bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3648{
3649 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3650}
3651
3652bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3653{
3654 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3655}
3656
3657bool ValidateSamplerParameterfv(Context *context,
3658 GLuint sampler,
3659 GLenum pname,
3660 const GLfloat *params)
3661{
3662 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3663}
3664
3665bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3666{
3667 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3668}
3669
3670bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3671{
3672 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3673}
3674
3675bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3676{
3677 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3678}
3679
3680bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3681{
3682 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3683}
3684
3685bool ValidateGetInternalformativ(Context *context,
3686 GLenum target,
3687 GLenum internalformat,
3688 GLenum pname,
3689 GLsizei bufSize,
3690 GLint *params)
3691{
3692 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3693 nullptr);
3694}
3695
Jamie Madillc29968b2016-01-20 11:17:23 -05003696} // namespace gl