blob: 9e0433a37f6b60db18e7877c336b11edf1661323 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -0400140 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
174 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
201 GLenum target,
202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
218 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700219 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500221 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 }
224
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 // Verify zero border
226 if (border != 0)
227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500228 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 }
231
Jamie Madill6f38f822014-06-06 17:12:20 -0400232 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
233 std::numeric_limits<GLsizei>::max() - xoffset < width ||
234 std::numeric_limits<GLsizei>::max() - yoffset < height ||
235 std::numeric_limits<GLsizei>::max() - zoffset < depth)
236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500237 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400238 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400239 }
240
Geoff Langaae65a42014-05-26 12:43:44 -0400241 const gl::Caps &caps = context->getCaps();
242
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 switch (target)
244 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800245 case GL_TEXTURE_2D:
246 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
247 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800250 return false;
251 }
252 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400254 case GL_TEXTURE_RECTANGLE_ANGLE:
255 ASSERT(level == 0);
256 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
257 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
258 {
259 context->handleError(InvalidValue());
260 return false;
261 }
262 if (isCompressed)
263 {
264 context->handleError(InvalidEnum()
265 << "Rectangle texture cannot have a compressed format.");
266 return false;
267 }
268 break;
269
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
271 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
272 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
276 if (!isSubImage && width != height)
277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500278 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 return false;
280 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500284 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800285 return false;
286 }
287 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400288
He Yunchaoced53ae2016-11-29 15:00:51 +0800289 case GL_TEXTURE_3D:
290 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
291 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
292 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500294 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800295 return false;
296 }
297 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298
He Yunchaoced53ae2016-11-29 15:00:51 +0800299 case GL_TEXTURE_2D_ARRAY:
300 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
301 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
302 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500304 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800305 return false;
306 }
307 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400308
He Yunchaoced53ae2016-11-29 15:00:51 +0800309 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500310 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
He Yunchaoced53ae2016-11-29 15:00:51 +0800314 gl::Texture *texture =
315 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 if (!texture)
317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500318 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 }
321
Geoff Lang69cce582015-09-17 13:20:36 -0400322 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500324 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 }
327
328 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400329 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400330 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500331 if (isSubImage && actualInternalFormat == GL_NONE)
332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500333 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500334 return false;
335 }
336
Geoff Langc4e93662017-05-01 10:45:59 -0400337 const gl::InternalFormat &actualFormatInfo = isSubImage
338 ? *texture->getFormat(target, level).info
339 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 if (isCompressed)
341 {
tmartino7c102692015-10-02 16:43:40 -0400342 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(
345 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400346 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400347 }
348
Geoff Lang966c9402017-04-18 12:38:27 -0400349 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350 {
Geoff Lang966c9402017-04-18 12:38:27 -0400351 if (!ValidCompressedSubImageSize(
352 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
353 texture->getWidth(target, level), texture->getHeight(target, level)))
354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500355 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400356 return false;
357 }
358
359 if (format != actualInternalFormat)
360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500361 context->handleError(InvalidOperation()
362 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400363 return false;
364 }
Geoff Lang86f81162017-10-30 15:10:45 -0400365
366 if (actualInternalFormat == GL_ETC1_RGB8_OES)
367 {
368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
369 return false;
370 }
Geoff Lang966c9402017-04-18 12:38:27 -0400371 }
372 else
373 {
374 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500376 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400377 return false;
378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 }
380
Geoff Langeb66a6e2016-10-31 13:06:12 -0400381 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500383 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400384 return false;
385 }
386
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 if (target == GL_TEXTURE_3D)
388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500389 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392 }
393 else
394 {
Geoff Langca271392017-04-05 12:30:00 -0400395 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 {
Geoff Lang5d601382014-07-22 15:14:06 -0400397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 }
400
401 // Validate sub image parameters
402 if (isSubImage)
403 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500404 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500406 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500412 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 }
415
416 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
417 std::numeric_limits<GLsizei>::max() - yoffset < height ||
418 std::numeric_limits<GLsizei>::max() - zoffset < depth)
419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500420 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 }
423
Geoff Langa9be0dc2014-12-17 12:34:40 -0500424 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
425 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
426 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500428 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
Geoff Langfb052642017-10-24 13:42:09 -0400431
432 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
433 context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER) == nullptr)
434 {
435 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
436 return false;
437 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 }
439
Geoff Langdbcced82017-06-06 15:55:54 -0400440 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
441 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
442 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400443 {
444 return false;
445 }
446
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400447 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700448 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400449 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400450 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800451 // ...data is not evenly divisible into the number of bytes needed to store in memory a
452 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400453 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400454 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400455 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400456 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400457 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
458
Geoff Langff5b2d52016-09-07 11:32:23 -0400459 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500461 context->handleError(InvalidOperation()
462 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400463 return false;
464 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400465 }
466
Jamie Madill7a5f7382014-03-05 15:01:24 -0500467 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700468 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500470 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400471 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500472 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400473 }
474
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400475 return true;
476}
477
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500478bool ValidateES3TexImage2DParameters(Context *context,
479 GLenum target,
480 GLint level,
481 GLenum internalformat,
482 bool isCompressed,
483 bool isSubImage,
484 GLint xoffset,
485 GLint yoffset,
486 GLint zoffset,
487 GLsizei width,
488 GLsizei height,
489 GLsizei depth,
490 GLint border,
491 GLenum format,
492 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400493 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400494 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500495{
496 if (!ValidTexture2DDestinationTarget(context, target))
497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500498 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500499 return false;
500 }
501
502 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
503 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400504 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500505}
506
507bool ValidateES3TexImage3DParameters(Context *context,
508 GLenum target,
509 GLint level,
510 GLenum internalformat,
511 bool isCompressed,
512 bool isSubImage,
513 GLint xoffset,
514 GLint yoffset,
515 GLint zoffset,
516 GLsizei width,
517 GLsizei height,
518 GLsizei depth,
519 GLint border,
520 GLenum format,
521 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400522 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400523 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500524{
525 if (!ValidTexture3DDestinationTarget(context, target))
526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500527 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500528 return false;
529 }
530
531 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
532 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400533 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500534}
535
Geoff Lang5d601382014-07-22 15:14:06 -0400536struct EffectiveInternalFormatInfo
537{
Jamie Madill76648fe2016-10-05 17:01:41 -0400538 GLenum effectiveFormat;
539 GLenum destFormat;
540 GLuint minRedBits;
541 GLuint maxRedBits;
542 GLuint minGreenBits;
543 GLuint maxGreenBits;
544 GLuint minBlueBits;
545 GLuint maxBlueBits;
546 GLuint minAlphaBits;
547 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400548};
549
Jamie Madill76648fe2016-10-05 17:01:41 -0400550static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
551 GLenum targetFormat,
552 const EffectiveInternalFormatInfo *list,
553 size_t size,
554 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400555{
Jamie Madill76648fe2016-10-05 17:01:41 -0400556 for (size_t curFormat = 0; curFormat < size; ++curFormat)
557 {
558 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
559 if ((formatInfo.destFormat == targetFormat) &&
560 (formatInfo.minRedBits <= srcFormat.redBits &&
561 formatInfo.maxRedBits >= srcFormat.redBits) &&
562 (formatInfo.minGreenBits <= srcFormat.greenBits &&
563 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
564 (formatInfo.minBlueBits <= srcFormat.blueBits &&
565 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
566 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
567 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
568 {
569 *outEffectiveFormat = formatInfo.effectiveFormat;
570 return true;
571 }
572 }
Geoff Lang5d601382014-07-22 15:14:06 -0400573
Jamie Madill76648fe2016-10-05 17:01:41 -0400574 *outEffectiveFormat = GL_NONE;
575 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400576}
577
Jamie Madill76648fe2016-10-05 17:01:41 -0400578bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
579 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400580{
Jamie Madill76648fe2016-10-05 17:01:41 -0400581 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
582 // Effective internal format coresponding to destination internal format and linear source
583 // buffer component sizes.
584 // | Source channel min/max sizes |
585 // Effective Internal Format | N/A | R | G | B | A |
586 // clang-format off
587 constexpr EffectiveInternalFormatInfo list[] = {
588 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
589 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
590 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
591 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
592 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
593 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
594 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
595 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
596 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
597 };
598 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400599
Jamie Madill76648fe2016-10-05 17:01:41 -0400600 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
601}
Geoff Lang5d601382014-07-22 15:14:06 -0400602
Jamie Madill76648fe2016-10-05 17:01:41 -0400603bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
604 const InternalFormat &destFormat,
605 GLenum *outEffectiveFormat)
606{
607 constexpr GLuint umax = UINT_MAX;
608
609 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
610 // Effective internal format coresponding to destination internal format andlinear source buffer
611 // component sizes.
612 // | Source channel min/max sizes |
613 // Effective Internal Format | Dest Format | R | G | B | A |
614 // clang-format off
615 constexpr EffectiveInternalFormatInfo list[] = {
616 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
617 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
618 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
619 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
620 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
621 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
622 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
623 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
624 };
625 // clang-format on
626
627 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
628 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400629}
630
He Yunchaoced53ae2016-11-29 15:00:51 +0800631static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
632 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400633 GLenum *outEffectiveFormat)
634{
Geoff Langca271392017-04-05 12:30:00 -0400635 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400636 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400637 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400638 }
639 else
640 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400641 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400642 }
Geoff Lang5d601382014-07-22 15:14:06 -0400643}
644
Corentin Wallez76287682016-04-25 09:23:38 -0400645static bool EqualOrFirstZero(GLuint first, GLuint second)
646{
647 return first == 0 || first == second;
648}
649
Geoff Langca271392017-04-05 12:30:00 -0400650static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
651 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400652 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400653{
Jamie Madill21b786b2016-11-01 17:41:31 -0400654 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400655 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400656 return false;
657 }
Geoff Lang5d601382014-07-22 15:14:06 -0400658
Jamie Madill21b786b2016-11-01 17:41:31 -0400659 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
660 // must both be signed, unsigned, or fixed point and both source and destinations
661 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
662 // conversion between fixed and floating point.
663
664 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
665 (framebufferFormatInfo.colorEncoding == GL_SRGB))
666 {
667 return false;
668 }
669
670 if (((textureFormatInfo.componentType == GL_INT) !=
671 (framebufferFormatInfo.componentType == GL_INT)) ||
672 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
673 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
674 {
675 return false;
676 }
677
678 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
679 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
680 textureFormatInfo.componentType == GL_FLOAT) &&
681 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
682 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
683 framebufferFormatInfo.componentType == GL_FLOAT))
684 {
685 return false;
686 }
687
688 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
689 // The effective internal format of the source buffer is determined with the following rules
690 // applied in order:
691 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
692 // format then the effective internal format is the source buffer's sized internal format.
693 // * If the source buffer is a texture that was created with an unsized base internal format,
694 // then the effective internal format is the source image array's effective internal
695 // format, as specified by table 3.12, which is determined from the <format> and <type>
696 // that were used when the source image array was specified by TexImage*.
697 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
698 // where Destination Internal Format matches internalformat and where the [source channel
699 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
700 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
701 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800702 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400703 if (readBufferHandle != 0)
704 {
705 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
706 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400707 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400708 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400709 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400710 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400711 else
Geoff Lang5d601382014-07-22 15:14:06 -0400712 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400713 // Renderbuffers cannot be created with an unsized internal format, so this must be an
714 // unsized-format texture. We can use the same table we use when creating textures to
715 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400716 sourceEffectiveFormat =
717 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400718 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 }
720 else
721 {
722 // The effective internal format must be derived from the source framebuffer's channel
723 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
724 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400725 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400726 GLenum effectiveFormat;
727 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
728 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400729 {
Geoff Langca271392017-04-05 12:30:00 -0400730 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400731 }
732 else
733 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400734 return false;
735 }
736 }
737 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
738 {
739 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400740 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400741 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
742 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
743 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
744 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
745 {
Geoff Langca271392017-04-05 12:30:00 -0400746 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400747 }
748 else
749 {
750 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400751 }
752 }
753 else
754 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400755 UNREACHABLE();
756 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400757 }
Geoff Lang5d601382014-07-22 15:14:06 -0400758 }
759
Geoff Langca271392017-04-05 12:30:00 -0400760 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400761 {
762 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
763 // sized, component sizes of the source and destination formats must exactly match if the
764 // destination format exists.
765 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
766 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
767 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
768 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
769 {
770 return false;
771 }
772 }
773
774 return true; // A conversion function exists, and no rule in the specification has precluded
775 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400776}
777
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500778bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
779 GLenum target,
780 GLint level,
781 GLenum internalformat,
782 bool isSubImage,
783 GLint xoffset,
784 GLint yoffset,
785 GLint zoffset,
786 GLint x,
787 GLint y,
788 GLsizei width,
789 GLsizei height,
790 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400792 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400793 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400794 xoffset, yoffset, zoffset, x, y, width, height, border,
795 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400796 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400797 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400799 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400800
Jamie Madill51f40ec2016-06-15 14:06:00 -0400801 const auto &state = context->getGLState();
802 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
803 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400804
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400805 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500807 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400808 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400809 }
810
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400811 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500813 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400815 }
816
Jamie Madill0c8abca2016-07-22 20:21:26 -0400817 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818
819 if (isSubImage)
820 {
Geoff Langca271392017-04-05 12:30:00 -0400821 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500822 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500824 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400825 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 }
827 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400828 else
829 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400830 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400831 const InternalFormat &framebufferFormat = *source->getFormat().info;
832 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400833 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500835 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400836 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400837 }
838 }
839
Geoff Lang784a8fd2013-09-24 12:33:16 -0400840 // If width or height is zero, it is a no-op. Return false without setting an error.
841 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842}
843
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500844bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
845 GLenum target,
846 GLint level,
847 GLenum internalformat,
848 bool isSubImage,
849 GLint xoffset,
850 GLint yoffset,
851 GLint zoffset,
852 GLint x,
853 GLint y,
854 GLsizei width,
855 GLsizei height,
856 GLint border)
857{
858 if (!ValidTexture2DDestinationTarget(context, target))
859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500860 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500861 return false;
862 }
863
864 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
865 xoffset, yoffset, zoffset, x, y, width, height,
866 border);
867}
868
869bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
870 GLenum target,
871 GLint level,
872 GLenum internalformat,
873 bool isSubImage,
874 GLint xoffset,
875 GLint yoffset,
876 GLint zoffset,
877 GLint x,
878 GLint y,
879 GLsizei width,
880 GLsizei height,
881 GLint border)
882{
883 if (!ValidTexture3DDestinationTarget(context, target))
884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500885 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500886 return false;
887 }
888
889 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
890 xoffset, yoffset, zoffset, x, y, width, height,
891 border);
892}
893
894bool ValidateES3TexStorageParametersBase(Context *context,
895 GLenum target,
896 GLsizei levels,
897 GLenum internalformat,
898 GLsizei width,
899 GLsizei height,
900 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901{
902 if (width < 1 || height < 1 || depth < 1 || levels < 1)
903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500904 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400905 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400906 }
907
Geoff Langb92c1332015-09-04 12:54:55 -0400908 GLsizei maxDim = std::max(width, height);
909 if (target != GL_TEXTURE_2D_ARRAY)
910 {
911 maxDim = std::max(maxDim, depth);
912 }
913
914 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 }
919
Geoff Langaae65a42014-05-26 12:43:44 -0400920 const gl::Caps &caps = context->getCaps();
921
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 switch (target)
923 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800924 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 {
Geoff Langaae65a42014-05-26 12:43:44 -0400926 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
927 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500929 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400930 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931 }
932 }
933 break;
934
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400935 case GL_TEXTURE_RECTANGLE_ANGLE:
936 {
937 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
938 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
939 {
940 context->handleError(InvalidValue());
941 return false;
942 }
943 }
944 break;
945
He Yunchaoced53ae2016-11-29 15:00:51 +0800946 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 if (width != height)
949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500950 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400951 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 }
953
Geoff Langaae65a42014-05-26 12:43:44 -0400954 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959 }
960 break;
961
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 {
Geoff Langaae65a42014-05-26 12:43:44 -0400964 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
965 static_cast<GLuint>(height) > caps.max3DTextureSize ||
966 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400969 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 }
971 }
972 break;
973
He Yunchaoced53ae2016-11-29 15:00:51 +0800974 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 {
Geoff Langaae65a42014-05-26 12:43:44 -0400976 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
977 static_cast<GLuint>(height) > caps.max2DTextureSize ||
978 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500980 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400981 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 }
983 }
984 break;
985
He Yunchaoced53ae2016-11-29 15:00:51 +0800986 default:
987 UNREACHABLE();
988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 }
990
Geoff Lang691e58c2014-12-19 17:03:25 -0500991 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400992 if (!texture || texture->id() == 0)
993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500994 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 }
997
Geoff Lang69cce582015-09-17 13:20:36 -0400998 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Geoff Langca271392017-04-05 12:30:00 -04001004 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001005 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001007 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001008 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001009 }
1010
Geoff Langca271392017-04-05 12:30:00 -04001011 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001017 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1018 {
1019 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1020 return false;
1021 }
1022
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 return true;
1024}
1025
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001026bool ValidateES3TexStorage2DParameters(Context *context,
1027 GLenum target,
1028 GLsizei levels,
1029 GLenum internalformat,
1030 GLsizei width,
1031 GLsizei height,
1032 GLsizei depth)
1033{
1034 if (!ValidTexture2DTarget(context, target))
1035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001036 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001037 return false;
1038 }
1039
1040 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1041 height, depth);
1042}
1043
1044bool ValidateES3TexStorage3DParameters(Context *context,
1045 GLenum target,
1046 GLsizei levels,
1047 GLenum internalformat,
1048 GLsizei width,
1049 GLsizei height,
1050 GLsizei depth)
1051{
1052 if (!ValidTexture3DTarget(context, target))
1053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001054 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001055 return false;
1056 }
1057
1058 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1059 height, depth);
1060}
1061
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001062bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1063{
Martin Radev1be913c2016-07-11 17:59:16 +03001064 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001065 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001067 return false;
1068 }
1069
1070 return ValidateBeginQueryBase(context, target, id);
1071}
1072
1073bool ValidateEndQuery(gl::Context *context, GLenum target)
1074{
Martin Radev1be913c2016-07-11 17:59:16 +03001075 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001076 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001078 return false;
1079 }
1080
1081 return ValidateEndQueryBase(context, target);
1082}
1083
1084bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1085{
Martin Radev1be913c2016-07-11 17:59:16 +03001086 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001087 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001088 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001089 return false;
1090 }
1091
Geoff Lang2186c382016-10-14 10:54:54 -04001092 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093}
1094
1095bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1096{
Martin Radev1be913c2016-07-11 17:59:16 +03001097 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001098 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001100 return false;
1101 }
1102
Geoff Lang2186c382016-10-14 10:54:54 -04001103 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001104}
1105
He Yunchaoced53ae2016-11-29 15:00:51 +08001106bool ValidateFramebufferTextureLayer(Context *context,
1107 GLenum target,
1108 GLenum attachment,
1109 GLuint texture,
1110 GLint level,
1111 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001112{
Martin Radev1be913c2016-07-11 17:59:16 +03001113 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001114 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001116 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001117 }
1118
Jamie Madill55ec3b12014-07-03 10:38:57 -04001119 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1120 {
1121 return false;
1122 }
1123
1124 const gl::Caps &caps = context->getCaps();
1125 if (texture != 0)
1126 {
Geoff Lang23e02842017-10-17 13:24:09 -04001127 if (layer < 0)
1128 {
1129 context->handleError(InvalidValue());
1130 return false;
1131 }
1132
Jamie Madill55ec3b12014-07-03 10:38:57 -04001133 gl::Texture *tex = context->getTexture(texture);
1134 ASSERT(tex);
1135
1136 switch (tex->getTarget())
1137 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001138 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001139 {
1140 if (level > gl::log2(caps.max2DTextureSize))
1141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001142 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001143 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001144 }
1145
1146 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001150 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001151 }
1152 break;
1153
He Yunchaoced53ae2016-11-29 15:00:51 +08001154 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001155 {
1156 if (level > gl::log2(caps.max3DTextureSize))
1157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001158 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001159 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001160 }
1161
1162 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001166 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001167 }
1168 break;
1169
He Yunchaoced53ae2016-11-29 15:00:51 +08001170 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001172 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001173 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001174
Jamie Madilla3944d42016-07-22 22:13:26 -04001175 const auto &format = tex->getFormat(tex->getTarget(), level);
1176 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001178 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001179 return false;
1180 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001181 }
1182
1183 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001184}
1185
He Yunchaoced53ae2016-11-29 15:00:51 +08001186bool ValidateInvalidateFramebuffer(Context *context,
1187 GLenum target,
1188 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001189 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001190{
Martin Radev1be913c2016-07-11 17:59:16 +03001191 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001192 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001194 return false;
1195 }
1196
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001197 bool defaultFramebuffer = false;
1198
1199 switch (target)
1200 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001201 case GL_DRAW_FRAMEBUFFER:
1202 case GL_FRAMEBUFFER:
1203 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1204 break;
1205 case GL_READ_FRAMEBUFFER:
1206 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1207 break;
1208 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 }
1212
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1214 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215}
1216
Jamie Madill3ef140a2017-08-26 23:11:21 -04001217bool ValidateInvalidateSubFramebuffer(Context *context,
1218 GLenum target,
1219 GLsizei numAttachments,
1220 const GLenum *attachments,
1221 GLint x,
1222 GLint y,
1223 GLsizei width,
1224 GLsizei height)
1225{
1226 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1227}
1228
Jamie Madillc29968b2016-01-20 11:17:23 -05001229bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001230{
Martin Radev1be913c2016-07-11 17:59:16 +03001231 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001232 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001233 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001234 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001235 }
1236
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001237 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001239 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001240 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001241 }
1242
1243 return true;
1244}
1245
Olli Etuaho71dfb362016-03-10 14:04:27 +02001246bool ValidateDrawRangeElements(Context *context,
1247 GLenum mode,
1248 GLuint start,
1249 GLuint end,
1250 GLsizei count,
1251 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001252 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001253{
Martin Radev1be913c2016-07-11 17:59:16 +03001254 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001255 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001257 return false;
1258 }
1259
1260 if (end < start)
1261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001262 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001263 return false;
1264 }
1265
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001266 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001267 {
1268 return false;
1269 }
1270
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001271 // Use the parameter buffer to retrieve and cache the index range.
1272 const auto &params = context->getParams<HasIndexRange>();
1273 const auto &indexRangeOpt = params.getIndexRange();
1274 if (!indexRangeOpt.valid())
1275 {
1276 // Unexpected error.
1277 return false;
1278 }
1279
1280 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001281 {
1282 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001283 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001284 return false;
1285 }
1286 return true;
1287}
1288
He Yunchaoced53ae2016-11-29 15:00:51 +08001289bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001290{
Martin Radev1be913c2016-07-11 17:59:16 +03001291 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001292 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001294 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001295 }
1296
Jamie Madill78f41802014-08-25 15:47:55 -04001297 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001298}
1299
Jamie Madillb885e572015-02-03 16:16:04 -05001300bool ValidateReadBuffer(Context *context, GLenum src)
1301{
Martin Radev1be913c2016-07-11 17:59:16 +03001302 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001303 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001304 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001305 return false;
1306 }
1307
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001308 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001309
1310 if (readFBO == nullptr)
1311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001312 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001313 return false;
1314 }
1315
1316 if (src == GL_NONE)
1317 {
1318 return true;
1319 }
1320
Olli Etuaho84c9f592016-03-09 14:37:25 +02001321 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001323 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001324 return false;
1325 }
1326
1327 if (readFBO->id() == 0)
1328 {
1329 if (src != GL_BACK)
1330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(
1332 InvalidOperation()
1333 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001334 return false;
1335 }
1336 }
1337 else
1338 {
1339 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1340
1341 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001344 return false;
1345 }
1346 }
1347
1348 return true;
1349}
1350
Jamie Madill86af3d22015-07-21 15:14:07 -04001351bool ValidateCompressedTexImage3D(Context *context,
1352 GLenum target,
1353 GLint level,
1354 GLenum internalformat,
1355 GLsizei width,
1356 GLsizei height,
1357 GLsizei depth,
1358 GLint border,
1359 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001360 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001361{
Martin Radev1be913c2016-07-11 17:59:16 +03001362 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001363 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001365 return false;
1366 }
1367
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001368 if (!ValidTextureTarget(context, target))
1369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001371 return false;
1372 }
1373
Jamie Madille2e406c2016-06-02 13:04:10 -04001374 // Validate image size
1375 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001378 return false;
1379 }
1380
Geoff Langca271392017-04-05 12:30:00 -04001381 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001382 if (!formatInfo.compressed)
1383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001385 return false;
1386 }
1387
Jamie Madill513558d2016-06-02 13:04:11 -04001388 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001389 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001390 if (blockSizeOrErr.isError())
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001393 return false;
1394 }
1395 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001398 return false;
1399 }
1400
1401 // 3D texture target validation
1402 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001405 return false;
1406 }
1407
1408 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001409 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001410 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1411 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001412 {
1413 return false;
1414 }
1415
1416 return true;
1417}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001418
Corentin Wallezb2931602017-04-11 15:58:57 -04001419bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1420 GLenum target,
1421 GLint level,
1422 GLenum internalformat,
1423 GLsizei width,
1424 GLsizei height,
1425 GLsizei depth,
1426 GLint border,
1427 GLsizei imageSize,
1428 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001429 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001430{
1431 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1432 {
1433 return false;
1434 }
1435
1436 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1437 depth, border, imageSize, data);
1438}
1439
Austin Kinrossbc781f32015-10-26 09:27:38 -07001440bool ValidateBindVertexArray(Context *context, GLuint array)
1441{
Martin Radev1be913c2016-07-11 17:59:16 +03001442 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001443 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001445 return false;
1446 }
1447
1448 return ValidateBindVertexArrayBase(context, array);
1449}
1450
Jamie Madilld7576732017-08-26 18:49:50 -04001451bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001452{
Martin Radev1be913c2016-07-11 17:59:16 +03001453 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001454 {
Jamie Madilld7576732017-08-26 18:49:50 -04001455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001456 return false;
1457 }
1458
1459 return true;
1460}
Geoff Langc5629752015-12-07 16:29:04 -05001461
Jiajia Qin6eafb042016-12-27 17:04:07 +08001462static bool ValidateBindBufferCommon(Context *context,
1463 GLenum target,
1464 GLuint index,
1465 GLuint buffer,
1466 GLintptr offset,
1467 GLsizeiptr size)
1468{
1469 if (context->getClientMajorVersion() < 3)
1470 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001472 return false;
1473 }
1474
1475 if (buffer != 0 && offset < 0)
1476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001478 return false;
1479 }
1480
1481 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1482 !context->isBufferGenerated(buffer))
1483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001484 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001485 return false;
1486 }
1487
1488 const Caps &caps = context->getCaps();
1489 switch (target)
1490 {
1491 case GL_TRANSFORM_FEEDBACK_BUFFER:
1492 {
1493 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001495 context->handleError(InvalidValue() << "index is greater than or equal to the "
1496 "number of TRANSFORM_FEEDBACK_BUFFER "
1497 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001498 return false;
1499 }
1500 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001503 return false;
1504 }
1505
1506 TransformFeedback *curTransformFeedback =
1507 context->getGLState().getCurrentTransformFeedback();
1508 if (curTransformFeedback && curTransformFeedback->isActive())
1509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidOperation()
1511 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1512 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001513 return false;
1514 }
1515 break;
1516 }
1517 case GL_UNIFORM_BUFFER:
1518 {
1519 if (index >= caps.maxUniformBufferBindings)
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidValue() << "index is greater than or equal to the "
1522 "number of UNIFORM_BUFFER indexed "
1523 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001524 return false;
1525 }
1526
1527 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1528 {
1529 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 InvalidValue()
1531 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001532 return false;
1533 }
1534 break;
1535 }
1536 case GL_ATOMIC_COUNTER_BUFFER:
1537 {
1538 if (context->getClientVersion() < ES_3_1)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidEnum()
1541 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001542 return false;
1543 }
1544 if (index >= caps.maxAtomicCounterBufferBindings)
1545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001546 context->handleError(InvalidValue() << "index is greater than or equal to the "
1547 "number of ATOMIC_COUNTER_BUFFER "
1548 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001549 return false;
1550 }
1551 if (buffer != 0 && (offset % 4) != 0)
1552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001554 return false;
1555 }
1556 break;
1557 }
1558 case GL_SHADER_STORAGE_BUFFER:
1559 {
1560 if (context->getClientVersion() < ES_3_1)
1561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001562 context->handleError(InvalidEnum()
1563 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001564 return false;
1565 }
1566 if (index >= caps.maxShaderStorageBufferBindings)
1567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001568 context->handleError(InvalidValue() << "index is greater than or equal to the "
1569 "number of SHADER_STORAGE_BUFFER "
1570 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001571 return false;
1572 }
1573 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001575 context->handleError(InvalidValue() << "offset must be multiple of value of "
1576 "SHADER_STORAGE_BUFFER_OFFSET_"
1577 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001578 return false;
1579 }
1580 break;
1581 }
1582 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001583 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001584 return false;
1585 }
1586
1587 return true;
1588}
1589
1590bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1591{
1592 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1593}
1594
1595bool ValidateBindBufferRange(Context *context,
1596 GLenum target,
1597 GLuint index,
1598 GLuint buffer,
1599 GLintptr offset,
1600 GLsizeiptr size)
1601{
1602 if (buffer != 0 && size <= 0)
1603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidValue()
1605 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001606 return false;
1607 }
1608 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1609}
1610
Geoff Langc5629752015-12-07 16:29:04 -05001611bool ValidateProgramBinary(Context *context,
1612 GLuint program,
1613 GLenum binaryFormat,
1614 const void *binary,
1615 GLint length)
1616{
Martin Radev1be913c2016-07-11 17:59:16 +03001617 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001618 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001620 return false;
1621 }
1622
1623 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1624}
1625
1626bool ValidateGetProgramBinary(Context *context,
1627 GLuint program,
1628 GLsizei bufSize,
1629 GLsizei *length,
1630 GLenum *binaryFormat,
1631 void *binary)
1632{
Martin Radev1be913c2016-07-11 17:59:16 +03001633 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001634 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001636 return false;
1637 }
1638
1639 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1640}
1641
Olli Etuahof0fee072016-03-30 15:11:58 +03001642bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001643{
Martin Radev1be913c2016-07-11 17:59:16 +03001644 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001647 return false;
1648 }
1649
1650 if (GetValidProgram(context, program) == nullptr)
1651 {
1652 return false;
1653 }
1654
1655 switch (pname)
1656 {
1657 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001658 if (value != GL_FALSE && value != GL_TRUE)
1659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidValue()
1661 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001662 return false;
1663 }
Geoff Langc5629752015-12-07 16:29:04 -05001664 break;
1665
Yunchao He61afff12017-03-14 15:34:03 +08001666 case GL_PROGRAM_SEPARABLE:
1667 if (context->getClientVersion() < ES_3_1)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidEnum()
1670 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001671 return false;
1672 }
1673
1674 if (value != GL_FALSE && value != GL_TRUE)
1675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidValue()
1677 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001678 return false;
1679 }
1680 break;
1681
Geoff Langc5629752015-12-07 16:29:04 -05001682 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001683 context->handleError(InvalidEnum()
1684 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001685 return false;
1686 }
1687
1688 return true;
1689}
Jamie Madillc29968b2016-01-20 11:17:23 -05001690
1691bool ValidateBlitFramebuffer(Context *context,
1692 GLint srcX0,
1693 GLint srcY0,
1694 GLint srcX1,
1695 GLint srcY1,
1696 GLint dstX0,
1697 GLint dstY0,
1698 GLint dstX1,
1699 GLint dstY1,
1700 GLbitfield mask,
1701 GLenum filter)
1702{
Martin Radev1be913c2016-07-11 17:59:16 +03001703 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001704 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001706 return false;
1707 }
1708
1709 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1710 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001711}
Jamie Madillc29968b2016-01-20 11:17:23 -05001712
1713bool ValidateClearBufferiv(ValidationContext *context,
1714 GLenum buffer,
1715 GLint drawbuffer,
1716 const GLint *value)
1717{
1718 switch (buffer)
1719 {
1720 case GL_COLOR:
1721 if (drawbuffer < 0 ||
1722 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
Geoff Lang76e65652017-03-27 14:58:02 -04001727 if (context->getExtensions().webglCompatibility)
1728 {
1729 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001730 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001731 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1732 {
1733 return false;
1734 }
1735 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001736 break;
1737
1738 case GL_STENCIL:
1739 if (drawbuffer != 0)
1740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001741 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 return false;
1743 }
1744 break;
1745
1746 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001747 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750
1751 return ValidateClearBuffer(context);
1752}
1753
1754bool ValidateClearBufferuiv(ValidationContext *context,
1755 GLenum buffer,
1756 GLint drawbuffer,
1757 const GLuint *value)
1758{
1759 switch (buffer)
1760 {
1761 case GL_COLOR:
1762 if (drawbuffer < 0 ||
1763 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001766 return false;
1767 }
Geoff Lang76e65652017-03-27 14:58:02 -04001768 if (context->getExtensions().webglCompatibility)
1769 {
1770 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001771 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001772 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1773 {
1774 return false;
1775 }
1776 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001777 break;
1778
1779 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 return ValidateClearBuffer(context);
1785}
1786
1787bool ValidateClearBufferfv(ValidationContext *context,
1788 GLenum buffer,
1789 GLint drawbuffer,
1790 const GLfloat *value)
1791{
1792 switch (buffer)
1793 {
1794 case GL_COLOR:
1795 if (drawbuffer < 0 ||
1796 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001798 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001799 return false;
1800 }
Geoff Lang76e65652017-03-27 14:58:02 -04001801 if (context->getExtensions().webglCompatibility)
1802 {
1803 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1804 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001805 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001806 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1807 {
1808 return false;
1809 }
1810 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001811 break;
1812
1813 case GL_DEPTH:
1814 if (drawbuffer != 0)
1815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001816 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819 break;
1820
1821 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001822 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001823 return false;
1824 }
1825
1826 return ValidateClearBuffer(context);
1827}
1828
1829bool ValidateClearBufferfi(ValidationContext *context,
1830 GLenum buffer,
1831 GLint drawbuffer,
1832 GLfloat depth,
1833 GLint stencil)
1834{
1835 switch (buffer)
1836 {
1837 case GL_DEPTH_STENCIL:
1838 if (drawbuffer != 0)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001841 return false;
1842 }
1843 break;
1844
1845 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001846 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001847 return false;
1848 }
1849
1850 return ValidateClearBuffer(context);
1851}
1852
1853bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1854{
Martin Radev1be913c2016-07-11 17:59:16 +03001855 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860
1861 return ValidateDrawBuffersBase(context, n, bufs);
1862}
1863
1864bool ValidateCopyTexSubImage3D(Context *context,
1865 GLenum target,
1866 GLint level,
1867 GLint xoffset,
1868 GLint yoffset,
1869 GLint zoffset,
1870 GLint x,
1871 GLint y,
1872 GLsizei width,
1873 GLsizei height)
1874{
Martin Radev1be913c2016-07-11 17:59:16 +03001875 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001877 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 return false;
1879 }
1880
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001881 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1882 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001883}
1884
Jamie Madill73a84962016-02-12 09:27:23 -05001885bool ValidateTexImage3D(Context *context,
1886 GLenum target,
1887 GLint level,
1888 GLint internalformat,
1889 GLsizei width,
1890 GLsizei height,
1891 GLsizei depth,
1892 GLint border,
1893 GLenum format,
1894 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001895 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001896{
Martin Radev1be913c2016-07-11 17:59:16 +03001897 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001898 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001900 return false;
1901 }
1902
1903 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001904 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001905 pixels);
1906}
1907
Geoff Langc52f6f12016-10-14 10:18:00 -04001908bool ValidateTexImage3DRobustANGLE(Context *context,
1909 GLenum target,
1910 GLint level,
1911 GLint internalformat,
1912 GLsizei width,
1913 GLsizei height,
1914 GLsizei depth,
1915 GLint border,
1916 GLenum format,
1917 GLenum type,
1918 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001919 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001920{
1921 if (context->getClientMajorVersion() < 3)
1922 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001924 return false;
1925 }
1926
1927 if (!ValidateRobustEntryPoint(context, bufSize))
1928 {
1929 return false;
1930 }
1931
1932 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1933 0, 0, width, height, depth, border, format, type,
1934 bufSize, pixels);
1935}
1936
Jamie Madill73a84962016-02-12 09:27:23 -05001937bool ValidateTexSubImage3D(Context *context,
1938 GLenum target,
1939 GLint level,
1940 GLint xoffset,
1941 GLint yoffset,
1942 GLint zoffset,
1943 GLsizei width,
1944 GLsizei height,
1945 GLsizei depth,
1946 GLenum format,
1947 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001948 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001949{
Martin Radev1be913c2016-07-11 17:59:16 +03001950 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001951 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001952 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001953 return false;
1954 }
1955
1956 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1957 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001958 -1, pixels);
1959}
1960
1961bool ValidateTexSubImage3DRobustANGLE(Context *context,
1962 GLenum target,
1963 GLint level,
1964 GLint xoffset,
1965 GLint yoffset,
1966 GLint zoffset,
1967 GLsizei width,
1968 GLsizei height,
1969 GLsizei depth,
1970 GLenum format,
1971 GLenum type,
1972 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001973 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001974{
1975 if (context->getClientMajorVersion() < 3)
1976 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001978 return false;
1979 }
1980
1981 if (!ValidateRobustEntryPoint(context, bufSize))
1982 {
1983 return false;
1984 }
1985
1986 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1987 yoffset, zoffset, width, height, depth, 0, format, type,
1988 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001989}
1990
1991bool ValidateCompressedTexSubImage3D(Context *context,
1992 GLenum target,
1993 GLint level,
1994 GLint xoffset,
1995 GLint yoffset,
1996 GLint zoffset,
1997 GLsizei width,
1998 GLsizei height,
1999 GLsizei depth,
2000 GLenum format,
2001 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002002 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002003{
Martin Radev1be913c2016-07-11 17:59:16 +03002004 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002005 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002007 return false;
2008 }
2009
Geoff Langca271392017-04-05 12:30:00 -04002010 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002011 if (!formatInfo.compressed)
2012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002013 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002014 return false;
2015 }
2016
Jamie Madill513558d2016-06-02 13:04:11 -04002017 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002018 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002019 if (blockSizeOrErr.isError())
2020 {
2021 context->handleError(blockSizeOrErr.getError());
2022 return false;
2023 }
2024 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002026 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002027 return false;
2028 }
2029
2030 if (!data)
2031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002032 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002033 return false;
2034 }
2035
Geoff Lang5ca5c652017-10-27 17:29:54 -04002036 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2037 yoffset, zoffset, width, height, depth, 0, format,
2038 GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002039}
Corentin Wallezb2931602017-04-11 15:58:57 -04002040bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2041 GLenum target,
2042 GLint level,
2043 GLint xoffset,
2044 GLint yoffset,
2045 GLint zoffset,
2046 GLsizei width,
2047 GLsizei height,
2048 GLsizei depth,
2049 GLenum format,
2050 GLsizei imageSize,
2051 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002052 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002053{
2054 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2055 {
2056 return false;
2057 }
2058
2059 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2060 height, depth, format, imageSize, data);
2061}
Jamie Madill73a84962016-02-12 09:27:23 -05002062
Olli Etuaho41997e72016-03-10 13:38:39 +02002063bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2064{
2065 return ValidateGenOrDeleteES3(context, n);
2066}
2067
2068bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2069{
2070 return ValidateGenOrDeleteES3(context, n);
2071}
2072
2073bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2074{
2075 return ValidateGenOrDeleteCountES3(context, count);
2076}
2077
2078bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2079{
2080 return ValidateGenOrDeleteCountES3(context, count);
2081}
2082
2083bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2084{
2085 return ValidateGenOrDeleteES3(context, n);
2086}
2087
2088bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2089{
2090 if (!ValidateGenOrDeleteES3(context, n))
2091 {
2092 return false;
2093 }
2094 for (GLint i = 0; i < n; ++i)
2095 {
2096 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2097 if (transformFeedback != nullptr && transformFeedback->isActive())
2098 {
2099 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002100 context->handleError(InvalidOperation()
2101 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002102 return false;
2103 }
2104 }
2105 return true;
2106}
2107
2108bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2109{
2110 return ValidateGenOrDeleteES3(context, n);
2111}
2112
2113bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2114{
2115 return ValidateGenOrDeleteES3(context, n);
2116}
2117
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002118bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2119{
Martin Radev1be913c2016-07-11 17:59:16 +03002120 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002121 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002123 return false;
2124 }
2125 switch (primitiveMode)
2126 {
2127 case GL_TRIANGLES:
2128 case GL_LINES:
2129 case GL_POINTS:
2130 break;
2131
2132 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002133 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002134 return false;
2135 }
2136
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002137 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002138 ASSERT(transformFeedback != nullptr);
2139
2140 if (transformFeedback->isActive())
2141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002142 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002143 return false;
2144 }
Geoff Lang79f71042017-08-14 16:43:43 -04002145
2146 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2147 {
2148 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2149 if (buffer.get() && buffer->isMapped())
2150 {
2151 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2152 return false;
2153 }
2154 }
2155
Olli Etuaho02032bd2017-10-13 18:10:17 +03002156 auto program = context->getGLState().getProgram();
2157
2158 if (!program)
2159 {
2160 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2161 return false;
2162 }
2163
2164 if (program->getTransformFeedbackVaryingCount() == 0)
2165 {
2166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2167 return false;
2168 }
2169
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002170 return true;
2171}
2172
Jamie Madill876429b2017-04-20 15:46:24 -04002173bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002174{
Geoff Lang496c02d2016-10-20 11:38:11 -07002175 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2176}
2177
2178bool ValidateGetBufferPointervRobustANGLE(Context *context,
2179 GLenum target,
2180 GLenum pname,
2181 GLsizei bufSize,
2182 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002183 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002184{
2185 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002186 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002187 return false;
2188 }
2189
Geoff Lang496c02d2016-10-20 11:38:11 -07002190 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2191 {
2192 return false;
2193 }
2194
2195 if (!ValidateRobustBufferSize(context, bufSize, *length))
2196 {
2197 return false;
2198 }
2199
2200 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002201}
2202
2203bool ValidateUnmapBuffer(Context *context, GLenum target)
2204{
Martin Radev1be913c2016-07-11 17:59:16 +03002205 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002206 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002208 return false;
2209 }
2210
2211 return ValidateUnmapBufferBase(context, target);
2212}
2213
2214bool ValidateMapBufferRange(Context *context,
2215 GLenum target,
2216 GLintptr offset,
2217 GLsizeiptr length,
2218 GLbitfield access)
2219{
Martin Radev1be913c2016-07-11 17:59:16 +03002220 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002221 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002223 return false;
2224 }
2225
2226 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2227}
2228
2229bool ValidateFlushMappedBufferRange(Context *context,
2230 GLenum target,
2231 GLintptr offset,
2232 GLsizeiptr length)
2233{
Martin Radev1be913c2016-07-11 17:59:16 +03002234 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002235 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002237 return false;
2238 }
2239
2240 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2241}
2242
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002243bool ValidateIndexedStateQuery(ValidationContext *context,
2244 GLenum pname,
2245 GLuint index,
2246 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002247{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002248 if (length)
2249 {
2250 *length = 0;
2251 }
2252
Martin Radev66fb8202016-07-28 11:45:20 +03002253 GLenum nativeType;
2254 unsigned int numParams;
2255 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002257 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002258 return false;
2259 }
2260
2261 const Caps &caps = context->getCaps();
2262 switch (pname)
2263 {
2264 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2265 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2266 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2267 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002269 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002270 return false;
2271 }
2272 break;
2273
2274 case GL_UNIFORM_BUFFER_START:
2275 case GL_UNIFORM_BUFFER_SIZE:
2276 case GL_UNIFORM_BUFFER_BINDING:
2277 if (index >= caps.maxUniformBufferBindings)
2278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002279 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002280 return false;
2281 }
2282 break;
Shao80957d92017-02-20 21:25:59 +08002283
Martin Radev66fb8202016-07-28 11:45:20 +03002284 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2285 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2286 if (index >= 3u)
2287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002288 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002289 return false;
2290 }
2291 break;
Shao80957d92017-02-20 21:25:59 +08002292
Jiajia Qin6eafb042016-12-27 17:04:07 +08002293 case GL_ATOMIC_COUNTER_BUFFER_START:
2294 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2295 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2296 if (context->getClientVersion() < ES_3_1)
2297 {
2298 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002299 InvalidEnum()
2300 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002301 return false;
2302 }
2303 if (index >= caps.maxAtomicCounterBufferBindings)
2304 {
2305 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002306 InvalidValue()
2307 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002308 return false;
2309 }
2310 break;
Shao80957d92017-02-20 21:25:59 +08002311
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002312 case GL_SHADER_STORAGE_BUFFER_START:
2313 case GL_SHADER_STORAGE_BUFFER_SIZE:
2314 case GL_SHADER_STORAGE_BUFFER_BINDING:
2315 if (context->getClientVersion() < ES_3_1)
2316 {
2317 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002318 InvalidEnum()
2319 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002320 return false;
2321 }
2322 if (index >= caps.maxShaderStorageBufferBindings)
2323 {
2324 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002325 InvalidValue()
2326 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002327 return false;
2328 }
2329 break;
2330
Shao80957d92017-02-20 21:25:59 +08002331 case GL_VERTEX_BINDING_BUFFER:
2332 case GL_VERTEX_BINDING_DIVISOR:
2333 case GL_VERTEX_BINDING_OFFSET:
2334 case GL_VERTEX_BINDING_STRIDE:
2335 if (context->getClientVersion() < ES_3_1)
2336 {
2337 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002338 InvalidEnum()
2339 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002340 return false;
2341 }
2342 if (index >= caps.maxVertexAttribBindings)
2343 {
2344 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 InvalidValue()
2346 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002347 return false;
2348 }
2349 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002350 case GL_SAMPLE_MASK_VALUE:
2351 if (context->getClientVersion() < ES_3_1)
2352 {
2353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2354 return false;
2355 }
2356 if (index >= caps.maxSampleMaskWords)
2357 {
2358 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2359 return false;
2360 }
2361 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002362 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002364 return false;
2365 }
2366
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002367 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002368 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002369 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002370 }
2371
2372 return true;
2373}
2374
2375bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2376{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002377 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002378 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002380 return false;
2381 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002382 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002383}
2384
Geoff Langcf255ea2016-10-20 11:39:09 -07002385bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2386 GLenum target,
2387 GLuint index,
2388 GLsizei bufSize,
2389 GLsizei *length,
2390 GLint *data)
2391{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002392 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002393 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002395 return false;
2396 }
2397
2398 if (!ValidateRobustEntryPoint(context, bufSize))
2399 {
2400 return false;
2401 }
2402
2403 if (!ValidateIndexedStateQuery(context, target, index, length))
2404 {
2405 return false;
2406 }
2407
2408 if (!ValidateRobustBufferSize(context, bufSize, *length))
2409 {
2410 return false;
2411 }
2412
2413 return true;
2414}
2415
Martin Radev66fb8202016-07-28 11:45:20 +03002416bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2417{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002418 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002419 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002420 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002421 return false;
2422 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002423 return ValidateIndexedStateQuery(context, target, index, nullptr);
2424}
2425
2426bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2427 GLenum target,
2428 GLuint index,
2429 GLsizei bufSize,
2430 GLsizei *length,
2431 GLint64 *data)
2432{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002433 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002434 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002435 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002436 return false;
2437 }
2438
2439 if (!ValidateRobustEntryPoint(context, bufSize))
2440 {
2441 return false;
2442 }
2443
2444 if (!ValidateIndexedStateQuery(context, target, index, length))
2445 {
2446 return false;
2447 }
2448
2449 if (!ValidateRobustBufferSize(context, bufSize, *length))
2450 {
2451 return false;
2452 }
2453
2454 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002455}
2456
Jamie Madillb0817d12016-11-01 15:48:31 -04002457bool ValidateCopyBufferSubData(ValidationContext *context,
2458 GLenum readTarget,
2459 GLenum writeTarget,
2460 GLintptr readOffset,
2461 GLintptr writeOffset,
2462 GLsizeiptr size)
2463{
2464 if (context->getClientMajorVersion() < 3)
2465 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002467 return false;
2468 }
2469
2470 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002472 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002473 return false;
2474 }
2475
2476 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2477 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2478
2479 if (!readBuffer || !writeBuffer)
2480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002482 return false;
2483 }
2484
2485 // Verify that readBuffer and writeBuffer are not currently mapped
2486 if (readBuffer->isMapped() || writeBuffer->isMapped())
2487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidOperation()
2489 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002490 return false;
2491 }
2492
Jamie Madilld2f0c742016-11-02 10:34:41 -04002493 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2494 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2495 CheckedNumeric<GLintptr> checkedSize(size);
2496
2497 auto checkedReadSum = checkedReadOffset + checkedSize;
2498 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2499
2500 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2501 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2502 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002505 return false;
2506 }
2507
Jamie Madilld2f0c742016-11-02 10:34:41 -04002508 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002510 context->handleError(InvalidValue()
2511 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002512 return false;
2513 }
2514
Jamie Madilld2f0c742016-11-02 10:34:41 -04002515 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2516 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002518 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002519 return false;
2520 }
2521
2522 if (readBuffer == writeBuffer)
2523 {
2524 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2525 if (!checkedOffsetDiff.IsValid())
2526 {
2527 // This shold not be possible.
2528 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidValue()
2530 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002531 return false;
2532 }
2533
2534 if (checkedOffsetDiff.ValueOrDie() < size)
2535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002536 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002537 return false;
2538 }
2539 }
2540
Jamie Madillb0817d12016-11-01 15:48:31 -04002541 return true;
2542}
2543
Geoff Langc339c4e2016-11-29 10:37:36 -05002544bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2545{
2546 if (context->getClientMajorVersion() < 3)
2547 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002549 return false;
2550 }
2551
2552 switch (name)
2553 {
2554 case GL_EXTENSIONS:
2555 if (index >= context->getExtensionStringCount())
2556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002557 context->handleError(InvalidValue()
2558 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002559 return false;
2560 }
2561 break;
2562
2563 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2564 if (!context->getExtensions().requestExtension)
2565 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002567 return false;
2568 }
2569 if (index >= context->getRequestableExtensionStringCount())
2570 {
2571 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002572 InvalidValue()
2573 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002574 return false;
2575 }
2576 break;
2577
2578 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002580 return false;
2581 }
2582
2583 return true;
2584}
2585
Jamie Madille8fb6402017-02-14 17:56:40 -05002586bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2587 GLenum target,
2588 GLsizei samples,
2589 GLenum internalformat,
2590 GLsizei width,
2591 GLsizei height)
2592{
2593 if (context->getClientMajorVersion() < 3)
2594 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002596 return false;
2597 }
2598
2599 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2600 height))
2601 {
2602 return false;
2603 }
2604
2605 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2606 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002607 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002608 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2609 samples > 0)
2610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002611 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002612 return false;
2613 }
2614
2615 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2616 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2617 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2618 {
2619 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002620 InvalidOperation()
2621 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002622 return false;
2623 }
2624
2625 return true;
2626}
2627
Geoff Langaa086d62017-03-23 16:47:21 -04002628bool ValidateVertexAttribIPointer(ValidationContext *context,
2629 GLuint index,
2630 GLint size,
2631 GLenum type,
2632 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002633 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002634{
2635 if (context->getClientMajorVersion() < 3)
2636 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002638 return false;
2639 }
2640
Shao80957d92017-02-20 21:25:59 +08002641 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002642 {
Geoff Langaa086d62017-03-23 16:47:21 -04002643 return false;
2644 }
2645
Geoff Langaa086d62017-03-23 16:47:21 -04002646 if (stride < 0)
2647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002648 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002649 return false;
2650 }
2651
Shao80957d92017-02-20 21:25:59 +08002652 const Caps &caps = context->getCaps();
2653 if (context->getClientVersion() >= ES_3_1)
2654 {
2655 if (stride > caps.maxVertexAttribStride)
2656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002657 context->handleError(InvalidValue()
2658 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002659 return false;
2660 }
2661
2662 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2663 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2664 // validation should be inherited.
2665 if (index >= caps.maxVertexAttribBindings)
2666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002667 context->handleError(InvalidValue()
2668 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002669 return false;
2670 }
2671 }
2672
Geoff Langaa086d62017-03-23 16:47:21 -04002673 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2674 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2675 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2676 // and the pointer argument is not NULL.
2677 if (context->getGLState().getVertexArrayId() != 0 &&
2678 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002680 context
2681 ->handleError(InvalidOperation()
2682 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002683 return false;
2684 }
2685
Geoff Lang2d62ab72017-03-23 16:54:40 -04002686 if (context->getExtensions().webglCompatibility)
2687 {
2688 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2689 {
2690 return false;
2691 }
2692 }
2693
Geoff Langaa086d62017-03-23 16:47:21 -04002694 return true;
2695}
2696
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002697bool ValidateGetSynciv(Context *context,
2698 GLsync sync,
2699 GLenum pname,
2700 GLsizei bufSize,
2701 GLsizei *length,
2702 GLint *values)
2703{
2704 if (context->getClientMajorVersion() < 3)
2705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002707 return false;
2708 }
2709
2710 if (bufSize < 0)
2711 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002712 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002713 return false;
2714 }
2715
Jamie Madill70b5bb02017-08-28 13:32:37 -04002716 Sync *syncObject = context->getSync(sync);
2717 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002719 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002720 return false;
2721 }
2722
2723 switch (pname)
2724 {
2725 case GL_OBJECT_TYPE:
2726 case GL_SYNC_CONDITION:
2727 case GL_SYNC_FLAGS:
2728 case GL_SYNC_STATUS:
2729 break;
2730
2731 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002732 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002733 return false;
2734 }
2735
2736 return true;
2737}
2738
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002739bool ValidateDrawElementsInstanced(ValidationContext *context,
2740 GLenum mode,
2741 GLsizei count,
2742 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002743 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002744 GLsizei instanceCount)
2745{
2746 if (context->getClientMajorVersion() < 3)
2747 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002748 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002749 return false;
2750 }
2751
2752 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2753}
2754
Martin Radev137032d2017-07-13 10:11:12 +03002755bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2756 GLenum target,
2757 GLenum attachment,
2758 GLuint texture,
2759 GLint level,
2760 GLint baseViewIndex,
2761 GLsizei numViews)
2762{
2763
2764 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2765 numViews))
2766 {
2767 return false;
2768 }
2769
Martin Radev137032d2017-07-13 10:11:12 +03002770 if (texture != 0)
2771 {
Martin Radev14b21262017-08-25 13:54:37 +03002772 if (baseViewIndex < 0)
2773 {
2774 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2775 return false;
2776 }
2777
Martin Radev137032d2017-07-13 10:11:12 +03002778 Texture *tex = context->getTexture(texture);
2779 ASSERT(tex);
2780
2781 switch (tex->getTarget())
2782 {
2783 case GL_TEXTURE_2D_ARRAY:
2784 {
2785 const Caps &caps = context->getCaps();
2786 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2787 {
2788 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2789 "greater than "
2790 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2791 return false;
2792 }
2793 }
2794 break;
2795 default:
2796 context->handleError(InvalidOperation()
2797 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2798 return false;
2799 }
2800
2801 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2802 {
2803 return false;
2804 }
2805 }
2806
2807 return true;
2808}
2809
2810bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2811 GLenum target,
2812 GLenum attachment,
2813 GLuint texture,
2814 GLint level,
2815 GLsizei numViews,
2816 const GLint *viewportOffsets)
2817{
2818 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2819 numViews))
2820 {
2821 return false;
2822 }
2823
Martin Radev137032d2017-07-13 10:11:12 +03002824 if (texture != 0)
2825 {
Martin Radev14b21262017-08-25 13:54:37 +03002826 const GLsizei numViewportOffsetValues = numViews * 2;
2827 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2828 {
2829 if (viewportOffsets[i] < 0)
2830 {
2831 context->handleError(InvalidValue()
2832 << "viewportOffsets cannot contain negative values.");
2833 return false;
2834 }
2835 }
2836
Martin Radev137032d2017-07-13 10:11:12 +03002837 Texture *tex = context->getTexture(texture);
2838 ASSERT(tex);
2839
2840 switch (tex->getTarget())
2841 {
2842 case GL_TEXTURE_2D:
2843 break;
2844 default:
2845 context->handleError(InvalidOperation()
2846 << "Texture's target must be GL_TEXTURE_2D.");
2847 return false;
2848 }
2849
2850 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2851 {
2852 return false;
2853 }
2854 }
2855
2856 return true;
2857}
2858
Jamie Madillff325f12017-08-26 15:06:05 -04002859bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2860{
2861 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2862}
2863
2864bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2865{
2866 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2867}
2868
2869bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2870{
2871 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2872}
2873
2874bool ValidateUniform4ui(Context *context,
2875 GLint location,
2876 GLuint v0,
2877 GLuint v1,
2878 GLuint v2,
2879 GLuint v3)
2880{
2881 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2882}
2883
2884bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2885{
2886 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2887}
2888
2889bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2890{
2891 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2892}
2893
2894bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2895{
2896 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2897}
2898
2899bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2900{
2901 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2902}
2903
Jamie Madillf0e04492017-08-26 15:28:42 -04002904bool ValidateIsQuery(Context *context, GLuint id)
2905{
2906 if (context->getClientMajorVersion() < 3)
2907 {
2908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2909 return false;
2910 }
2911
2912 return true;
2913}
2914
Jamie Madillc8c95812017-08-26 18:40:09 -04002915bool ValidateUniformMatrix2x3fv(Context *context,
2916 GLint location,
2917 GLsizei count,
2918 GLboolean transpose,
2919 const GLfloat *value)
2920{
2921 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2922}
2923
2924bool ValidateUniformMatrix3x2fv(Context *context,
2925 GLint location,
2926 GLsizei count,
2927 GLboolean transpose,
2928 const GLfloat *value)
2929{
2930 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2931}
2932
2933bool ValidateUniformMatrix2x4fv(Context *context,
2934 GLint location,
2935 GLsizei count,
2936 GLboolean transpose,
2937 const GLfloat *value)
2938{
2939 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2940}
2941
2942bool ValidateUniformMatrix4x2fv(Context *context,
2943 GLint location,
2944 GLsizei count,
2945 GLboolean transpose,
2946 const GLfloat *value)
2947{
2948 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2949}
2950
2951bool ValidateUniformMatrix3x4fv(Context *context,
2952 GLint location,
2953 GLsizei count,
2954 GLboolean transpose,
2955 const GLfloat *value)
2956{
2957 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2958}
2959
2960bool ValidateUniformMatrix4x3fv(Context *context,
2961 GLint location,
2962 GLsizei count,
2963 GLboolean transpose,
2964 const GLfloat *value)
2965{
2966 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2967}
2968
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002969bool ValidateEndTransformFeedback(Context *context)
2970{
2971 if (context->getClientMajorVersion() < 3)
2972 {
2973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2974 return false;
2975 }
2976
2977 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2978 ASSERT(transformFeedback != nullptr);
2979
2980 if (!transformFeedback->isActive())
2981 {
2982 context->handleError(InvalidOperation());
2983 return false;
2984 }
2985
2986 return true;
2987}
2988
2989bool ValidateTransformFeedbackVaryings(Context *context,
2990 GLuint program,
2991 GLsizei count,
2992 const GLchar *const *varyings,
2993 GLenum bufferMode)
2994{
2995 if (context->getClientMajorVersion() < 3)
2996 {
2997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2998 return false;
2999 }
3000
3001 if (count < 0)
3002 {
3003 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3004 return false;
3005 }
3006
3007 switch (bufferMode)
3008 {
3009 case GL_INTERLEAVED_ATTRIBS:
3010 break;
3011 case GL_SEPARATE_ATTRIBS:
3012 {
3013 const Caps &caps = context->getCaps();
3014 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3015 {
3016 context->handleError(InvalidValue());
3017 return false;
3018 }
3019 break;
3020 }
3021 default:
3022 context->handleError(InvalidEnum());
3023 return false;
3024 }
3025
3026 Program *programObject = GetValidProgram(context, program);
3027 if (!programObject)
3028 {
3029 return false;
3030 }
3031
3032 return true;
3033}
3034
3035bool ValidateGetTransformFeedbackVarying(Context *context,
3036 GLuint program,
3037 GLuint index,
3038 GLsizei bufSize,
3039 GLsizei *length,
3040 GLsizei *size,
3041 GLenum *type,
3042 GLchar *name)
3043{
3044 if (context->getClientMajorVersion() < 3)
3045 {
3046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3047 return false;
3048 }
3049
3050 if (bufSize < 0)
3051 {
3052 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3053 return false;
3054 }
3055
3056 Program *programObject = GetValidProgram(context, program);
3057 if (!programObject)
3058 {
3059 return false;
3060 }
3061
3062 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3063 {
3064 context->handleError(InvalidValue());
3065 return false;
3066 }
3067
3068 return true;
3069}
3070
3071bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3072{
3073 if (context->getClientMajorVersion() < 3)
3074 {
3075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3076 return false;
3077 }
3078
3079 switch (target)
3080 {
3081 case GL_TRANSFORM_FEEDBACK:
3082 {
3083 // Cannot bind a transform feedback object if the current one is started and not
3084 // paused (3.0.2 pg 85 section 2.14.1)
3085 TransformFeedback *curTransformFeedback =
3086 context->getGLState().getCurrentTransformFeedback();
3087 if (curTransformFeedback && curTransformFeedback->isActive() &&
3088 !curTransformFeedback->isPaused())
3089 {
3090 context->handleError(InvalidOperation());
3091 return false;
3092 }
3093
3094 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3095 // 2.14.1)
3096 if (!context->isTransformFeedbackGenerated(id))
3097 {
3098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3099 return false;
3100 }
3101 }
3102 break;
3103
3104 default:
3105 context->handleError(InvalidEnum());
3106 return false;
3107 }
3108
3109 return true;
3110}
3111
3112bool ValidateIsTransformFeedback(Context *context, GLuint id)
3113{
3114 if (context->getClientMajorVersion() < 3)
3115 {
3116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3117 return false;
3118 }
3119
3120 return true;
3121}
3122
3123bool ValidatePauseTransformFeedback(Context *context)
3124{
3125 if (context->getClientMajorVersion() < 3)
3126 {
3127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3128 return false;
3129 }
3130
3131 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3132 ASSERT(transformFeedback != nullptr);
3133
3134 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3135 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3136 {
3137 context->handleError(InvalidOperation());
3138 return false;
3139 }
3140
3141 return true;
3142}
3143
3144bool ValidateResumeTransformFeedback(Context *context)
3145{
3146 if (context->getClientMajorVersion() < 3)
3147 {
3148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3149 return false;
3150 }
3151
3152 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3153 ASSERT(transformFeedback != nullptr);
3154
3155 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3156 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3157 {
3158 context->handleError(InvalidOperation());
3159 return false;
3160 }
3161
3162 return true;
3163}
3164
Jamie Madill12e957f2017-08-26 21:42:26 -04003165bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3166{
3167 if (context->getClientMajorVersion() < 3)
3168 {
3169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3170 return false;
3171 }
3172
3173 return ValidateVertexAttribIndex(context, index);
3174}
3175
3176bool ValidateVertexAttribI4ui(Context *context,
3177 GLuint index,
3178 GLuint x,
3179 GLuint y,
3180 GLuint z,
3181 GLuint w)
3182{
3183 if (context->getClientMajorVersion() < 3)
3184 {
3185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3186 return false;
3187 }
3188
3189 return ValidateVertexAttribIndex(context, index);
3190}
3191
3192bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3193{
3194 if (context->getClientMajorVersion() < 3)
3195 {
3196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3197 return false;
3198 }
3199
3200 return ValidateVertexAttribIndex(context, index);
3201}
3202
3203bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3204{
3205 if (context->getClientMajorVersion() < 3)
3206 {
3207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3208 return false;
3209 }
3210
3211 return ValidateVertexAttribIndex(context, index);
3212}
3213
3214bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3215{
3216 if (context->getClientMajorVersion() < 3)
3217 {
3218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3219 return false;
3220 }
3221
3222 Program *programObject = GetValidProgram(context, program);
3223 if (!programObject)
3224 {
3225 return false;
3226 }
3227
3228 if (!programObject->isLinked())
3229 {
3230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3231 return false;
3232 }
3233
3234 return true;
3235}
3236
3237bool ValidateGetUniformIndices(Context *context,
3238 GLuint program,
3239 GLsizei uniformCount,
3240 const GLchar *const *uniformNames,
3241 GLuint *uniformIndices)
3242{
3243 if (context->getClientMajorVersion() < 3)
3244 {
3245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3246 return false;
3247 }
3248
3249 if (uniformCount < 0)
3250 {
3251 context->handleError(InvalidValue());
3252 return false;
3253 }
3254
3255 Program *programObject = GetValidProgram(context, program);
3256 if (!programObject)
3257 {
3258 return false;
3259 }
3260
3261 return true;
3262}
3263
3264bool ValidateGetActiveUniformsiv(Context *context,
3265 GLuint program,
3266 GLsizei uniformCount,
3267 const GLuint *uniformIndices,
3268 GLenum pname,
3269 GLint *params)
3270{
3271 if (context->getClientMajorVersion() < 3)
3272 {
3273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3274 return false;
3275 }
3276
3277 if (uniformCount < 0)
3278 {
3279 context->handleError(InvalidValue());
3280 return false;
3281 }
3282
3283 Program *programObject = GetValidProgram(context, program);
3284 if (!programObject)
3285 {
3286 return false;
3287 }
3288
3289 switch (pname)
3290 {
3291 case GL_UNIFORM_TYPE:
3292 case GL_UNIFORM_SIZE:
3293 case GL_UNIFORM_NAME_LENGTH:
3294 case GL_UNIFORM_BLOCK_INDEX:
3295 case GL_UNIFORM_OFFSET:
3296 case GL_UNIFORM_ARRAY_STRIDE:
3297 case GL_UNIFORM_MATRIX_STRIDE:
3298 case GL_UNIFORM_IS_ROW_MAJOR:
3299 break;
3300
3301 default:
3302 context->handleError(InvalidEnum());
3303 return false;
3304 }
3305
3306 if (uniformCount > programObject->getActiveUniformCount())
3307 {
3308 context->handleError(InvalidValue());
3309 return false;
3310 }
3311
3312 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3313 {
3314 const GLuint index = uniformIndices[uniformId];
3315
3316 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3317 {
3318 context->handleError(InvalidValue());
3319 return false;
3320 }
3321 }
3322
3323 return true;
3324}
3325
3326bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3327{
3328 if (context->getClientMajorVersion() < 3)
3329 {
3330 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3331 return false;
3332 }
3333
3334 Program *programObject = GetValidProgram(context, program);
3335 if (!programObject)
3336 {
3337 return false;
3338 }
3339
3340 return true;
3341}
3342
3343bool ValidateGetActiveUniformBlockiv(Context *context,
3344 GLuint program,
3345 GLuint uniformBlockIndex,
3346 GLenum pname,
3347 GLint *params)
3348{
3349 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3350}
3351
3352bool ValidateGetActiveUniformBlockName(Context *context,
3353 GLuint program,
3354 GLuint uniformBlockIndex,
3355 GLsizei bufSize,
3356 GLsizei *length,
3357 GLchar *uniformBlockName)
3358{
3359 if (context->getClientMajorVersion() < 3)
3360 {
3361 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3362 return false;
3363 }
3364
3365 Program *programObject = GetValidProgram(context, program);
3366 if (!programObject)
3367 {
3368 return false;
3369 }
3370
3371 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3372 {
3373 context->handleError(InvalidValue());
3374 return false;
3375 }
3376
3377 return true;
3378}
3379
3380bool ValidateUniformBlockBinding(Context *context,
3381 GLuint program,
3382 GLuint uniformBlockIndex,
3383 GLuint uniformBlockBinding)
3384{
3385 if (context->getClientMajorVersion() < 3)
3386 {
3387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3388 return false;
3389 }
3390
3391 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3392 {
3393 context->handleError(InvalidValue());
3394 return false;
3395 }
3396
3397 Program *programObject = GetValidProgram(context, program);
3398 if (!programObject)
3399 {
3400 return false;
3401 }
3402
3403 // if never linked, there won't be any uniform blocks
3404 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3405 {
3406 context->handleError(InvalidValue());
3407 return false;
3408 }
3409
3410 return true;
3411}
3412
3413bool ValidateDrawArraysInstanced(Context *context,
3414 GLenum mode,
3415 GLint first,
3416 GLsizei count,
3417 GLsizei primcount)
3418{
3419 if (context->getClientMajorVersion() < 3)
3420 {
3421 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3422 return false;
3423 }
3424
3425 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3426}
3427
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003428bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3429{
3430 if (context->getClientMajorVersion() < 3)
3431 {
3432 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3433 return false;
3434 }
3435
3436 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3437 {
3438 context->handleError(InvalidEnum());
3439 return false;
3440 }
3441
3442 if (flags != 0)
3443 {
3444 context->handleError(InvalidValue());
3445 return false;
3446 }
3447
3448 return true;
3449}
3450
3451bool ValidateIsSync(Context *context, GLsync sync)
3452{
3453 if (context->getClientMajorVersion() < 3)
3454 {
3455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3456 return false;
3457 }
3458
3459 return true;
3460}
3461
3462bool ValidateDeleteSync(Context *context, GLsync sync)
3463{
3464 if (context->getClientMajorVersion() < 3)
3465 {
3466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3467 return false;
3468 }
3469
Jamie Madill70b5bb02017-08-28 13:32:37 -04003470 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003471 {
3472 context->handleError(InvalidValue());
3473 return false;
3474 }
3475
3476 return true;
3477}
3478
3479bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3480{
3481 if (context->getClientMajorVersion() < 3)
3482 {
3483 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3484 return false;
3485 }
3486
3487 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3488 {
3489 context->handleError(InvalidValue());
3490 return false;
3491 }
3492
Jamie Madill70b5bb02017-08-28 13:32:37 -04003493 Sync *clientWaitSync = context->getSync(sync);
3494 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003495 {
3496 context->handleError(InvalidValue());
3497 return false;
3498 }
3499
3500 return true;
3501}
3502
3503bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3504{
3505 if (context->getClientMajorVersion() < 3)
3506 {
3507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3508 return false;
3509 }
3510
3511 if (flags != 0)
3512 {
3513 context->handleError(InvalidValue());
3514 return false;
3515 }
3516
3517 if (timeout != GL_TIMEOUT_IGNORED)
3518 {
3519 context->handleError(InvalidValue());
3520 return false;
3521 }
3522
Jamie Madill70b5bb02017-08-28 13:32:37 -04003523 Sync *waitSync = context->getSync(sync);
3524 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003525 {
3526 context->handleError(InvalidValue());
3527 return false;
3528 }
3529
3530 return true;
3531}
3532
3533bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3534{
3535 if (context->getClientMajorVersion() < 3)
3536 {
3537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3538 return false;
3539 }
3540
3541 GLenum nativeType = GL_NONE;
3542 unsigned int numParams = 0;
3543 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3544 {
3545 return false;
3546 }
3547
3548 return true;
3549}
3550
Jamie Madill3ef140a2017-08-26 23:11:21 -04003551bool ValidateIsSampler(Context *context, GLuint sampler)
3552{
3553 if (context->getClientMajorVersion() < 3)
3554 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003555 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003556 return false;
3557 }
3558
3559 return true;
3560}
3561
3562bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3563{
3564 if (context->getClientMajorVersion() < 3)
3565 {
3566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3567 return false;
3568 }
3569
3570 if (sampler != 0 && !context->isSampler(sampler))
3571 {
3572 context->handleError(InvalidOperation());
3573 return false;
3574 }
3575
3576 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3577 {
3578 context->handleError(InvalidValue());
3579 return false;
3580 }
3581
3582 return true;
3583}
3584
3585bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3586{
3587 if (context->getClientMajorVersion() < 3)
3588 {
3589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3590 return false;
3591 }
3592
3593 return ValidateVertexAttribIndex(context, index);
3594}
3595
3596bool ValidateTexStorage2D(Context *context,
3597 GLenum target,
3598 GLsizei levels,
3599 GLenum internalformat,
3600 GLsizei width,
3601 GLsizei height)
3602{
3603 if (context->getClientMajorVersion() < 3)
3604 {
3605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3606 return false;
3607 }
3608
3609 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3610 1))
3611 {
3612 return false;
3613 }
3614
3615 return true;
3616}
3617
3618bool ValidateTexStorage3D(Context *context,
3619 GLenum target,
3620 GLsizei levels,
3621 GLenum internalformat,
3622 GLsizei width,
3623 GLsizei height,
3624 GLsizei depth)
3625{
3626 if (context->getClientMajorVersion() < 3)
3627 {
3628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3629 return false;
3630 }
3631
3632 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3633 depth))
3634 {
3635 return false;
3636 }
3637
3638 return true;
3639}
3640
Jamie Madill9696d072017-08-26 23:19:57 -04003641bool ValidateGetBufferParameteri64v(ValidationContext *context,
3642 GLenum target,
3643 GLenum pname,
3644 GLint64 *params)
3645{
3646 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3647}
3648
3649bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3650{
3651 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3652}
3653
3654bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3655{
3656 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3657}
3658
3659bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3660{
3661 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3662}
3663
3664bool ValidateSamplerParameterfv(Context *context,
3665 GLuint sampler,
3666 GLenum pname,
3667 const GLfloat *params)
3668{
3669 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3670}
3671
3672bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3673{
3674 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3675}
3676
3677bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3678{
3679 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3680}
3681
3682bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3683{
3684 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3685}
3686
3687bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3688{
3689 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3690}
3691
3692bool ValidateGetInternalformativ(Context *context,
3693 GLenum target,
3694 GLenum internalformat,
3695 GLenum pname,
3696 GLsizei bufSize,
3697 GLint *params)
3698{
3699 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3700 nullptr);
3701}
3702
Jamie Madillc29968b2016-01-20 11:17:23 -05003703} // namespace gl