blob: 5ff83debe64110b2f971a7819fedf416a50c7e23 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -0400140 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
174 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
201 GLenum target,
202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
218 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700219 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500221 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 }
224
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 // Verify zero border
226 if (border != 0)
227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500228 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 }
231
Jamie Madill6f38f822014-06-06 17:12:20 -0400232 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
233 std::numeric_limits<GLsizei>::max() - xoffset < width ||
234 std::numeric_limits<GLsizei>::max() - yoffset < height ||
235 std::numeric_limits<GLsizei>::max() - zoffset < depth)
236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500237 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400238 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400239 }
240
Geoff Langaae65a42014-05-26 12:43:44 -0400241 const gl::Caps &caps = context->getCaps();
242
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 switch (target)
244 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800245 case GL_TEXTURE_2D:
246 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
247 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800250 return false;
251 }
252 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400254 case GL_TEXTURE_RECTANGLE_ANGLE:
255 ASSERT(level == 0);
256 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
257 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
258 {
259 context->handleError(InvalidValue());
260 return false;
261 }
262 if (isCompressed)
263 {
264 context->handleError(InvalidEnum()
265 << "Rectangle texture cannot have a compressed format.");
266 return false;
267 }
268 break;
269
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
271 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
272 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
276 if (!isSubImage && width != height)
277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500278 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 return false;
280 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500284 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800285 return false;
286 }
287 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400288
He Yunchaoced53ae2016-11-29 15:00:51 +0800289 case GL_TEXTURE_3D:
290 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
291 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
292 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500294 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800295 return false;
296 }
297 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298
He Yunchaoced53ae2016-11-29 15:00:51 +0800299 case GL_TEXTURE_2D_ARRAY:
300 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
301 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
302 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500304 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800305 return false;
306 }
307 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400308
He Yunchaoced53ae2016-11-29 15:00:51 +0800309 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500310 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
He Yunchaoced53ae2016-11-29 15:00:51 +0800314 gl::Texture *texture =
315 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 if (!texture)
317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500318 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 }
321
Geoff Lang69cce582015-09-17 13:20:36 -0400322 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500324 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 }
327
328 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400329 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400330 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500331 if (isSubImage && actualInternalFormat == GL_NONE)
332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500333 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500334 return false;
335 }
336
Geoff Langc4e93662017-05-01 10:45:59 -0400337 const gl::InternalFormat &actualFormatInfo = isSubImage
338 ? *texture->getFormat(target, level).info
339 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 if (isCompressed)
341 {
tmartino7c102692015-10-02 16:43:40 -0400342 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(
345 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400346 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400347 }
348
Geoff Lang966c9402017-04-18 12:38:27 -0400349 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350 {
Geoff Lang966c9402017-04-18 12:38:27 -0400351 if (!ValidCompressedSubImageSize(
352 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
353 texture->getWidth(target, level), texture->getHeight(target, level)))
354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500355 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400356 return false;
357 }
358
359 if (format != actualInternalFormat)
360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500361 context->handleError(InvalidOperation()
362 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400363 return false;
364 }
Geoff Lang86f81162017-10-30 15:10:45 -0400365
366 if (actualInternalFormat == GL_ETC1_RGB8_OES)
367 {
368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
369 return false;
370 }
Geoff Lang966c9402017-04-18 12:38:27 -0400371 }
372 else
373 {
374 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500376 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400377 return false;
378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 }
380
Geoff Langeb66a6e2016-10-31 13:06:12 -0400381 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500383 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400384 return false;
385 }
386
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 if (target == GL_TEXTURE_3D)
388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500389 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392 }
393 else
394 {
Geoff Langca271392017-04-05 12:30:00 -0400395 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 {
Geoff Lang5d601382014-07-22 15:14:06 -0400397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 }
400
401 // Validate sub image parameters
402 if (isSubImage)
403 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500404 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500406 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500412 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 }
415
416 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
417 std::numeric_limits<GLsizei>::max() - yoffset < height ||
418 std::numeric_limits<GLsizei>::max() - zoffset < depth)
419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500420 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 }
423
Geoff Langa9be0dc2014-12-17 12:34:40 -0500424 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
425 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
426 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500428 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
431 }
432
Geoff Langdbcced82017-06-06 15:55:54 -0400433 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
434 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
435 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400436 {
437 return false;
438 }
439
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400440 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700441 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400442 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400443 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800444 // ...data is not evenly divisible into the number of bytes needed to store in memory a
445 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400446 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400447 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400448 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400449 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400450 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
451
Geoff Langff5b2d52016-09-07 11:32:23 -0400452 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500454 context->handleError(InvalidOperation()
455 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400456 return false;
457 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400458 }
459
Jamie Madill7a5f7382014-03-05 15:01:24 -0500460 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700461 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500463 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400464 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500465 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400466 }
467
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 return true;
469}
470
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500471bool ValidateES3TexImage2DParameters(Context *context,
472 GLenum target,
473 GLint level,
474 GLenum internalformat,
475 bool isCompressed,
476 bool isSubImage,
477 GLint xoffset,
478 GLint yoffset,
479 GLint zoffset,
480 GLsizei width,
481 GLsizei height,
482 GLsizei depth,
483 GLint border,
484 GLenum format,
485 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400486 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400487 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500488{
489 if (!ValidTexture2DDestinationTarget(context, target))
490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500491 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500492 return false;
493 }
494
495 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
496 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400497 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500498}
499
500bool ValidateES3TexImage3DParameters(Context *context,
501 GLenum target,
502 GLint level,
503 GLenum internalformat,
504 bool isCompressed,
505 bool isSubImage,
506 GLint xoffset,
507 GLint yoffset,
508 GLint zoffset,
509 GLsizei width,
510 GLsizei height,
511 GLsizei depth,
512 GLint border,
513 GLenum format,
514 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400515 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400516 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500517{
518 if (!ValidTexture3DDestinationTarget(context, target))
519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500520 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500521 return false;
522 }
523
524 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
525 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400526 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500527}
528
Geoff Lang5d601382014-07-22 15:14:06 -0400529struct EffectiveInternalFormatInfo
530{
Jamie Madill76648fe2016-10-05 17:01:41 -0400531 GLenum effectiveFormat;
532 GLenum destFormat;
533 GLuint minRedBits;
534 GLuint maxRedBits;
535 GLuint minGreenBits;
536 GLuint maxGreenBits;
537 GLuint minBlueBits;
538 GLuint maxBlueBits;
539 GLuint minAlphaBits;
540 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400541};
542
Jamie Madill76648fe2016-10-05 17:01:41 -0400543static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
544 GLenum targetFormat,
545 const EffectiveInternalFormatInfo *list,
546 size_t size,
547 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400548{
Jamie Madill76648fe2016-10-05 17:01:41 -0400549 for (size_t curFormat = 0; curFormat < size; ++curFormat)
550 {
551 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
552 if ((formatInfo.destFormat == targetFormat) &&
553 (formatInfo.minRedBits <= srcFormat.redBits &&
554 formatInfo.maxRedBits >= srcFormat.redBits) &&
555 (formatInfo.minGreenBits <= srcFormat.greenBits &&
556 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
557 (formatInfo.minBlueBits <= srcFormat.blueBits &&
558 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
559 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
560 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
561 {
562 *outEffectiveFormat = formatInfo.effectiveFormat;
563 return true;
564 }
565 }
Geoff Lang5d601382014-07-22 15:14:06 -0400566
Jamie Madill76648fe2016-10-05 17:01:41 -0400567 *outEffectiveFormat = GL_NONE;
568 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400569}
570
Jamie Madill76648fe2016-10-05 17:01:41 -0400571bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
572 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400573{
Jamie Madill76648fe2016-10-05 17:01:41 -0400574 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
575 // Effective internal format coresponding to destination internal format and linear source
576 // buffer component sizes.
577 // | Source channel min/max sizes |
578 // Effective Internal Format | N/A | R | G | B | A |
579 // clang-format off
580 constexpr EffectiveInternalFormatInfo list[] = {
581 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
582 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
583 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
584 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
585 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
586 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
587 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
588 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
589 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
590 };
591 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400592
Jamie Madill76648fe2016-10-05 17:01:41 -0400593 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
594}
Geoff Lang5d601382014-07-22 15:14:06 -0400595
Jamie Madill76648fe2016-10-05 17:01:41 -0400596bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
597 const InternalFormat &destFormat,
598 GLenum *outEffectiveFormat)
599{
600 constexpr GLuint umax = UINT_MAX;
601
602 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
603 // Effective internal format coresponding to destination internal format andlinear source buffer
604 // component sizes.
605 // | Source channel min/max sizes |
606 // Effective Internal Format | Dest Format | R | G | B | A |
607 // clang-format off
608 constexpr EffectiveInternalFormatInfo list[] = {
609 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
610 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
611 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
612 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
613 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
614 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
615 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
616 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
617 };
618 // clang-format on
619
620 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
621 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400622}
623
He Yunchaoced53ae2016-11-29 15:00:51 +0800624static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
625 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400626 GLenum *outEffectiveFormat)
627{
Geoff Langca271392017-04-05 12:30:00 -0400628 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400629 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400630 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400631 }
632 else
633 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400634 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400635 }
Geoff Lang5d601382014-07-22 15:14:06 -0400636}
637
Corentin Wallez76287682016-04-25 09:23:38 -0400638static bool EqualOrFirstZero(GLuint first, GLuint second)
639{
640 return first == 0 || first == second;
641}
642
Geoff Langca271392017-04-05 12:30:00 -0400643static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
644 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400645 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400646{
Jamie Madill21b786b2016-11-01 17:41:31 -0400647 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400648 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400649 return false;
650 }
Geoff Lang5d601382014-07-22 15:14:06 -0400651
Jamie Madill21b786b2016-11-01 17:41:31 -0400652 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
653 // must both be signed, unsigned, or fixed point and both source and destinations
654 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
655 // conversion between fixed and floating point.
656
657 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
658 (framebufferFormatInfo.colorEncoding == GL_SRGB))
659 {
660 return false;
661 }
662
663 if (((textureFormatInfo.componentType == GL_INT) !=
664 (framebufferFormatInfo.componentType == GL_INT)) ||
665 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
666 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
667 {
668 return false;
669 }
670
671 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
672 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
673 textureFormatInfo.componentType == GL_FLOAT) &&
674 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
675 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
676 framebufferFormatInfo.componentType == GL_FLOAT))
677 {
678 return false;
679 }
680
681 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
682 // The effective internal format of the source buffer is determined with the following rules
683 // applied in order:
684 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
685 // format then the effective internal format is the source buffer's sized internal format.
686 // * If the source buffer is a texture that was created with an unsized base internal format,
687 // then the effective internal format is the source image array's effective internal
688 // format, as specified by table 3.12, which is determined from the <format> and <type>
689 // that were used when the source image array was specified by TexImage*.
690 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
691 // where Destination Internal Format matches internalformat and where the [source channel
692 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
693 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
694 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800695 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400696 if (readBufferHandle != 0)
697 {
698 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
699 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400700 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400701 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400702 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400703 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400704 else
Geoff Lang5d601382014-07-22 15:14:06 -0400705 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400706 // Renderbuffers cannot be created with an unsized internal format, so this must be an
707 // unsized-format texture. We can use the same table we use when creating textures to
708 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400709 sourceEffectiveFormat =
710 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400711 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400712 }
713 else
714 {
715 // The effective internal format must be derived from the source framebuffer's channel
716 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
717 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400718 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 GLenum effectiveFormat;
720 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
721 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400722 {
Geoff Langca271392017-04-05 12:30:00 -0400723 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400724 }
725 else
726 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400727 return false;
728 }
729 }
730 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
731 {
732 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400733 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400734 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
735 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
736 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
737 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
738 {
Geoff Langca271392017-04-05 12:30:00 -0400739 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400740 }
741 else
742 {
743 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400744 }
745 }
746 else
747 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400748 UNREACHABLE();
749 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400750 }
Geoff Lang5d601382014-07-22 15:14:06 -0400751 }
752
Geoff Langca271392017-04-05 12:30:00 -0400753 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400754 {
755 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
756 // sized, component sizes of the source and destination formats must exactly match if the
757 // destination format exists.
758 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
759 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
760 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
761 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
762 {
763 return false;
764 }
765 }
766
767 return true; // A conversion function exists, and no rule in the specification has precluded
768 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400769}
770
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500771bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
772 GLenum target,
773 GLint level,
774 GLenum internalformat,
775 bool isSubImage,
776 GLint xoffset,
777 GLint yoffset,
778 GLint zoffset,
779 GLint x,
780 GLint y,
781 GLsizei width,
782 GLsizei height,
783 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400785 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400786 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400787 xoffset, yoffset, zoffset, x, y, width, height, border,
788 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400789 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400792 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793
Jamie Madill51f40ec2016-06-15 14:06:00 -0400794 const auto &state = context->getGLState();
795 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
796 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400797
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400798 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500800 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400802 }
803
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400804 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500806 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400807 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400808 }
809
Jamie Madill0c8abca2016-07-22 20:21:26 -0400810 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811
812 if (isSubImage)
813 {
Geoff Langca271392017-04-05 12:30:00 -0400814 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500815 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500817 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400821 else
822 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400823 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400824 const InternalFormat &framebufferFormat = *source->getFormat().info;
825 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400826 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400830 }
831 }
832
Geoff Lang784a8fd2013-09-24 12:33:16 -0400833 // If width or height is zero, it is a no-op. Return false without setting an error.
834 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835}
836
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500837bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
838 GLenum target,
839 GLint level,
840 GLenum internalformat,
841 bool isSubImage,
842 GLint xoffset,
843 GLint yoffset,
844 GLint zoffset,
845 GLint x,
846 GLint y,
847 GLsizei width,
848 GLsizei height,
849 GLint border)
850{
851 if (!ValidTexture2DDestinationTarget(context, target))
852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500853 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500854 return false;
855 }
856
857 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
858 xoffset, yoffset, zoffset, x, y, width, height,
859 border);
860}
861
862bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
863 GLenum target,
864 GLint level,
865 GLenum internalformat,
866 bool isSubImage,
867 GLint xoffset,
868 GLint yoffset,
869 GLint zoffset,
870 GLint x,
871 GLint y,
872 GLsizei width,
873 GLsizei height,
874 GLint border)
875{
876 if (!ValidTexture3DDestinationTarget(context, target))
877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500879 return false;
880 }
881
882 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
883 xoffset, yoffset, zoffset, x, y, width, height,
884 border);
885}
886
887bool ValidateES3TexStorageParametersBase(Context *context,
888 GLenum target,
889 GLsizei levels,
890 GLenum internalformat,
891 GLsizei width,
892 GLsizei height,
893 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894{
895 if (width < 1 || height < 1 || depth < 1 || levels < 1)
896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500897 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400898 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400899 }
900
Geoff Langb92c1332015-09-04 12:54:55 -0400901 GLsizei maxDim = std::max(width, height);
902 if (target != GL_TEXTURE_2D_ARRAY)
903 {
904 maxDim = std::max(maxDim, depth);
905 }
906
907 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500909 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400910 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400911 }
912
Geoff Langaae65a42014-05-26 12:43:44 -0400913 const gl::Caps &caps = context->getCaps();
914
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 switch (target)
916 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800917 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 {
Geoff Langaae65a42014-05-26 12:43:44 -0400919 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
920 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500922 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925 }
926 break;
927
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400928 case GL_TEXTURE_RECTANGLE_ANGLE:
929 {
930 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
931 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
932 {
933 context->handleError(InvalidValue());
934 return false;
935 }
936 }
937 break;
938
He Yunchaoced53ae2016-11-29 15:00:51 +0800939 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400941 if (width != height)
942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500943 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400944 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 }
946
Geoff Langaae65a42014-05-26 12:43:44 -0400947 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500949 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952 }
953 break;
954
He Yunchaoced53ae2016-11-29 15:00:51 +0800955 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 {
Geoff Langaae65a42014-05-26 12:43:44 -0400957 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
958 static_cast<GLuint>(height) > caps.max3DTextureSize ||
959 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500961 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 }
964 }
965 break;
966
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 {
Geoff Langaae65a42014-05-26 12:43:44 -0400969 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
970 static_cast<GLuint>(height) > caps.max2DTextureSize ||
971 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500973 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 }
976 }
977 break;
978
He Yunchaoced53ae2016-11-29 15:00:51 +0800979 default:
980 UNREACHABLE();
981 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 }
983
Geoff Lang691e58c2014-12-19 17:03:25 -0500984 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985 if (!texture || texture->id() == 0)
986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500987 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 }
990
Geoff Lang69cce582015-09-17 13:20:36 -0400991 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500993 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400995 }
996
Geoff Langca271392017-04-05 12:30:00 -0400997 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400998 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Geoff Langca271392017-04-05 12:30:00 -04001004 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001010 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1011 {
1012 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1013 return false;
1014 }
1015
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 return true;
1017}
1018
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001019bool ValidateES3TexStorage2DParameters(Context *context,
1020 GLenum target,
1021 GLsizei levels,
1022 GLenum internalformat,
1023 GLsizei width,
1024 GLsizei height,
1025 GLsizei depth)
1026{
1027 if (!ValidTexture2DTarget(context, target))
1028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001029 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001030 return false;
1031 }
1032
1033 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1034 height, depth);
1035}
1036
1037bool ValidateES3TexStorage3DParameters(Context *context,
1038 GLenum target,
1039 GLsizei levels,
1040 GLenum internalformat,
1041 GLsizei width,
1042 GLsizei height,
1043 GLsizei depth)
1044{
1045 if (!ValidTexture3DTarget(context, target))
1046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001047 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001048 return false;
1049 }
1050
1051 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1052 height, depth);
1053}
1054
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001055bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1056{
Martin Radev1be913c2016-07-11 17:59:16 +03001057 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001058 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001060 return false;
1061 }
1062
1063 return ValidateBeginQueryBase(context, target, id);
1064}
1065
1066bool ValidateEndQuery(gl::Context *context, GLenum target)
1067{
Martin Radev1be913c2016-07-11 17:59:16 +03001068 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001069 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001071 return false;
1072 }
1073
1074 return ValidateEndQueryBase(context, target);
1075}
1076
1077bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1078{
Martin Radev1be913c2016-07-11 17:59:16 +03001079 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001080 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001082 return false;
1083 }
1084
Geoff Lang2186c382016-10-14 10:54:54 -04001085 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086}
1087
1088bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1089{
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001091 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001093 return false;
1094 }
1095
Geoff Lang2186c382016-10-14 10:54:54 -04001096 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097}
1098
He Yunchaoced53ae2016-11-29 15:00:51 +08001099bool ValidateFramebufferTextureLayer(Context *context,
1100 GLenum target,
1101 GLenum attachment,
1102 GLuint texture,
1103 GLint level,
1104 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001105{
Martin Radev1be913c2016-07-11 17:59:16 +03001106 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001107 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001110 }
1111
Jamie Madill55ec3b12014-07-03 10:38:57 -04001112 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1113 {
1114 return false;
1115 }
1116
1117 const gl::Caps &caps = context->getCaps();
1118 if (texture != 0)
1119 {
Geoff Lang23e02842017-10-17 13:24:09 -04001120 if (layer < 0)
1121 {
1122 context->handleError(InvalidValue());
1123 return false;
1124 }
1125
Jamie Madill55ec3b12014-07-03 10:38:57 -04001126 gl::Texture *tex = context->getTexture(texture);
1127 ASSERT(tex);
1128
1129 switch (tex->getTarget())
1130 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001131 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001132 {
1133 if (level > gl::log2(caps.max2DTextureSize))
1134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001135 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001137 }
1138
1139 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001143 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001144 }
1145 break;
1146
He Yunchaoced53ae2016-11-29 15:00:51 +08001147 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001148 {
1149 if (level > gl::log2(caps.max3DTextureSize))
1150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001151 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001153 }
1154
1155 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001157 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001158 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001159 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001160 }
1161 break;
1162
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001166 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001167
Jamie Madilla3944d42016-07-22 22:13:26 -04001168 const auto &format = tex->getFormat(tex->getTarget(), level);
1169 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001172 return false;
1173 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001174 }
1175
1176 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001177}
1178
He Yunchaoced53ae2016-11-29 15:00:51 +08001179bool ValidateInvalidateFramebuffer(Context *context,
1180 GLenum target,
1181 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001182 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183{
Martin Radev1be913c2016-07-11 17:59:16 +03001184 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001185 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001187 return false;
1188 }
1189
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001190 bool defaultFramebuffer = false;
1191
1192 switch (target)
1193 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 case GL_DRAW_FRAMEBUFFER:
1195 case GL_FRAMEBUFFER:
1196 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1197 break;
1198 case GL_READ_FRAMEBUFFER:
1199 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1200 break;
1201 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001204 }
1205
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1207 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001208}
1209
Jamie Madill3ef140a2017-08-26 23:11:21 -04001210bool ValidateInvalidateSubFramebuffer(Context *context,
1211 GLenum target,
1212 GLsizei numAttachments,
1213 const GLenum *attachments,
1214 GLint x,
1215 GLint y,
1216 GLsizei width,
1217 GLsizei height)
1218{
1219 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1220}
1221
Jamie Madillc29968b2016-01-20 11:17:23 -05001222bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001223{
Martin Radev1be913c2016-07-11 17:59:16 +03001224 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001225 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001228 }
1229
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001230 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001232 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001233 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001234 }
1235
1236 return true;
1237}
1238
Olli Etuaho71dfb362016-03-10 14:04:27 +02001239bool ValidateDrawRangeElements(Context *context,
1240 GLenum mode,
1241 GLuint start,
1242 GLuint end,
1243 GLsizei count,
1244 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001245 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001246{
Martin Radev1be913c2016-07-11 17:59:16 +03001247 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001248 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001250 return false;
1251 }
1252
1253 if (end < start)
1254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001256 return false;
1257 }
1258
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001259 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001260 {
1261 return false;
1262 }
1263
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001264 // Use the parameter buffer to retrieve and cache the index range.
1265 const auto &params = context->getParams<HasIndexRange>();
1266 const auto &indexRangeOpt = params.getIndexRange();
1267 if (!indexRangeOpt.valid())
1268 {
1269 // Unexpected error.
1270 return false;
1271 }
1272
1273 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001274 {
1275 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001276 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001277 return false;
1278 }
1279 return true;
1280}
1281
He Yunchaoced53ae2016-11-29 15:00:51 +08001282bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001283{
Martin Radev1be913c2016-07-11 17:59:16 +03001284 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001285 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001287 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001288 }
1289
Jamie Madill78f41802014-08-25 15:47:55 -04001290 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001291}
1292
Jamie Madillb885e572015-02-03 16:16:04 -05001293bool ValidateReadBuffer(Context *context, GLenum src)
1294{
Martin Radev1be913c2016-07-11 17:59:16 +03001295 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001296 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001298 return false;
1299 }
1300
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001301 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001302
1303 if (readFBO == nullptr)
1304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001306 return false;
1307 }
1308
1309 if (src == GL_NONE)
1310 {
1311 return true;
1312 }
1313
Olli Etuaho84c9f592016-03-09 14:37:25 +02001314 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001315 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001316 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001317 return false;
1318 }
1319
1320 if (readFBO->id() == 0)
1321 {
1322 if (src != GL_BACK)
1323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(
1325 InvalidOperation()
1326 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001327 return false;
1328 }
1329 }
1330 else
1331 {
1332 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1333
1334 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001337 return false;
1338 }
1339 }
1340
1341 return true;
1342}
1343
Jamie Madill86af3d22015-07-21 15:14:07 -04001344bool ValidateCompressedTexImage3D(Context *context,
1345 GLenum target,
1346 GLint level,
1347 GLenum internalformat,
1348 GLsizei width,
1349 GLsizei height,
1350 GLsizei depth,
1351 GLint border,
1352 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001353 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001354{
Martin Radev1be913c2016-07-11 17:59:16 +03001355 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001356 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001357 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001358 return false;
1359 }
1360
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001361 if (!ValidTextureTarget(context, target))
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001364 return false;
1365 }
1366
Jamie Madille2e406c2016-06-02 13:04:10 -04001367 // Validate image size
1368 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001371 return false;
1372 }
1373
Geoff Langca271392017-04-05 12:30:00 -04001374 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001375 if (!formatInfo.compressed)
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001378 return false;
1379 }
1380
Jamie Madill513558d2016-06-02 13:04:11 -04001381 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001382 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001383 if (blockSizeOrErr.isError())
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001386 return false;
1387 }
1388 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001391 return false;
1392 }
1393
1394 // 3D texture target validation
1395 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001398 return false;
1399 }
1400
1401 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001402 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001403 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1404 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001405 {
1406 return false;
1407 }
1408
1409 return true;
1410}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001411
Corentin Wallezb2931602017-04-11 15:58:57 -04001412bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1413 GLenum target,
1414 GLint level,
1415 GLenum internalformat,
1416 GLsizei width,
1417 GLsizei height,
1418 GLsizei depth,
1419 GLint border,
1420 GLsizei imageSize,
1421 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001422 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001423{
1424 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1425 {
1426 return false;
1427 }
1428
1429 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1430 depth, border, imageSize, data);
1431}
1432
Austin Kinrossbc781f32015-10-26 09:27:38 -07001433bool ValidateBindVertexArray(Context *context, GLuint array)
1434{
Martin Radev1be913c2016-07-11 17:59:16 +03001435 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001436 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001437 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001438 return false;
1439 }
1440
1441 return ValidateBindVertexArrayBase(context, array);
1442}
1443
Jamie Madilld7576732017-08-26 18:49:50 -04001444bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001445{
Martin Radev1be913c2016-07-11 17:59:16 +03001446 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001447 {
Jamie Madilld7576732017-08-26 18:49:50 -04001448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001449 return false;
1450 }
1451
1452 return true;
1453}
Geoff Langc5629752015-12-07 16:29:04 -05001454
Jiajia Qin6eafb042016-12-27 17:04:07 +08001455static bool ValidateBindBufferCommon(Context *context,
1456 GLenum target,
1457 GLuint index,
1458 GLuint buffer,
1459 GLintptr offset,
1460 GLsizeiptr size)
1461{
1462 if (context->getClientMajorVersion() < 3)
1463 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001465 return false;
1466 }
1467
1468 if (buffer != 0 && offset < 0)
1469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001470 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001471 return false;
1472 }
1473
1474 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1475 !context->isBufferGenerated(buffer))
1476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001478 return false;
1479 }
1480
1481 const Caps &caps = context->getCaps();
1482 switch (target)
1483 {
1484 case GL_TRANSFORM_FEEDBACK_BUFFER:
1485 {
1486 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001488 context->handleError(InvalidValue() << "index is greater than or equal to the "
1489 "number of TRANSFORM_FEEDBACK_BUFFER "
1490 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001491 return false;
1492 }
1493 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001495 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001496 return false;
1497 }
1498
1499 TransformFeedback *curTransformFeedback =
1500 context->getGLState().getCurrentTransformFeedback();
1501 if (curTransformFeedback && curTransformFeedback->isActive())
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidOperation()
1504 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1505 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001506 return false;
1507 }
1508 break;
1509 }
1510 case GL_UNIFORM_BUFFER:
1511 {
1512 if (index >= caps.maxUniformBufferBindings)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidValue() << "index is greater than or equal to the "
1515 "number of UNIFORM_BUFFER indexed "
1516 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001517 return false;
1518 }
1519
1520 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1521 {
1522 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 InvalidValue()
1524 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001525 return false;
1526 }
1527 break;
1528 }
1529 case GL_ATOMIC_COUNTER_BUFFER:
1530 {
1531 if (context->getClientVersion() < ES_3_1)
1532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(InvalidEnum()
1534 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001535 return false;
1536 }
1537 if (index >= caps.maxAtomicCounterBufferBindings)
1538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001539 context->handleError(InvalidValue() << "index is greater than or equal to the "
1540 "number of ATOMIC_COUNTER_BUFFER "
1541 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001542 return false;
1543 }
1544 if (buffer != 0 && (offset % 4) != 0)
1545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001546 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001547 return false;
1548 }
1549 break;
1550 }
1551 case GL_SHADER_STORAGE_BUFFER:
1552 {
1553 if (context->getClientVersion() < ES_3_1)
1554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001555 context->handleError(InvalidEnum()
1556 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001557 return false;
1558 }
1559 if (index >= caps.maxShaderStorageBufferBindings)
1560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidValue() << "index is greater than or equal to the "
1562 "number of SHADER_STORAGE_BUFFER "
1563 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001564 return false;
1565 }
1566 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001568 context->handleError(InvalidValue() << "offset must be multiple of value of "
1569 "SHADER_STORAGE_BUFFER_OFFSET_"
1570 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001571 return false;
1572 }
1573 break;
1574 }
1575 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001577 return false;
1578 }
1579
1580 return true;
1581}
1582
1583bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1584{
1585 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1586}
1587
1588bool ValidateBindBufferRange(Context *context,
1589 GLenum target,
1590 GLuint index,
1591 GLuint buffer,
1592 GLintptr offset,
1593 GLsizeiptr size)
1594{
1595 if (buffer != 0 && size <= 0)
1596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidValue()
1598 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001599 return false;
1600 }
1601 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1602}
1603
Geoff Langc5629752015-12-07 16:29:04 -05001604bool ValidateProgramBinary(Context *context,
1605 GLuint program,
1606 GLenum binaryFormat,
1607 const void *binary,
1608 GLint length)
1609{
Martin Radev1be913c2016-07-11 17:59:16 +03001610 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001611 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001612 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001613 return false;
1614 }
1615
1616 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1617}
1618
1619bool ValidateGetProgramBinary(Context *context,
1620 GLuint program,
1621 GLsizei bufSize,
1622 GLsizei *length,
1623 GLenum *binaryFormat,
1624 void *binary)
1625{
Martin Radev1be913c2016-07-11 17:59:16 +03001626 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001627 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001629 return false;
1630 }
1631
1632 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1633}
1634
Olli Etuahof0fee072016-03-30 15:11:58 +03001635bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001636{
Martin Radev1be913c2016-07-11 17:59:16 +03001637 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001640 return false;
1641 }
1642
1643 if (GetValidProgram(context, program) == nullptr)
1644 {
1645 return false;
1646 }
1647
1648 switch (pname)
1649 {
1650 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001651 if (value != GL_FALSE && value != GL_TRUE)
1652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidValue()
1654 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001655 return false;
1656 }
Geoff Langc5629752015-12-07 16:29:04 -05001657 break;
1658
Yunchao He61afff12017-03-14 15:34:03 +08001659 case GL_PROGRAM_SEPARABLE:
1660 if (context->getClientVersion() < ES_3_1)
1661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001662 context->handleError(InvalidEnum()
1663 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001664 return false;
1665 }
1666
1667 if (value != GL_FALSE && value != GL_TRUE)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidValue()
1670 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001671 return false;
1672 }
1673 break;
1674
Geoff Langc5629752015-12-07 16:29:04 -05001675 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidEnum()
1677 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001678 return false;
1679 }
1680
1681 return true;
1682}
Jamie Madillc29968b2016-01-20 11:17:23 -05001683
1684bool ValidateBlitFramebuffer(Context *context,
1685 GLint srcX0,
1686 GLint srcY0,
1687 GLint srcX1,
1688 GLint srcY1,
1689 GLint dstX0,
1690 GLint dstY0,
1691 GLint dstX1,
1692 GLint dstY1,
1693 GLbitfield mask,
1694 GLenum filter)
1695{
Martin Radev1be913c2016-07-11 17:59:16 +03001696 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001697 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001699 return false;
1700 }
1701
1702 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1703 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001704}
Jamie Madillc29968b2016-01-20 11:17:23 -05001705
1706bool ValidateClearBufferiv(ValidationContext *context,
1707 GLenum buffer,
1708 GLint drawbuffer,
1709 const GLint *value)
1710{
1711 switch (buffer)
1712 {
1713 case GL_COLOR:
1714 if (drawbuffer < 0 ||
1715 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001718 return false;
1719 }
Geoff Lang76e65652017-03-27 14:58:02 -04001720 if (context->getExtensions().webglCompatibility)
1721 {
1722 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001723 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001724 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1725 {
1726 return false;
1727 }
1728 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001729 break;
1730
1731 case GL_STENCIL:
1732 if (drawbuffer != 0)
1733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001734 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001735 return false;
1736 }
1737 break;
1738
1739 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001741 return false;
1742 }
1743
1744 return ValidateClearBuffer(context);
1745}
1746
1747bool ValidateClearBufferuiv(ValidationContext *context,
1748 GLenum buffer,
1749 GLint drawbuffer,
1750 const GLuint *value)
1751{
1752 switch (buffer)
1753 {
1754 case GL_COLOR:
1755 if (drawbuffer < 0 ||
1756 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001759 return false;
1760 }
Geoff Lang76e65652017-03-27 14:58:02 -04001761 if (context->getExtensions().webglCompatibility)
1762 {
1763 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001764 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001765 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1766 {
1767 return false;
1768 }
1769 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001770 break;
1771
1772 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001773 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001774 return false;
1775 }
1776
1777 return ValidateClearBuffer(context);
1778}
1779
1780bool ValidateClearBufferfv(ValidationContext *context,
1781 GLenum buffer,
1782 GLint drawbuffer,
1783 const GLfloat *value)
1784{
1785 switch (buffer)
1786 {
1787 case GL_COLOR:
1788 if (drawbuffer < 0 ||
1789 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001791 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 return false;
1793 }
Geoff Lang76e65652017-03-27 14:58:02 -04001794 if (context->getExtensions().webglCompatibility)
1795 {
1796 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1797 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001798 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001799 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1800 {
1801 return false;
1802 }
1803 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 break;
1805
1806 case GL_DEPTH:
1807 if (drawbuffer != 0)
1808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001809 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 return false;
1811 }
1812 break;
1813
1814 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001815 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 return false;
1817 }
1818
1819 return ValidateClearBuffer(context);
1820}
1821
1822bool ValidateClearBufferfi(ValidationContext *context,
1823 GLenum buffer,
1824 GLint drawbuffer,
1825 GLfloat depth,
1826 GLint stencil)
1827{
1828 switch (buffer)
1829 {
1830 case GL_DEPTH_STENCIL:
1831 if (drawbuffer != 0)
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836 break;
1837
1838 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 return false;
1841 }
1842
1843 return ValidateClearBuffer(context);
1844}
1845
1846bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1847{
Martin Radev1be913c2016-07-11 17:59:16 +03001848 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 return false;
1852 }
1853
1854 return ValidateDrawBuffersBase(context, n, bufs);
1855}
1856
1857bool ValidateCopyTexSubImage3D(Context *context,
1858 GLenum target,
1859 GLint level,
1860 GLint xoffset,
1861 GLint yoffset,
1862 GLint zoffset,
1863 GLint x,
1864 GLint y,
1865 GLsizei width,
1866 GLsizei height)
1867{
Martin Radev1be913c2016-07-11 17:59:16 +03001868 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001871 return false;
1872 }
1873
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001874 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1875 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001876}
1877
Jamie Madill73a84962016-02-12 09:27:23 -05001878bool ValidateTexImage3D(Context *context,
1879 GLenum target,
1880 GLint level,
1881 GLint internalformat,
1882 GLsizei width,
1883 GLsizei height,
1884 GLsizei depth,
1885 GLint border,
1886 GLenum format,
1887 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001888 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001889{
Martin Radev1be913c2016-07-11 17:59:16 +03001890 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001891 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001893 return false;
1894 }
1895
1896 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001897 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001898 pixels);
1899}
1900
Geoff Langc52f6f12016-10-14 10:18:00 -04001901bool ValidateTexImage3DRobustANGLE(Context *context,
1902 GLenum target,
1903 GLint level,
1904 GLint internalformat,
1905 GLsizei width,
1906 GLsizei height,
1907 GLsizei depth,
1908 GLint border,
1909 GLenum format,
1910 GLenum type,
1911 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001912 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001913{
1914 if (context->getClientMajorVersion() < 3)
1915 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001917 return false;
1918 }
1919
1920 if (!ValidateRobustEntryPoint(context, bufSize))
1921 {
1922 return false;
1923 }
1924
1925 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1926 0, 0, width, height, depth, border, format, type,
1927 bufSize, pixels);
1928}
1929
Jamie Madill73a84962016-02-12 09:27:23 -05001930bool ValidateTexSubImage3D(Context *context,
1931 GLenum target,
1932 GLint level,
1933 GLint xoffset,
1934 GLint yoffset,
1935 GLint zoffset,
1936 GLsizei width,
1937 GLsizei height,
1938 GLsizei depth,
1939 GLenum format,
1940 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001941 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001942{
Martin Radev1be913c2016-07-11 17:59:16 +03001943 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001944 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001945 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001946 return false;
1947 }
1948
1949 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1950 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001951 -1, pixels);
1952}
1953
1954bool ValidateTexSubImage3DRobustANGLE(Context *context,
1955 GLenum target,
1956 GLint level,
1957 GLint xoffset,
1958 GLint yoffset,
1959 GLint zoffset,
1960 GLsizei width,
1961 GLsizei height,
1962 GLsizei depth,
1963 GLenum format,
1964 GLenum type,
1965 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001966 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001967{
1968 if (context->getClientMajorVersion() < 3)
1969 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001971 return false;
1972 }
1973
1974 if (!ValidateRobustEntryPoint(context, bufSize))
1975 {
1976 return false;
1977 }
1978
1979 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1980 yoffset, zoffset, width, height, depth, 0, format, type,
1981 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001982}
1983
1984bool ValidateCompressedTexSubImage3D(Context *context,
1985 GLenum target,
1986 GLint level,
1987 GLint xoffset,
1988 GLint yoffset,
1989 GLint zoffset,
1990 GLsizei width,
1991 GLsizei height,
1992 GLsizei depth,
1993 GLenum format,
1994 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001995 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001996{
Martin Radev1be913c2016-07-11 17:59:16 +03001997 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001998 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001999 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002000 return false;
2001 }
2002
Geoff Langca271392017-04-05 12:30:00 -04002003 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002004 if (!formatInfo.compressed)
2005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002006 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002007 return false;
2008 }
2009
Jamie Madill513558d2016-06-02 13:04:11 -04002010 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002011 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002012 if (blockSizeOrErr.isError())
2013 {
2014 context->handleError(blockSizeOrErr.getError());
2015 return false;
2016 }
2017 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002019 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002020 return false;
2021 }
2022
2023 if (!data)
2024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002025 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002026 return false;
2027 }
2028
2029 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04002030 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002031}
Corentin Wallezb2931602017-04-11 15:58:57 -04002032bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2033 GLenum target,
2034 GLint level,
2035 GLint xoffset,
2036 GLint yoffset,
2037 GLint zoffset,
2038 GLsizei width,
2039 GLsizei height,
2040 GLsizei depth,
2041 GLenum format,
2042 GLsizei imageSize,
2043 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002044 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002045{
2046 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2047 {
2048 return false;
2049 }
2050
2051 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2052 height, depth, format, imageSize, data);
2053}
Jamie Madill73a84962016-02-12 09:27:23 -05002054
Olli Etuaho41997e72016-03-10 13:38:39 +02002055bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2056{
2057 return ValidateGenOrDeleteES3(context, n);
2058}
2059
2060bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2061{
2062 return ValidateGenOrDeleteES3(context, n);
2063}
2064
2065bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2066{
2067 return ValidateGenOrDeleteCountES3(context, count);
2068}
2069
2070bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2071{
2072 return ValidateGenOrDeleteCountES3(context, count);
2073}
2074
2075bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2076{
2077 return ValidateGenOrDeleteES3(context, n);
2078}
2079
2080bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2081{
2082 if (!ValidateGenOrDeleteES3(context, n))
2083 {
2084 return false;
2085 }
2086 for (GLint i = 0; i < n; ++i)
2087 {
2088 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2089 if (transformFeedback != nullptr && transformFeedback->isActive())
2090 {
2091 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002092 context->handleError(InvalidOperation()
2093 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002094 return false;
2095 }
2096 }
2097 return true;
2098}
2099
2100bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2101{
2102 return ValidateGenOrDeleteES3(context, n);
2103}
2104
2105bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2106{
2107 return ValidateGenOrDeleteES3(context, n);
2108}
2109
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002110bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2111{
Martin Radev1be913c2016-07-11 17:59:16 +03002112 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002113 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002115 return false;
2116 }
2117 switch (primitiveMode)
2118 {
2119 case GL_TRIANGLES:
2120 case GL_LINES:
2121 case GL_POINTS:
2122 break;
2123
2124 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002125 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002126 return false;
2127 }
2128
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002129 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002130 ASSERT(transformFeedback != nullptr);
2131
2132 if (transformFeedback->isActive())
2133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002134 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002135 return false;
2136 }
Geoff Lang79f71042017-08-14 16:43:43 -04002137
2138 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2139 {
2140 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2141 if (buffer.get() && buffer->isMapped())
2142 {
2143 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2144 return false;
2145 }
2146 }
2147
Olli Etuaho02032bd2017-10-13 18:10:17 +03002148 auto program = context->getGLState().getProgram();
2149
2150 if (!program)
2151 {
2152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2153 return false;
2154 }
2155
2156 if (program->getTransformFeedbackVaryingCount() == 0)
2157 {
2158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2159 return false;
2160 }
2161
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002162 return true;
2163}
2164
Jamie Madill876429b2017-04-20 15:46:24 -04002165bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002166{
Geoff Lang496c02d2016-10-20 11:38:11 -07002167 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2168}
2169
2170bool ValidateGetBufferPointervRobustANGLE(Context *context,
2171 GLenum target,
2172 GLenum pname,
2173 GLsizei bufSize,
2174 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002175 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002176{
2177 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002178 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002179 return false;
2180 }
2181
Geoff Lang496c02d2016-10-20 11:38:11 -07002182 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2183 {
2184 return false;
2185 }
2186
2187 if (!ValidateRobustBufferSize(context, bufSize, *length))
2188 {
2189 return false;
2190 }
2191
2192 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002193}
2194
2195bool ValidateUnmapBuffer(Context *context, GLenum target)
2196{
Martin Radev1be913c2016-07-11 17:59:16 +03002197 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002198 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002200 return false;
2201 }
2202
2203 return ValidateUnmapBufferBase(context, target);
2204}
2205
2206bool ValidateMapBufferRange(Context *context,
2207 GLenum target,
2208 GLintptr offset,
2209 GLsizeiptr length,
2210 GLbitfield access)
2211{
Martin Radev1be913c2016-07-11 17:59:16 +03002212 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002213 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002215 return false;
2216 }
2217
2218 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2219}
2220
2221bool ValidateFlushMappedBufferRange(Context *context,
2222 GLenum target,
2223 GLintptr offset,
2224 GLsizeiptr length)
2225{
Martin Radev1be913c2016-07-11 17:59:16 +03002226 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002227 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002229 return false;
2230 }
2231
2232 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2233}
2234
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002235bool ValidateIndexedStateQuery(ValidationContext *context,
2236 GLenum pname,
2237 GLuint index,
2238 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002239{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002240 if (length)
2241 {
2242 *length = 0;
2243 }
2244
Martin Radev66fb8202016-07-28 11:45:20 +03002245 GLenum nativeType;
2246 unsigned int numParams;
2247 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002249 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002250 return false;
2251 }
2252
2253 const Caps &caps = context->getCaps();
2254 switch (pname)
2255 {
2256 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2257 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2258 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2259 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002261 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002262 return false;
2263 }
2264 break;
2265
2266 case GL_UNIFORM_BUFFER_START:
2267 case GL_UNIFORM_BUFFER_SIZE:
2268 case GL_UNIFORM_BUFFER_BINDING:
2269 if (index >= caps.maxUniformBufferBindings)
2270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002272 return false;
2273 }
2274 break;
Shao80957d92017-02-20 21:25:59 +08002275
Martin Radev66fb8202016-07-28 11:45:20 +03002276 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2277 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2278 if (index >= 3u)
2279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002280 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002281 return false;
2282 }
2283 break;
Shao80957d92017-02-20 21:25:59 +08002284
Jiajia Qin6eafb042016-12-27 17:04:07 +08002285 case GL_ATOMIC_COUNTER_BUFFER_START:
2286 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2287 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2288 if (context->getClientVersion() < ES_3_1)
2289 {
2290 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002291 InvalidEnum()
2292 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002293 return false;
2294 }
2295 if (index >= caps.maxAtomicCounterBufferBindings)
2296 {
2297 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002298 InvalidValue()
2299 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002300 return false;
2301 }
2302 break;
Shao80957d92017-02-20 21:25:59 +08002303
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002304 case GL_SHADER_STORAGE_BUFFER_START:
2305 case GL_SHADER_STORAGE_BUFFER_SIZE:
2306 case GL_SHADER_STORAGE_BUFFER_BINDING:
2307 if (context->getClientVersion() < ES_3_1)
2308 {
2309 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002310 InvalidEnum()
2311 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002312 return false;
2313 }
2314 if (index >= caps.maxShaderStorageBufferBindings)
2315 {
2316 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002317 InvalidValue()
2318 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002319 return false;
2320 }
2321 break;
2322
Shao80957d92017-02-20 21:25:59 +08002323 case GL_VERTEX_BINDING_BUFFER:
2324 case GL_VERTEX_BINDING_DIVISOR:
2325 case GL_VERTEX_BINDING_OFFSET:
2326 case GL_VERTEX_BINDING_STRIDE:
2327 if (context->getClientVersion() < ES_3_1)
2328 {
2329 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002330 InvalidEnum()
2331 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002332 return false;
2333 }
2334 if (index >= caps.maxVertexAttribBindings)
2335 {
2336 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002337 InvalidValue()
2338 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002339 return false;
2340 }
2341 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002342 case GL_SAMPLE_MASK_VALUE:
2343 if (context->getClientVersion() < ES_3_1)
2344 {
2345 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2346 return false;
2347 }
2348 if (index >= caps.maxSampleMaskWords)
2349 {
2350 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2351 return false;
2352 }
2353 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002354 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002355 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002356 return false;
2357 }
2358
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002359 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002360 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002361 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002362 }
2363
2364 return true;
2365}
2366
2367bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2368{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002369 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002370 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002372 return false;
2373 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002374 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002375}
2376
Geoff Langcf255ea2016-10-20 11:39:09 -07002377bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2378 GLenum target,
2379 GLuint index,
2380 GLsizei bufSize,
2381 GLsizei *length,
2382 GLint *data)
2383{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002384 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002385 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002387 return false;
2388 }
2389
2390 if (!ValidateRobustEntryPoint(context, bufSize))
2391 {
2392 return false;
2393 }
2394
2395 if (!ValidateIndexedStateQuery(context, target, index, length))
2396 {
2397 return false;
2398 }
2399
2400 if (!ValidateRobustBufferSize(context, bufSize, *length))
2401 {
2402 return false;
2403 }
2404
2405 return true;
2406}
2407
Martin Radev66fb8202016-07-28 11:45:20 +03002408bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2409{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002410 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002412 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002413 return false;
2414 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002415 return ValidateIndexedStateQuery(context, target, index, nullptr);
2416}
2417
2418bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2419 GLenum target,
2420 GLuint index,
2421 GLsizei bufSize,
2422 GLsizei *length,
2423 GLint64 *data)
2424{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002425 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002426 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002427 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002428 return false;
2429 }
2430
2431 if (!ValidateRobustEntryPoint(context, bufSize))
2432 {
2433 return false;
2434 }
2435
2436 if (!ValidateIndexedStateQuery(context, target, index, length))
2437 {
2438 return false;
2439 }
2440
2441 if (!ValidateRobustBufferSize(context, bufSize, *length))
2442 {
2443 return false;
2444 }
2445
2446 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002447}
2448
Jamie Madillb0817d12016-11-01 15:48:31 -04002449bool ValidateCopyBufferSubData(ValidationContext *context,
2450 GLenum readTarget,
2451 GLenum writeTarget,
2452 GLintptr readOffset,
2453 GLintptr writeOffset,
2454 GLsizeiptr size)
2455{
2456 if (context->getClientMajorVersion() < 3)
2457 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002459 return false;
2460 }
2461
2462 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002464 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002465 return false;
2466 }
2467
2468 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2469 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2470
2471 if (!readBuffer || !writeBuffer)
2472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002473 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002474 return false;
2475 }
2476
2477 // Verify that readBuffer and writeBuffer are not currently mapped
2478 if (readBuffer->isMapped() || writeBuffer->isMapped())
2479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002480 context->handleError(InvalidOperation()
2481 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002482 return false;
2483 }
2484
Jamie Madilld2f0c742016-11-02 10:34:41 -04002485 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2486 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2487 CheckedNumeric<GLintptr> checkedSize(size);
2488
2489 auto checkedReadSum = checkedReadOffset + checkedSize;
2490 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2491
2492 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2493 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2494 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002496 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002497 return false;
2498 }
2499
Jamie Madilld2f0c742016-11-02 10:34:41 -04002500 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002502 context->handleError(InvalidValue()
2503 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002504 return false;
2505 }
2506
Jamie Madilld2f0c742016-11-02 10:34:41 -04002507 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2508 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002510 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002511 return false;
2512 }
2513
2514 if (readBuffer == writeBuffer)
2515 {
2516 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2517 if (!checkedOffsetDiff.IsValid())
2518 {
2519 // This shold not be possible.
2520 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002521 context->handleError(InvalidValue()
2522 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002523 return false;
2524 }
2525
2526 if (checkedOffsetDiff.ValueOrDie() < size)
2527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002528 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002529 return false;
2530 }
2531 }
2532
Jamie Madillb0817d12016-11-01 15:48:31 -04002533 return true;
2534}
2535
Geoff Langc339c4e2016-11-29 10:37:36 -05002536bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2537{
2538 if (context->getClientMajorVersion() < 3)
2539 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002541 return false;
2542 }
2543
2544 switch (name)
2545 {
2546 case GL_EXTENSIONS:
2547 if (index >= context->getExtensionStringCount())
2548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002549 context->handleError(InvalidValue()
2550 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002551 return false;
2552 }
2553 break;
2554
2555 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2556 if (!context->getExtensions().requestExtension)
2557 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002558 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002559 return false;
2560 }
2561 if (index >= context->getRequestableExtensionStringCount())
2562 {
2563 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002564 InvalidValue()
2565 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002566 return false;
2567 }
2568 break;
2569
2570 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002571 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002572 return false;
2573 }
2574
2575 return true;
2576}
2577
Jamie Madille8fb6402017-02-14 17:56:40 -05002578bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2579 GLenum target,
2580 GLsizei samples,
2581 GLenum internalformat,
2582 GLsizei width,
2583 GLsizei height)
2584{
2585 if (context->getClientMajorVersion() < 3)
2586 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002588 return false;
2589 }
2590
2591 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2592 height))
2593 {
2594 return false;
2595 }
2596
2597 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2598 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002599 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002600 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2601 samples > 0)
2602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002603 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002604 return false;
2605 }
2606
2607 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2608 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2609 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2610 {
2611 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002612 InvalidOperation()
2613 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002614 return false;
2615 }
2616
2617 return true;
2618}
2619
Geoff Langaa086d62017-03-23 16:47:21 -04002620bool ValidateVertexAttribIPointer(ValidationContext *context,
2621 GLuint index,
2622 GLint size,
2623 GLenum type,
2624 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002625 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002626{
2627 if (context->getClientMajorVersion() < 3)
2628 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002630 return false;
2631 }
2632
Shao80957d92017-02-20 21:25:59 +08002633 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002634 {
Geoff Langaa086d62017-03-23 16:47:21 -04002635 return false;
2636 }
2637
Geoff Langaa086d62017-03-23 16:47:21 -04002638 if (stride < 0)
2639 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002640 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002641 return false;
2642 }
2643
Shao80957d92017-02-20 21:25:59 +08002644 const Caps &caps = context->getCaps();
2645 if (context->getClientVersion() >= ES_3_1)
2646 {
2647 if (stride > caps.maxVertexAttribStride)
2648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002649 context->handleError(InvalidValue()
2650 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002651 return false;
2652 }
2653
2654 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2655 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2656 // validation should be inherited.
2657 if (index >= caps.maxVertexAttribBindings)
2658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002659 context->handleError(InvalidValue()
2660 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002661 return false;
2662 }
2663 }
2664
Geoff Langaa086d62017-03-23 16:47:21 -04002665 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2666 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2667 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2668 // and the pointer argument is not NULL.
2669 if (context->getGLState().getVertexArrayId() != 0 &&
2670 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002672 context
2673 ->handleError(InvalidOperation()
2674 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002675 return false;
2676 }
2677
Geoff Lang2d62ab72017-03-23 16:54:40 -04002678 if (context->getExtensions().webglCompatibility)
2679 {
2680 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2681 {
2682 return false;
2683 }
2684 }
2685
Geoff Langaa086d62017-03-23 16:47:21 -04002686 return true;
2687}
2688
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002689bool ValidateGetSynciv(Context *context,
2690 GLsync sync,
2691 GLenum pname,
2692 GLsizei bufSize,
2693 GLsizei *length,
2694 GLint *values)
2695{
2696 if (context->getClientMajorVersion() < 3)
2697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002699 return false;
2700 }
2701
2702 if (bufSize < 0)
2703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002704 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002705 return false;
2706 }
2707
Jamie Madill70b5bb02017-08-28 13:32:37 -04002708 Sync *syncObject = context->getSync(sync);
2709 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002711 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002712 return false;
2713 }
2714
2715 switch (pname)
2716 {
2717 case GL_OBJECT_TYPE:
2718 case GL_SYNC_CONDITION:
2719 case GL_SYNC_FLAGS:
2720 case GL_SYNC_STATUS:
2721 break;
2722
2723 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002724 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002725 return false;
2726 }
2727
2728 return true;
2729}
2730
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002731bool ValidateDrawElementsInstanced(ValidationContext *context,
2732 GLenum mode,
2733 GLsizei count,
2734 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002735 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002736 GLsizei instanceCount)
2737{
2738 if (context->getClientMajorVersion() < 3)
2739 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002740 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002741 return false;
2742 }
2743
2744 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2745}
2746
Martin Radev137032d2017-07-13 10:11:12 +03002747bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2748 GLenum target,
2749 GLenum attachment,
2750 GLuint texture,
2751 GLint level,
2752 GLint baseViewIndex,
2753 GLsizei numViews)
2754{
2755
2756 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2757 numViews))
2758 {
2759 return false;
2760 }
2761
Martin Radev137032d2017-07-13 10:11:12 +03002762 if (texture != 0)
2763 {
Martin Radev14b21262017-08-25 13:54:37 +03002764 if (baseViewIndex < 0)
2765 {
2766 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2767 return false;
2768 }
2769
Martin Radev137032d2017-07-13 10:11:12 +03002770 Texture *tex = context->getTexture(texture);
2771 ASSERT(tex);
2772
2773 switch (tex->getTarget())
2774 {
2775 case GL_TEXTURE_2D_ARRAY:
2776 {
2777 const Caps &caps = context->getCaps();
2778 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2779 {
2780 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2781 "greater than "
2782 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2783 return false;
2784 }
2785 }
2786 break;
2787 default:
2788 context->handleError(InvalidOperation()
2789 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2790 return false;
2791 }
2792
2793 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2794 {
2795 return false;
2796 }
2797 }
2798
2799 return true;
2800}
2801
2802bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2803 GLenum target,
2804 GLenum attachment,
2805 GLuint texture,
2806 GLint level,
2807 GLsizei numViews,
2808 const GLint *viewportOffsets)
2809{
2810 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2811 numViews))
2812 {
2813 return false;
2814 }
2815
Martin Radev137032d2017-07-13 10:11:12 +03002816 if (texture != 0)
2817 {
Martin Radev14b21262017-08-25 13:54:37 +03002818 const GLsizei numViewportOffsetValues = numViews * 2;
2819 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2820 {
2821 if (viewportOffsets[i] < 0)
2822 {
2823 context->handleError(InvalidValue()
2824 << "viewportOffsets cannot contain negative values.");
2825 return false;
2826 }
2827 }
2828
Martin Radev137032d2017-07-13 10:11:12 +03002829 Texture *tex = context->getTexture(texture);
2830 ASSERT(tex);
2831
2832 switch (tex->getTarget())
2833 {
2834 case GL_TEXTURE_2D:
2835 break;
2836 default:
2837 context->handleError(InvalidOperation()
2838 << "Texture's target must be GL_TEXTURE_2D.");
2839 return false;
2840 }
2841
2842 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2843 {
2844 return false;
2845 }
2846 }
2847
2848 return true;
2849}
2850
Jamie Madillff325f12017-08-26 15:06:05 -04002851bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2852{
2853 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2854}
2855
2856bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2857{
2858 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2859}
2860
2861bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2862{
2863 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2864}
2865
2866bool ValidateUniform4ui(Context *context,
2867 GLint location,
2868 GLuint v0,
2869 GLuint v1,
2870 GLuint v2,
2871 GLuint v3)
2872{
2873 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2874}
2875
2876bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2877{
2878 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2879}
2880
2881bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2882{
2883 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2884}
2885
2886bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2887{
2888 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2889}
2890
2891bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2892{
2893 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2894}
2895
Jamie Madillf0e04492017-08-26 15:28:42 -04002896bool ValidateIsQuery(Context *context, GLuint id)
2897{
2898 if (context->getClientMajorVersion() < 3)
2899 {
2900 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2901 return false;
2902 }
2903
2904 return true;
2905}
2906
Jamie Madillc8c95812017-08-26 18:40:09 -04002907bool ValidateUniformMatrix2x3fv(Context *context,
2908 GLint location,
2909 GLsizei count,
2910 GLboolean transpose,
2911 const GLfloat *value)
2912{
2913 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2914}
2915
2916bool ValidateUniformMatrix3x2fv(Context *context,
2917 GLint location,
2918 GLsizei count,
2919 GLboolean transpose,
2920 const GLfloat *value)
2921{
2922 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2923}
2924
2925bool ValidateUniformMatrix2x4fv(Context *context,
2926 GLint location,
2927 GLsizei count,
2928 GLboolean transpose,
2929 const GLfloat *value)
2930{
2931 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2932}
2933
2934bool ValidateUniformMatrix4x2fv(Context *context,
2935 GLint location,
2936 GLsizei count,
2937 GLboolean transpose,
2938 const GLfloat *value)
2939{
2940 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2941}
2942
2943bool ValidateUniformMatrix3x4fv(Context *context,
2944 GLint location,
2945 GLsizei count,
2946 GLboolean transpose,
2947 const GLfloat *value)
2948{
2949 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2950}
2951
2952bool ValidateUniformMatrix4x3fv(Context *context,
2953 GLint location,
2954 GLsizei count,
2955 GLboolean transpose,
2956 const GLfloat *value)
2957{
2958 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2959}
2960
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002961bool ValidateEndTransformFeedback(Context *context)
2962{
2963 if (context->getClientMajorVersion() < 3)
2964 {
2965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2966 return false;
2967 }
2968
2969 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2970 ASSERT(transformFeedback != nullptr);
2971
2972 if (!transformFeedback->isActive())
2973 {
2974 context->handleError(InvalidOperation());
2975 return false;
2976 }
2977
2978 return true;
2979}
2980
2981bool ValidateTransformFeedbackVaryings(Context *context,
2982 GLuint program,
2983 GLsizei count,
2984 const GLchar *const *varyings,
2985 GLenum bufferMode)
2986{
2987 if (context->getClientMajorVersion() < 3)
2988 {
2989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2990 return false;
2991 }
2992
2993 if (count < 0)
2994 {
2995 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2996 return false;
2997 }
2998
2999 switch (bufferMode)
3000 {
3001 case GL_INTERLEAVED_ATTRIBS:
3002 break;
3003 case GL_SEPARATE_ATTRIBS:
3004 {
3005 const Caps &caps = context->getCaps();
3006 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3007 {
3008 context->handleError(InvalidValue());
3009 return false;
3010 }
3011 break;
3012 }
3013 default:
3014 context->handleError(InvalidEnum());
3015 return false;
3016 }
3017
3018 Program *programObject = GetValidProgram(context, program);
3019 if (!programObject)
3020 {
3021 return false;
3022 }
3023
3024 return true;
3025}
3026
3027bool ValidateGetTransformFeedbackVarying(Context *context,
3028 GLuint program,
3029 GLuint index,
3030 GLsizei bufSize,
3031 GLsizei *length,
3032 GLsizei *size,
3033 GLenum *type,
3034 GLchar *name)
3035{
3036 if (context->getClientMajorVersion() < 3)
3037 {
3038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3039 return false;
3040 }
3041
3042 if (bufSize < 0)
3043 {
3044 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3045 return false;
3046 }
3047
3048 Program *programObject = GetValidProgram(context, program);
3049 if (!programObject)
3050 {
3051 return false;
3052 }
3053
3054 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3055 {
3056 context->handleError(InvalidValue());
3057 return false;
3058 }
3059
3060 return true;
3061}
3062
3063bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3064{
3065 if (context->getClientMajorVersion() < 3)
3066 {
3067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3068 return false;
3069 }
3070
3071 switch (target)
3072 {
3073 case GL_TRANSFORM_FEEDBACK:
3074 {
3075 // Cannot bind a transform feedback object if the current one is started and not
3076 // paused (3.0.2 pg 85 section 2.14.1)
3077 TransformFeedback *curTransformFeedback =
3078 context->getGLState().getCurrentTransformFeedback();
3079 if (curTransformFeedback && curTransformFeedback->isActive() &&
3080 !curTransformFeedback->isPaused())
3081 {
3082 context->handleError(InvalidOperation());
3083 return false;
3084 }
3085
3086 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3087 // 2.14.1)
3088 if (!context->isTransformFeedbackGenerated(id))
3089 {
3090 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3091 return false;
3092 }
3093 }
3094 break;
3095
3096 default:
3097 context->handleError(InvalidEnum());
3098 return false;
3099 }
3100
3101 return true;
3102}
3103
3104bool ValidateIsTransformFeedback(Context *context, GLuint id)
3105{
3106 if (context->getClientMajorVersion() < 3)
3107 {
3108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3109 return false;
3110 }
3111
3112 return true;
3113}
3114
3115bool ValidatePauseTransformFeedback(Context *context)
3116{
3117 if (context->getClientMajorVersion() < 3)
3118 {
3119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3120 return false;
3121 }
3122
3123 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3124 ASSERT(transformFeedback != nullptr);
3125
3126 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3127 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3128 {
3129 context->handleError(InvalidOperation());
3130 return false;
3131 }
3132
3133 return true;
3134}
3135
3136bool ValidateResumeTransformFeedback(Context *context)
3137{
3138 if (context->getClientMajorVersion() < 3)
3139 {
3140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3141 return false;
3142 }
3143
3144 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3145 ASSERT(transformFeedback != nullptr);
3146
3147 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3148 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3149 {
3150 context->handleError(InvalidOperation());
3151 return false;
3152 }
3153
3154 return true;
3155}
3156
Jamie Madill12e957f2017-08-26 21:42:26 -04003157bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3158{
3159 if (context->getClientMajorVersion() < 3)
3160 {
3161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3162 return false;
3163 }
3164
3165 return ValidateVertexAttribIndex(context, index);
3166}
3167
3168bool ValidateVertexAttribI4ui(Context *context,
3169 GLuint index,
3170 GLuint x,
3171 GLuint y,
3172 GLuint z,
3173 GLuint w)
3174{
3175 if (context->getClientMajorVersion() < 3)
3176 {
3177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3178 return false;
3179 }
3180
3181 return ValidateVertexAttribIndex(context, index);
3182}
3183
3184bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3185{
3186 if (context->getClientMajorVersion() < 3)
3187 {
3188 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3189 return false;
3190 }
3191
3192 return ValidateVertexAttribIndex(context, index);
3193}
3194
3195bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3196{
3197 if (context->getClientMajorVersion() < 3)
3198 {
3199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3200 return false;
3201 }
3202
3203 return ValidateVertexAttribIndex(context, index);
3204}
3205
3206bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3207{
3208 if (context->getClientMajorVersion() < 3)
3209 {
3210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3211 return false;
3212 }
3213
3214 Program *programObject = GetValidProgram(context, program);
3215 if (!programObject)
3216 {
3217 return false;
3218 }
3219
3220 if (!programObject->isLinked())
3221 {
3222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3223 return false;
3224 }
3225
3226 return true;
3227}
3228
3229bool ValidateGetUniformIndices(Context *context,
3230 GLuint program,
3231 GLsizei uniformCount,
3232 const GLchar *const *uniformNames,
3233 GLuint *uniformIndices)
3234{
3235 if (context->getClientMajorVersion() < 3)
3236 {
3237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3238 return false;
3239 }
3240
3241 if (uniformCount < 0)
3242 {
3243 context->handleError(InvalidValue());
3244 return false;
3245 }
3246
3247 Program *programObject = GetValidProgram(context, program);
3248 if (!programObject)
3249 {
3250 return false;
3251 }
3252
3253 return true;
3254}
3255
3256bool ValidateGetActiveUniformsiv(Context *context,
3257 GLuint program,
3258 GLsizei uniformCount,
3259 const GLuint *uniformIndices,
3260 GLenum pname,
3261 GLint *params)
3262{
3263 if (context->getClientMajorVersion() < 3)
3264 {
3265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3266 return false;
3267 }
3268
3269 if (uniformCount < 0)
3270 {
3271 context->handleError(InvalidValue());
3272 return false;
3273 }
3274
3275 Program *programObject = GetValidProgram(context, program);
3276 if (!programObject)
3277 {
3278 return false;
3279 }
3280
3281 switch (pname)
3282 {
3283 case GL_UNIFORM_TYPE:
3284 case GL_UNIFORM_SIZE:
3285 case GL_UNIFORM_NAME_LENGTH:
3286 case GL_UNIFORM_BLOCK_INDEX:
3287 case GL_UNIFORM_OFFSET:
3288 case GL_UNIFORM_ARRAY_STRIDE:
3289 case GL_UNIFORM_MATRIX_STRIDE:
3290 case GL_UNIFORM_IS_ROW_MAJOR:
3291 break;
3292
3293 default:
3294 context->handleError(InvalidEnum());
3295 return false;
3296 }
3297
3298 if (uniformCount > programObject->getActiveUniformCount())
3299 {
3300 context->handleError(InvalidValue());
3301 return false;
3302 }
3303
3304 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3305 {
3306 const GLuint index = uniformIndices[uniformId];
3307
3308 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3309 {
3310 context->handleError(InvalidValue());
3311 return false;
3312 }
3313 }
3314
3315 return true;
3316}
3317
3318bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3319{
3320 if (context->getClientMajorVersion() < 3)
3321 {
3322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3323 return false;
3324 }
3325
3326 Program *programObject = GetValidProgram(context, program);
3327 if (!programObject)
3328 {
3329 return false;
3330 }
3331
3332 return true;
3333}
3334
3335bool ValidateGetActiveUniformBlockiv(Context *context,
3336 GLuint program,
3337 GLuint uniformBlockIndex,
3338 GLenum pname,
3339 GLint *params)
3340{
3341 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3342}
3343
3344bool ValidateGetActiveUniformBlockName(Context *context,
3345 GLuint program,
3346 GLuint uniformBlockIndex,
3347 GLsizei bufSize,
3348 GLsizei *length,
3349 GLchar *uniformBlockName)
3350{
3351 if (context->getClientMajorVersion() < 3)
3352 {
3353 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3354 return false;
3355 }
3356
3357 Program *programObject = GetValidProgram(context, program);
3358 if (!programObject)
3359 {
3360 return false;
3361 }
3362
3363 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3364 {
3365 context->handleError(InvalidValue());
3366 return false;
3367 }
3368
3369 return true;
3370}
3371
3372bool ValidateUniformBlockBinding(Context *context,
3373 GLuint program,
3374 GLuint uniformBlockIndex,
3375 GLuint uniformBlockBinding)
3376{
3377 if (context->getClientMajorVersion() < 3)
3378 {
3379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3380 return false;
3381 }
3382
3383 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3384 {
3385 context->handleError(InvalidValue());
3386 return false;
3387 }
3388
3389 Program *programObject = GetValidProgram(context, program);
3390 if (!programObject)
3391 {
3392 return false;
3393 }
3394
3395 // if never linked, there won't be any uniform blocks
3396 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3397 {
3398 context->handleError(InvalidValue());
3399 return false;
3400 }
3401
3402 return true;
3403}
3404
3405bool ValidateDrawArraysInstanced(Context *context,
3406 GLenum mode,
3407 GLint first,
3408 GLsizei count,
3409 GLsizei primcount)
3410{
3411 if (context->getClientMajorVersion() < 3)
3412 {
3413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3414 return false;
3415 }
3416
3417 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3418}
3419
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003420bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3421{
3422 if (context->getClientMajorVersion() < 3)
3423 {
3424 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3425 return false;
3426 }
3427
3428 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3429 {
3430 context->handleError(InvalidEnum());
3431 return false;
3432 }
3433
3434 if (flags != 0)
3435 {
3436 context->handleError(InvalidValue());
3437 return false;
3438 }
3439
3440 return true;
3441}
3442
3443bool ValidateIsSync(Context *context, GLsync sync)
3444{
3445 if (context->getClientMajorVersion() < 3)
3446 {
3447 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3448 return false;
3449 }
3450
3451 return true;
3452}
3453
3454bool ValidateDeleteSync(Context *context, GLsync sync)
3455{
3456 if (context->getClientMajorVersion() < 3)
3457 {
3458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3459 return false;
3460 }
3461
Jamie Madill70b5bb02017-08-28 13:32:37 -04003462 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003463 {
3464 context->handleError(InvalidValue());
3465 return false;
3466 }
3467
3468 return true;
3469}
3470
3471bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3472{
3473 if (context->getClientMajorVersion() < 3)
3474 {
3475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3476 return false;
3477 }
3478
3479 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3480 {
3481 context->handleError(InvalidValue());
3482 return false;
3483 }
3484
Jamie Madill70b5bb02017-08-28 13:32:37 -04003485 Sync *clientWaitSync = context->getSync(sync);
3486 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003487 {
3488 context->handleError(InvalidValue());
3489 return false;
3490 }
3491
3492 return true;
3493}
3494
3495bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3496{
3497 if (context->getClientMajorVersion() < 3)
3498 {
3499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3500 return false;
3501 }
3502
3503 if (flags != 0)
3504 {
3505 context->handleError(InvalidValue());
3506 return false;
3507 }
3508
3509 if (timeout != GL_TIMEOUT_IGNORED)
3510 {
3511 context->handleError(InvalidValue());
3512 return false;
3513 }
3514
Jamie Madill70b5bb02017-08-28 13:32:37 -04003515 Sync *waitSync = context->getSync(sync);
3516 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003517 {
3518 context->handleError(InvalidValue());
3519 return false;
3520 }
3521
3522 return true;
3523}
3524
3525bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3526{
3527 if (context->getClientMajorVersion() < 3)
3528 {
3529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3530 return false;
3531 }
3532
3533 GLenum nativeType = GL_NONE;
3534 unsigned int numParams = 0;
3535 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3536 {
3537 return false;
3538 }
3539
3540 return true;
3541}
3542
Jamie Madill3ef140a2017-08-26 23:11:21 -04003543bool ValidateIsSampler(Context *context, GLuint sampler)
3544{
3545 if (context->getClientMajorVersion() < 3)
3546 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003547 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003548 return false;
3549 }
3550
3551 return true;
3552}
3553
3554bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3555{
3556 if (context->getClientMajorVersion() < 3)
3557 {
3558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3559 return false;
3560 }
3561
3562 if (sampler != 0 && !context->isSampler(sampler))
3563 {
3564 context->handleError(InvalidOperation());
3565 return false;
3566 }
3567
3568 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3569 {
3570 context->handleError(InvalidValue());
3571 return false;
3572 }
3573
3574 return true;
3575}
3576
3577bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3578{
3579 if (context->getClientMajorVersion() < 3)
3580 {
3581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3582 return false;
3583 }
3584
3585 return ValidateVertexAttribIndex(context, index);
3586}
3587
3588bool ValidateTexStorage2D(Context *context,
3589 GLenum target,
3590 GLsizei levels,
3591 GLenum internalformat,
3592 GLsizei width,
3593 GLsizei height)
3594{
3595 if (context->getClientMajorVersion() < 3)
3596 {
3597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3598 return false;
3599 }
3600
3601 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3602 1))
3603 {
3604 return false;
3605 }
3606
3607 return true;
3608}
3609
3610bool ValidateTexStorage3D(Context *context,
3611 GLenum target,
3612 GLsizei levels,
3613 GLenum internalformat,
3614 GLsizei width,
3615 GLsizei height,
3616 GLsizei depth)
3617{
3618 if (context->getClientMajorVersion() < 3)
3619 {
3620 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3621 return false;
3622 }
3623
3624 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3625 depth))
3626 {
3627 return false;
3628 }
3629
3630 return true;
3631}
3632
Jamie Madill9696d072017-08-26 23:19:57 -04003633bool ValidateGetBufferParameteri64v(ValidationContext *context,
3634 GLenum target,
3635 GLenum pname,
3636 GLint64 *params)
3637{
3638 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3639}
3640
3641bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3642{
3643 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3644}
3645
3646bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3647{
3648 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3649}
3650
3651bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3652{
3653 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3654}
3655
3656bool ValidateSamplerParameterfv(Context *context,
3657 GLuint sampler,
3658 GLenum pname,
3659 const GLfloat *params)
3660{
3661 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3662}
3663
3664bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3665{
3666 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3667}
3668
3669bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3670{
3671 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3672}
3673
3674bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3675{
3676 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3677}
3678
3679bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3680{
3681 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3682}
3683
3684bool ValidateGetInternalformativ(Context *context,
3685 GLenum target,
3686 GLenum internalformat,
3687 GLenum pname,
3688 GLsizei bufSize,
3689 GLint *params)
3690{
3691 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3692 nullptr);
3693}
3694
Jamie Madillc29968b2016-01-20 11:17:23 -05003695} // namespace gl