blob: 0aa209d875072149700bdf60553597cad186f5d1 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
Martin Radev14b21262017-08-25 13:54:37 +030048 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030049 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800112bool ValidateGenOrDeleteES3(Context *context, GLint n)
113{
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120}
121
122bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123{
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135}
136
Jamie Madillff325f12017-08-26 15:06:05 -0400137} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300138
He Yunchaoced53ae2016-11-29 15:00:51 +0800139static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -0400140 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400144{
Geoff Lang5d601382014-07-22 15:14:06 -0400145
146 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400147 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400148 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400166 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400167 }
168
Geoff Langca271392017-04-05 12:30:00 -0400169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
174 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400179 return false;
180 }
181
Geoff Lang5d601382014-07-22 15:14:06 -0400182 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400183 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400195 }
196
197 return true;
198}
199
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500200bool ValidateES3TexImageParametersBase(Context *context,
201 GLenum target,
202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400215 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400216 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217{
218 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700219 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500221 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 }
224
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400225 // Verify zero border
226 if (border != 0)
227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500228 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 }
231
Jamie Madill6f38f822014-06-06 17:12:20 -0400232 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
233 std::numeric_limits<GLsizei>::max() - xoffset < width ||
234 std::numeric_limits<GLsizei>::max() - yoffset < height ||
235 std::numeric_limits<GLsizei>::max() - zoffset < depth)
236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500237 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400238 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400239 }
240
Geoff Langaae65a42014-05-26 12:43:44 -0400241 const gl::Caps &caps = context->getCaps();
242
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 switch (target)
244 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800245 case GL_TEXTURE_2D:
246 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
247 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800250 return false;
251 }
252 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400254 case GL_TEXTURE_RECTANGLE_ANGLE:
255 ASSERT(level == 0);
256 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
257 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
258 {
259 context->handleError(InvalidValue());
260 return false;
261 }
262 if (isCompressed)
263 {
264 context->handleError(InvalidEnum()
265 << "Rectangle texture cannot have a compressed format.");
266 return false;
267 }
268 break;
269
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
271 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
272 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
276 if (!isSubImage && width != height)
277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500278 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800279 return false;
280 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281
He Yunchaoced53ae2016-11-29 15:00:51 +0800282 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500284 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800285 return false;
286 }
287 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400288
He Yunchaoced53ae2016-11-29 15:00:51 +0800289 case GL_TEXTURE_3D:
290 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
291 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
292 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500294 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800295 return false;
296 }
297 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298
He Yunchaoced53ae2016-11-29 15:00:51 +0800299 case GL_TEXTURE_2D_ARRAY:
300 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
301 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
302 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500304 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800305 return false;
306 }
307 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400308
He Yunchaoced53ae2016-11-29 15:00:51 +0800309 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500310 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
He Yunchaoced53ae2016-11-29 15:00:51 +0800314 gl::Texture *texture =
315 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 if (!texture)
317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500318 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 }
321
Geoff Lang69cce582015-09-17 13:20:36 -0400322 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500324 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 }
327
328 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400329 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400330 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500331 if (isSubImage && actualInternalFormat == GL_NONE)
332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500333 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500334 return false;
335 }
336
Geoff Langc4e93662017-05-01 10:45:59 -0400337 const gl::InternalFormat &actualFormatInfo = isSubImage
338 ? *texture->getFormat(target, level).info
339 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 if (isCompressed)
341 {
tmartino7c102692015-10-02 16:43:40 -0400342 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(
345 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400346 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400347 }
348
Geoff Lang966c9402017-04-18 12:38:27 -0400349 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350 {
Geoff Lang966c9402017-04-18 12:38:27 -0400351 if (!ValidCompressedSubImageSize(
352 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
353 texture->getWidth(target, level), texture->getHeight(target, level)))
354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500355 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400356 return false;
357 }
358
359 if (format != actualInternalFormat)
360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500361 context->handleError(InvalidOperation()
362 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400363 return false;
364 }
Geoff Lang86f81162017-10-30 15:10:45 -0400365
366 if (actualInternalFormat == GL_ETC1_RGB8_OES)
367 {
368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
369 return false;
370 }
Geoff Lang966c9402017-04-18 12:38:27 -0400371 }
372 else
373 {
374 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500376 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400377 return false;
378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 }
380
Geoff Langeb66a6e2016-10-31 13:06:12 -0400381 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500383 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400384 return false;
385 }
386
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 if (target == GL_TEXTURE_3D)
388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500389 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392 }
393 else
394 {
Geoff Langca271392017-04-05 12:30:00 -0400395 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 {
Geoff Lang5d601382014-07-22 15:14:06 -0400397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 }
400
401 // Validate sub image parameters
402 if (isSubImage)
403 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500404 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500406 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500412 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 }
415
416 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
417 std::numeric_limits<GLsizei>::max() - yoffset < height ||
418 std::numeric_limits<GLsizei>::max() - zoffset < depth)
419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500420 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 }
423
Geoff Langa9be0dc2014-12-17 12:34:40 -0500424 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
425 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
426 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500428 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
Geoff Langfb052642017-10-24 13:42:09 -0400431
432 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400433 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400434 {
435 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
436 return false;
437 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 }
439
Geoff Langdbcced82017-06-06 15:55:54 -0400440 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
441 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
442 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400443 {
444 return false;
445 }
446
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400447 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400448 gl::Buffer *pixelUnpackBuffer =
449 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400450 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400451 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800452 // ...data is not evenly divisible into the number of bytes needed to store in memory a
453 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400454 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400455 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400456 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400457 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400458 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
459
Geoff Langff5b2d52016-09-07 11:32:23 -0400460 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500462 context->handleError(InvalidOperation()
463 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400464 return false;
465 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400466 }
467
Jamie Madill7a5f7382014-03-05 15:01:24 -0500468 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700469 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500471 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400472 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500473 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400474 }
475
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 return true;
477}
478
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500479bool ValidateES3TexImage2DParameters(Context *context,
480 GLenum target,
481 GLint level,
482 GLenum internalformat,
483 bool isCompressed,
484 bool isSubImage,
485 GLint xoffset,
486 GLint yoffset,
487 GLint zoffset,
488 GLsizei width,
489 GLsizei height,
490 GLsizei depth,
491 GLint border,
492 GLenum format,
493 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400494 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400495 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500496{
497 if (!ValidTexture2DDestinationTarget(context, target))
498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500499 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500500 return false;
501 }
502
503 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
504 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400505 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500506}
507
508bool ValidateES3TexImage3DParameters(Context *context,
509 GLenum target,
510 GLint level,
511 GLenum internalformat,
512 bool isCompressed,
513 bool isSubImage,
514 GLint xoffset,
515 GLint yoffset,
516 GLint zoffset,
517 GLsizei width,
518 GLsizei height,
519 GLsizei depth,
520 GLint border,
521 GLenum format,
522 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400523 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400524 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500525{
526 if (!ValidTexture3DDestinationTarget(context, target))
527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500528 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500529 return false;
530 }
531
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500532 if (IsETC2EACFormat(format) && target != GL_TEXTURE_2D_ARRAY)
533 {
534 // ES 3.1, Section 8.7, page 169.
535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
536 return false;
537 }
538
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500539 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
540 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400541 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500542}
543
Geoff Lang5d601382014-07-22 15:14:06 -0400544struct EffectiveInternalFormatInfo
545{
Jamie Madill76648fe2016-10-05 17:01:41 -0400546 GLenum effectiveFormat;
547 GLenum destFormat;
548 GLuint minRedBits;
549 GLuint maxRedBits;
550 GLuint minGreenBits;
551 GLuint maxGreenBits;
552 GLuint minBlueBits;
553 GLuint maxBlueBits;
554 GLuint minAlphaBits;
555 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400556};
557
Jamie Madill76648fe2016-10-05 17:01:41 -0400558static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
559 GLenum targetFormat,
560 const EffectiveInternalFormatInfo *list,
561 size_t size,
562 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400563{
Jamie Madill76648fe2016-10-05 17:01:41 -0400564 for (size_t curFormat = 0; curFormat < size; ++curFormat)
565 {
566 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
567 if ((formatInfo.destFormat == targetFormat) &&
568 (formatInfo.minRedBits <= srcFormat.redBits &&
569 formatInfo.maxRedBits >= srcFormat.redBits) &&
570 (formatInfo.minGreenBits <= srcFormat.greenBits &&
571 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
572 (formatInfo.minBlueBits <= srcFormat.blueBits &&
573 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
574 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
575 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
576 {
577 *outEffectiveFormat = formatInfo.effectiveFormat;
578 return true;
579 }
580 }
Geoff Lang5d601382014-07-22 15:14:06 -0400581
Jamie Madill76648fe2016-10-05 17:01:41 -0400582 *outEffectiveFormat = GL_NONE;
583 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400584}
585
Jamie Madill76648fe2016-10-05 17:01:41 -0400586bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
587 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400588{
Jamie Madill76648fe2016-10-05 17:01:41 -0400589 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
590 // Effective internal format coresponding to destination internal format and linear source
591 // buffer component sizes.
592 // | Source channel min/max sizes |
593 // Effective Internal Format | N/A | R | G | B | A |
594 // clang-format off
595 constexpr EffectiveInternalFormatInfo list[] = {
596 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
597 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
598 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
599 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
600 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
601 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
602 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
603 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
604 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
605 };
606 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400607
Jamie Madill76648fe2016-10-05 17:01:41 -0400608 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
609}
Geoff Lang5d601382014-07-22 15:14:06 -0400610
Jamie Madill76648fe2016-10-05 17:01:41 -0400611bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
612 const InternalFormat &destFormat,
613 GLenum *outEffectiveFormat)
614{
615 constexpr GLuint umax = UINT_MAX;
616
617 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
618 // Effective internal format coresponding to destination internal format andlinear source buffer
619 // component sizes.
620 // | Source channel min/max sizes |
621 // Effective Internal Format | Dest Format | R | G | B | A |
622 // clang-format off
623 constexpr EffectiveInternalFormatInfo list[] = {
624 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
625 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
626 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
627 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
628 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
629 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
630 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
631 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
632 };
633 // clang-format on
634
635 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
636 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400637}
638
He Yunchaoced53ae2016-11-29 15:00:51 +0800639static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
640 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400641 GLenum *outEffectiveFormat)
642{
Geoff Langca271392017-04-05 12:30:00 -0400643 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400644 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400645 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400646 }
647 else
648 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400649 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400650 }
Geoff Lang5d601382014-07-22 15:14:06 -0400651}
652
Corentin Wallez76287682016-04-25 09:23:38 -0400653static bool EqualOrFirstZero(GLuint first, GLuint second)
654{
655 return first == 0 || first == second;
656}
657
Geoff Langca271392017-04-05 12:30:00 -0400658static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
659 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400660 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400661{
Jamie Madill21b786b2016-11-01 17:41:31 -0400662 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400663 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400664 return false;
665 }
Geoff Lang5d601382014-07-22 15:14:06 -0400666
Jamie Madill21b786b2016-11-01 17:41:31 -0400667 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
668 // must both be signed, unsigned, or fixed point and both source and destinations
669 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
670 // conversion between fixed and floating point.
671
672 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
673 (framebufferFormatInfo.colorEncoding == GL_SRGB))
674 {
675 return false;
676 }
677
678 if (((textureFormatInfo.componentType == GL_INT) !=
679 (framebufferFormatInfo.componentType == GL_INT)) ||
680 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
681 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
682 {
683 return false;
684 }
685
686 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
687 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
688 textureFormatInfo.componentType == GL_FLOAT) &&
689 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
690 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
691 framebufferFormatInfo.componentType == GL_FLOAT))
692 {
693 return false;
694 }
695
696 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
697 // The effective internal format of the source buffer is determined with the following rules
698 // applied in order:
699 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
700 // format then the effective internal format is the source buffer's sized internal format.
701 // * If the source buffer is a texture that was created with an unsized base internal format,
702 // then the effective internal format is the source image array's effective internal
703 // format, as specified by table 3.12, which is determined from the <format> and <type>
704 // that were used when the source image array was specified by TexImage*.
705 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
706 // where Destination Internal Format matches internalformat and where the [source channel
707 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
708 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
709 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800710 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400711 if (readBufferHandle != 0)
712 {
713 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
714 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400715 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400716 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400718 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400719 else
Geoff Lang5d601382014-07-22 15:14:06 -0400720 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400721 // Renderbuffers cannot be created with an unsized internal format, so this must be an
722 // unsized-format texture. We can use the same table we use when creating textures to
723 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400724 sourceEffectiveFormat =
725 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400726 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400727 }
728 else
729 {
730 // The effective internal format must be derived from the source framebuffer's channel
731 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
732 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400733 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400734 GLenum effectiveFormat;
735 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
736 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400737 {
Geoff Langca271392017-04-05 12:30:00 -0400738 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400739 }
740 else
741 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400742 return false;
743 }
744 }
745 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
746 {
747 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400748 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400749 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
750 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
751 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
752 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
753 {
Geoff Langca271392017-04-05 12:30:00 -0400754 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400755 }
756 else
757 {
758 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400759 }
760 }
761 else
762 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400763 UNREACHABLE();
764 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400765 }
Geoff Lang5d601382014-07-22 15:14:06 -0400766 }
767
Geoff Langca271392017-04-05 12:30:00 -0400768 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400769 {
770 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
771 // sized, component sizes of the source and destination formats must exactly match if the
772 // destination format exists.
773 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
774 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
775 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
776 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
777 {
778 return false;
779 }
780 }
781
782 return true; // A conversion function exists, and no rule in the specification has precluded
783 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400784}
785
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
787 GLenum target,
788 GLint level,
789 GLenum internalformat,
790 bool isSubImage,
791 GLint xoffset,
792 GLint yoffset,
793 GLint zoffset,
794 GLint x,
795 GLint y,
796 GLsizei width,
797 GLsizei height,
798 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400799{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400800 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400801 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400802 xoffset, yoffset, zoffset, x, y, width, height, border,
803 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400804 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400805 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400807 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808
Jamie Madill51f40ec2016-06-15 14:06:00 -0400809 const auto &state = context->getGLState();
810 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
811 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400812
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400813 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500815 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400816 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400817 }
818
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400819 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500821 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400822 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400823 }
824
Jamie Madill0c8abca2016-07-22 20:21:26 -0400825 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826
827 if (isSubImage)
828 {
Geoff Langca271392017-04-05 12:30:00 -0400829 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500830 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500832 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400833 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 }
835 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400836 else
837 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400838 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400839 const InternalFormat &framebufferFormat = *source->getFormat().info;
840 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400841 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500843 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400844 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400845 }
846 }
847
Geoff Lang784a8fd2013-09-24 12:33:16 -0400848 // If width or height is zero, it is a no-op. Return false without setting an error.
849 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850}
851
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500852bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
853 GLenum target,
854 GLint level,
855 GLenum internalformat,
856 bool isSubImage,
857 GLint xoffset,
858 GLint yoffset,
859 GLint zoffset,
860 GLint x,
861 GLint y,
862 GLsizei width,
863 GLsizei height,
864 GLint border)
865{
866 if (!ValidTexture2DDestinationTarget(context, target))
867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500868 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500869 return false;
870 }
871
872 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
873 xoffset, yoffset, zoffset, x, y, width, height,
874 border);
875}
876
877bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
878 GLenum target,
879 GLint level,
880 GLenum internalformat,
881 bool isSubImage,
882 GLint xoffset,
883 GLint yoffset,
884 GLint zoffset,
885 GLint x,
886 GLint y,
887 GLsizei width,
888 GLsizei height,
889 GLint border)
890{
891 if (!ValidTexture3DDestinationTarget(context, target))
892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500893 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500894 return false;
895 }
896
897 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
898 xoffset, yoffset, zoffset, x, y, width, height,
899 border);
900}
901
902bool ValidateES3TexStorageParametersBase(Context *context,
903 GLenum target,
904 GLsizei levels,
905 GLenum internalformat,
906 GLsizei width,
907 GLsizei height,
908 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909{
910 if (width < 1 || height < 1 || depth < 1 || levels < 1)
911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500912 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400913 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 }
915
Geoff Langb92c1332015-09-04 12:54:55 -0400916 GLsizei maxDim = std::max(width, height);
917 if (target != GL_TEXTURE_2D_ARRAY)
918 {
919 maxDim = std::max(maxDim, depth);
920 }
921
922 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500924 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400925 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 }
927
Geoff Langaae65a42014-05-26 12:43:44 -0400928 const gl::Caps &caps = context->getCaps();
929
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 switch (target)
931 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800932 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 {
Geoff Langaae65a42014-05-26 12:43:44 -0400934 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
935 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500937 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 }
940 }
941 break;
942
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400943 case GL_TEXTURE_RECTANGLE_ANGLE:
944 {
945 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
946 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
947 {
948 context->handleError(InvalidValue());
949 return false;
950 }
951 }
952 break;
953
He Yunchaoced53ae2016-11-29 15:00:51 +0800954 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400955 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 if (width != height)
957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500958 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 }
961
Geoff Langaae65a42014-05-26 12:43:44 -0400962 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500964 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400965 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966 }
967 }
968 break;
969
He Yunchaoced53ae2016-11-29 15:00:51 +0800970 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 {
Geoff Langaae65a42014-05-26 12:43:44 -0400972 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
973 static_cast<GLuint>(height) > caps.max3DTextureSize ||
974 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500976 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400977 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400978 }
979 }
980 break;
981
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 {
Geoff Langaae65a42014-05-26 12:43:44 -0400984 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
985 static_cast<GLuint>(height) > caps.max2DTextureSize ||
986 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500988 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 }
991 }
992 break;
993
He Yunchaoced53ae2016-11-29 15:00:51 +0800994 default:
995 UNREACHABLE();
996 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997 }
998
Geoff Lang691e58c2014-12-19 17:03:25 -0500999 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 if (!texture || texture->id() == 0)
1001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001002 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001003 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 }
1005
Geoff Lang69cce582015-09-17 13:20:36 -04001006 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001009 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 }
1011
Geoff Langca271392017-04-05 12:30:00 -04001012 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001013 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001015 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001017 }
1018
Geoff Langca271392017-04-05 12:30:00 -04001019 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001021 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001025 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1026 {
1027 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1028 return false;
1029 }
1030
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 return true;
1032}
1033
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001034bool ValidateES3TexStorage2DParameters(Context *context,
1035 GLenum target,
1036 GLsizei levels,
1037 GLenum internalformat,
1038 GLsizei width,
1039 GLsizei height,
1040 GLsizei depth)
1041{
1042 if (!ValidTexture2DTarget(context, target))
1043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001044 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001045 return false;
1046 }
1047
1048 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1049 height, depth);
1050}
1051
1052bool ValidateES3TexStorage3DParameters(Context *context,
1053 GLenum target,
1054 GLsizei levels,
1055 GLenum internalformat,
1056 GLsizei width,
1057 GLsizei height,
1058 GLsizei depth)
1059{
1060 if (!ValidTexture3DTarget(context, target))
1061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001062 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001063 return false;
1064 }
1065
1066 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1067 height, depth);
1068}
1069
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001070bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1071{
Martin Radev1be913c2016-07-11 17:59:16 +03001072 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001073 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001075 return false;
1076 }
1077
1078 return ValidateBeginQueryBase(context, target, id);
1079}
1080
1081bool ValidateEndQuery(gl::Context *context, GLenum target)
1082{
Martin Radev1be913c2016-07-11 17:59:16 +03001083 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001084 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001086 return false;
1087 }
1088
1089 return ValidateEndQueryBase(context, target);
1090}
1091
1092bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1093{
Martin Radev1be913c2016-07-11 17:59:16 +03001094 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001095 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001097 return false;
1098 }
1099
Geoff Lang2186c382016-10-14 10:54:54 -04001100 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001101}
1102
1103bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1104{
Martin Radev1be913c2016-07-11 17:59:16 +03001105 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001106 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001107 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001108 return false;
1109 }
1110
Geoff Lang2186c382016-10-14 10:54:54 -04001111 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001112}
1113
He Yunchaoced53ae2016-11-29 15:00:51 +08001114bool ValidateFramebufferTextureLayer(Context *context,
1115 GLenum target,
1116 GLenum attachment,
1117 GLuint texture,
1118 GLint level,
1119 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001120{
Martin Radev1be913c2016-07-11 17:59:16 +03001121 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001122 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001125 }
1126
Jamie Madill55ec3b12014-07-03 10:38:57 -04001127 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1128 {
1129 return false;
1130 }
1131
1132 const gl::Caps &caps = context->getCaps();
1133 if (texture != 0)
1134 {
Geoff Lang23e02842017-10-17 13:24:09 -04001135 if (layer < 0)
1136 {
1137 context->handleError(InvalidValue());
1138 return false;
1139 }
1140
Jamie Madill55ec3b12014-07-03 10:38:57 -04001141 gl::Texture *tex = context->getTexture(texture);
1142 ASSERT(tex);
1143
1144 switch (tex->getTarget())
1145 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001146 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001147 {
1148 if (level > gl::log2(caps.max2DTextureSize))
1149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001150 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001151 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001152 }
1153
1154 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001158 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001159 }
1160 break;
1161
He Yunchaoced53ae2016-11-29 15:00:51 +08001162 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001163 {
1164 if (level > gl::log2(caps.max3DTextureSize))
1165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001166 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001168 }
1169
1170 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001172 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001174 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001175 }
1176 break;
1177
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001179 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001180 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001181 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001182
Jamie Madilla3944d42016-07-22 22:13:26 -04001183 const auto &format = tex->getFormat(tex->getTarget(), level);
1184 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001186 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001187 return false;
1188 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001189 }
1190
1191 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001192}
1193
He Yunchaoced53ae2016-11-29 15:00:51 +08001194bool ValidateInvalidateFramebuffer(Context *context,
1195 GLenum target,
1196 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001197 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001198{
Martin Radev1be913c2016-07-11 17:59:16 +03001199 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001202 return false;
1203 }
1204
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001205 bool defaultFramebuffer = false;
1206
1207 switch (target)
1208 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001209 case GL_DRAW_FRAMEBUFFER:
1210 case GL_FRAMEBUFFER:
1211 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1212 break;
1213 case GL_READ_FRAMEBUFFER:
1214 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1215 break;
1216 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001217 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 }
1220
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1222 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223}
1224
Jamie Madill3ef140a2017-08-26 23:11:21 -04001225bool ValidateInvalidateSubFramebuffer(Context *context,
1226 GLenum target,
1227 GLsizei numAttachments,
1228 const GLenum *attachments,
1229 GLint x,
1230 GLint y,
1231 GLsizei width,
1232 GLsizei height)
1233{
1234 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1235}
1236
Jamie Madillc29968b2016-01-20 11:17:23 -05001237bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001238{
Martin Radev1be913c2016-07-11 17:59:16 +03001239 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001240 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001242 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001243 }
1244
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001245 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001249 }
1250
1251 return true;
1252}
1253
Olli Etuaho71dfb362016-03-10 14:04:27 +02001254bool ValidateDrawRangeElements(Context *context,
1255 GLenum mode,
1256 GLuint start,
1257 GLuint end,
1258 GLsizei count,
1259 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001260 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001261{
Martin Radev1be913c2016-07-11 17:59:16 +03001262 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001263 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001265 return false;
1266 }
1267
1268 if (end < start)
1269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001271 return false;
1272 }
1273
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001274 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001275 {
1276 return false;
1277 }
1278
Jamie Madill9fdaa492018-02-16 10:52:11 -05001279 // Skip range checks for no-op calls.
1280 if (count <= 0)
1281 {
1282 return true;
1283 }
1284
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001285 // Use the parameter buffer to retrieve and cache the index range.
1286 const auto &params = context->getParams<HasIndexRange>();
1287 const auto &indexRangeOpt = params.getIndexRange();
1288 if (!indexRangeOpt.valid())
1289 {
1290 // Unexpected error.
1291 return false;
1292 }
1293
1294 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001295 {
1296 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001297 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001298 return false;
1299 }
1300 return true;
1301}
1302
He Yunchaoced53ae2016-11-29 15:00:51 +08001303bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001304{
Martin Radev1be913c2016-07-11 17:59:16 +03001305 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001306 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001308 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001309 }
1310
Jamie Madill78f41802014-08-25 15:47:55 -04001311 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001312}
1313
Jamie Madillb885e572015-02-03 16:16:04 -05001314bool ValidateReadBuffer(Context *context, GLenum src)
1315{
Martin Radev1be913c2016-07-11 17:59:16 +03001316 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001317 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001319 return false;
1320 }
1321
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001322 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001323
1324 if (readFBO == nullptr)
1325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001326 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001327 return false;
1328 }
1329
1330 if (src == GL_NONE)
1331 {
1332 return true;
1333 }
1334
Olli Etuaho84c9f592016-03-09 14:37:25 +02001335 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001338 return false;
1339 }
1340
1341 if (readFBO->id() == 0)
1342 {
1343 if (src != GL_BACK)
1344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001345 context->handleError(
1346 InvalidOperation()
1347 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001348 return false;
1349 }
1350 }
1351 else
1352 {
1353 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1354
1355 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001358 return false;
1359 }
1360 }
1361
1362 return true;
1363}
1364
Jamie Madill86af3d22015-07-21 15:14:07 -04001365bool ValidateCompressedTexImage3D(Context *context,
1366 GLenum target,
1367 GLint level,
1368 GLenum internalformat,
1369 GLsizei width,
1370 GLsizei height,
1371 GLsizei depth,
1372 GLint border,
1373 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001374 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001375{
Martin Radev1be913c2016-07-11 17:59:16 +03001376 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001377 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001378 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001379 return false;
1380 }
1381
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001382 if (!ValidTextureTarget(context, target))
1383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001385 return false;
1386 }
1387
Jamie Madille2e406c2016-06-02 13:04:10 -04001388 // Validate image size
1389 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001392 return false;
1393 }
1394
Geoff Langca271392017-04-05 12:30:00 -04001395 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001396 if (!formatInfo.compressed)
1397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001398 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001399 return false;
1400 }
1401
Jeff Gilbert48590352017-11-07 16:03:38 -08001402 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001403 if (blockSizeOrErr.isError())
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001406 return false;
1407 }
1408 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001410 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001411 return false;
1412 }
1413
1414 // 3D texture target validation
1415 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001418 return false;
1419 }
1420
1421 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001422 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001423 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1424 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001425 {
1426 return false;
1427 }
1428
1429 return true;
1430}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001431
Corentin Wallezb2931602017-04-11 15:58:57 -04001432bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1433 GLenum target,
1434 GLint level,
1435 GLenum internalformat,
1436 GLsizei width,
1437 GLsizei height,
1438 GLsizei depth,
1439 GLint border,
1440 GLsizei imageSize,
1441 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001442 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001443{
1444 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1445 {
1446 return false;
1447 }
1448
1449 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1450 depth, border, imageSize, data);
1451}
1452
Austin Kinrossbc781f32015-10-26 09:27:38 -07001453bool ValidateBindVertexArray(Context *context, GLuint array)
1454{
Martin Radev1be913c2016-07-11 17:59:16 +03001455 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001456 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001458 return false;
1459 }
1460
1461 return ValidateBindVertexArrayBase(context, array);
1462}
1463
Jamie Madilld7576732017-08-26 18:49:50 -04001464bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001465{
Martin Radev1be913c2016-07-11 17:59:16 +03001466 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001467 {
Jamie Madilld7576732017-08-26 18:49:50 -04001468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001469 return false;
1470 }
1471
1472 return true;
1473}
Geoff Langc5629752015-12-07 16:29:04 -05001474
Jiajia Qin6eafb042016-12-27 17:04:07 +08001475static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001476 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001477 GLuint index,
1478 GLuint buffer,
1479 GLintptr offset,
1480 GLsizeiptr size)
1481{
1482 if (context->getClientMajorVersion() < 3)
1483 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001484 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001485 return false;
1486 }
1487
1488 if (buffer != 0 && offset < 0)
1489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001490 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001491 return false;
1492 }
1493
1494 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1495 !context->isBufferGenerated(buffer))
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001498 return false;
1499 }
1500
1501 const Caps &caps = context->getCaps();
1502 switch (target)
1503 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001504 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001505 {
1506 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001508 context->handleError(InvalidValue() << "index is greater than or equal to the "
1509 "number of TRANSFORM_FEEDBACK_BUFFER "
1510 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001511 return false;
1512 }
1513 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001516 return false;
1517 }
1518
1519 TransformFeedback *curTransformFeedback =
1520 context->getGLState().getCurrentTransformFeedback();
1521 if (curTransformFeedback && curTransformFeedback->isActive())
1522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(InvalidOperation()
1524 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1525 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001526 return false;
1527 }
1528 break;
1529 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001530 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001531 {
1532 if (index >= caps.maxUniformBufferBindings)
1533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001534 context->handleError(InvalidValue() << "index is greater than or equal to the "
1535 "number of UNIFORM_BUFFER indexed "
1536 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001537 return false;
1538 }
1539
1540 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1541 {
1542 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001543 InvalidValue()
1544 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001545 return false;
1546 }
1547 break;
1548 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001549 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001550 {
1551 if (context->getClientVersion() < ES_3_1)
1552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidEnum()
1554 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001555 return false;
1556 }
1557 if (index >= caps.maxAtomicCounterBufferBindings)
1558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001559 context->handleError(InvalidValue() << "index is greater than or equal to the "
1560 "number of ATOMIC_COUNTER_BUFFER "
1561 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001562 return false;
1563 }
1564 if (buffer != 0 && (offset % 4) != 0)
1565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001566 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001567 return false;
1568 }
1569 break;
1570 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001571 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001572 {
1573 if (context->getClientVersion() < ES_3_1)
1574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001575 context->handleError(InvalidEnum()
1576 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001577 return false;
1578 }
1579 if (index >= caps.maxShaderStorageBufferBindings)
1580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001581 context->handleError(InvalidValue() << "index is greater than or equal to the "
1582 "number of SHADER_STORAGE_BUFFER "
1583 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001584 return false;
1585 }
1586 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001588 context->handleError(InvalidValue() << "offset must be multiple of value of "
1589 "SHADER_STORAGE_BUFFER_OFFSET_"
1590 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001591 return false;
1592 }
1593 break;
1594 }
1595 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001596 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001597 return false;
1598 }
1599
1600 return true;
1601}
1602
Corentin Wallez336129f2017-10-17 15:55:40 -04001603bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001604{
1605 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1606}
1607
1608bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001609 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001610 GLuint index,
1611 GLuint buffer,
1612 GLintptr offset,
1613 GLsizeiptr size)
1614{
1615 if (buffer != 0 && size <= 0)
1616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidValue()
1618 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001619 return false;
1620 }
1621 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1622}
1623
Geoff Langc5629752015-12-07 16:29:04 -05001624bool ValidateProgramBinary(Context *context,
1625 GLuint program,
1626 GLenum binaryFormat,
1627 const void *binary,
1628 GLint length)
1629{
Martin Radev1be913c2016-07-11 17:59:16 +03001630 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001631 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001633 return false;
1634 }
1635
1636 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1637}
1638
1639bool ValidateGetProgramBinary(Context *context,
1640 GLuint program,
1641 GLsizei bufSize,
1642 GLsizei *length,
1643 GLenum *binaryFormat,
1644 void *binary)
1645{
Martin Radev1be913c2016-07-11 17:59:16 +03001646 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001647 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001649 return false;
1650 }
1651
1652 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1653}
1654
Olli Etuahof0fee072016-03-30 15:11:58 +03001655bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001656{
Martin Radev1be913c2016-07-11 17:59:16 +03001657 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001658 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001660 return false;
1661 }
1662
1663 if (GetValidProgram(context, program) == nullptr)
1664 {
1665 return false;
1666 }
1667
1668 switch (pname)
1669 {
1670 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001671 if (value != GL_FALSE && value != GL_TRUE)
1672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001673 context->handleError(InvalidValue()
1674 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001675 return false;
1676 }
Geoff Langc5629752015-12-07 16:29:04 -05001677 break;
1678
Yunchao He61afff12017-03-14 15:34:03 +08001679 case GL_PROGRAM_SEPARABLE:
1680 if (context->getClientVersion() < ES_3_1)
1681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001682 context->handleError(InvalidEnum()
1683 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001684 return false;
1685 }
1686
1687 if (value != GL_FALSE && value != GL_TRUE)
1688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidValue()
1690 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001691 return false;
1692 }
1693 break;
1694
Geoff Langc5629752015-12-07 16:29:04 -05001695 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001696 context->handleError(InvalidEnum()
1697 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001698 return false;
1699 }
1700
1701 return true;
1702}
Jamie Madillc29968b2016-01-20 11:17:23 -05001703
1704bool ValidateBlitFramebuffer(Context *context,
1705 GLint srcX0,
1706 GLint srcY0,
1707 GLint srcX1,
1708 GLint srcY1,
1709 GLint dstX0,
1710 GLint dstY0,
1711 GLint dstX1,
1712 GLint dstY1,
1713 GLbitfield mask,
1714 GLenum filter)
1715{
Martin Radev1be913c2016-07-11 17:59:16 +03001716 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001717 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001719 return false;
1720 }
1721
1722 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1723 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724}
Jamie Madillc29968b2016-01-20 11:17:23 -05001725
1726bool ValidateClearBufferiv(ValidationContext *context,
1727 GLenum buffer,
1728 GLint drawbuffer,
1729 const GLint *value)
1730{
1731 switch (buffer)
1732 {
1733 case GL_COLOR:
1734 if (drawbuffer < 0 ||
1735 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001737 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001738 return false;
1739 }
Geoff Lang76e65652017-03-27 14:58:02 -04001740 if (context->getExtensions().webglCompatibility)
1741 {
1742 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001743 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001744 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1745 {
1746 return false;
1747 }
1748 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001749 break;
1750
1751 case GL_STENCIL:
1752 if (drawbuffer != 0)
1753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001754 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001755 return false;
1756 }
1757 break;
1758
1759 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
1763
1764 return ValidateClearBuffer(context);
1765}
1766
1767bool ValidateClearBufferuiv(ValidationContext *context,
1768 GLenum buffer,
1769 GLint drawbuffer,
1770 const GLuint *value)
1771{
1772 switch (buffer)
1773 {
1774 case GL_COLOR:
1775 if (drawbuffer < 0 ||
1776 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001778 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 return false;
1780 }
Geoff Lang76e65652017-03-27 14:58:02 -04001781 if (context->getExtensions().webglCompatibility)
1782 {
1783 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001784 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001785 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1786 {
1787 return false;
1788 }
1789 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001790 break;
1791
1792 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001794 return false;
1795 }
1796
1797 return ValidateClearBuffer(context);
1798}
1799
1800bool ValidateClearBufferfv(ValidationContext *context,
1801 GLenum buffer,
1802 GLint drawbuffer,
1803 const GLfloat *value)
1804{
1805 switch (buffer)
1806 {
1807 case GL_COLOR:
1808 if (drawbuffer < 0 ||
1809 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001811 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
Geoff Lang76e65652017-03-27 14:58:02 -04001814 if (context->getExtensions().webglCompatibility)
1815 {
1816 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1817 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001818 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001819 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1820 {
1821 return false;
1822 }
1823 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 break;
1825
1826 case GL_DEPTH:
1827 if (drawbuffer != 0)
1828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001829 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832 break;
1833
1834 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001836 return false;
1837 }
1838
1839 return ValidateClearBuffer(context);
1840}
1841
1842bool ValidateClearBufferfi(ValidationContext *context,
1843 GLenum buffer,
1844 GLint drawbuffer,
1845 GLfloat depth,
1846 GLint stencil)
1847{
1848 switch (buffer)
1849 {
1850 case GL_DEPTH_STENCIL:
1851 if (drawbuffer != 0)
1852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001853 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001854 return false;
1855 }
1856 break;
1857
1858 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001859 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001860 return false;
1861 }
1862
1863 return ValidateClearBuffer(context);
1864}
1865
1866bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1867{
Martin Radev1be913c2016-07-11 17:59:16 +03001868 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001871 return false;
1872 }
1873
1874 return ValidateDrawBuffersBase(context, n, bufs);
1875}
1876
1877bool ValidateCopyTexSubImage3D(Context *context,
1878 GLenum target,
1879 GLint level,
1880 GLint xoffset,
1881 GLint yoffset,
1882 GLint zoffset,
1883 GLint x,
1884 GLint y,
1885 GLsizei width,
1886 GLsizei height)
1887{
Martin Radev1be913c2016-07-11 17:59:16 +03001888 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001889 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001891 return false;
1892 }
1893
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001894 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1895 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001896}
1897
Jamie Madill73a84962016-02-12 09:27:23 -05001898bool ValidateTexImage3D(Context *context,
1899 GLenum target,
1900 GLint level,
1901 GLint internalformat,
1902 GLsizei width,
1903 GLsizei height,
1904 GLsizei depth,
1905 GLint border,
1906 GLenum format,
1907 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001908 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001909{
Martin Radev1be913c2016-07-11 17:59:16 +03001910 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001911 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001913 return false;
1914 }
1915
1916 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001917 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001918 pixels);
1919}
1920
Geoff Langc52f6f12016-10-14 10:18:00 -04001921bool ValidateTexImage3DRobustANGLE(Context *context,
1922 GLenum target,
1923 GLint level,
1924 GLint internalformat,
1925 GLsizei width,
1926 GLsizei height,
1927 GLsizei depth,
1928 GLint border,
1929 GLenum format,
1930 GLenum type,
1931 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001932 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001933{
1934 if (context->getClientMajorVersion() < 3)
1935 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001937 return false;
1938 }
1939
1940 if (!ValidateRobustEntryPoint(context, bufSize))
1941 {
1942 return false;
1943 }
1944
1945 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1946 0, 0, width, height, depth, border, format, type,
1947 bufSize, pixels);
1948}
1949
Jamie Madill73a84962016-02-12 09:27:23 -05001950bool ValidateTexSubImage3D(Context *context,
1951 GLenum target,
1952 GLint level,
1953 GLint xoffset,
1954 GLint yoffset,
1955 GLint zoffset,
1956 GLsizei width,
1957 GLsizei height,
1958 GLsizei depth,
1959 GLenum format,
1960 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001961 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001962{
Martin Radev1be913c2016-07-11 17:59:16 +03001963 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001964 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001966 return false;
1967 }
1968
1969 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1970 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001971 -1, pixels);
1972}
1973
1974bool ValidateTexSubImage3DRobustANGLE(Context *context,
1975 GLenum target,
1976 GLint level,
1977 GLint xoffset,
1978 GLint yoffset,
1979 GLint zoffset,
1980 GLsizei width,
1981 GLsizei height,
1982 GLsizei depth,
1983 GLenum format,
1984 GLenum type,
1985 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001986 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001987{
1988 if (context->getClientMajorVersion() < 3)
1989 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001991 return false;
1992 }
1993
1994 if (!ValidateRobustEntryPoint(context, bufSize))
1995 {
1996 return false;
1997 }
1998
1999 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2000 yoffset, zoffset, width, height, depth, 0, format, type,
2001 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002002}
2003
2004bool ValidateCompressedTexSubImage3D(Context *context,
2005 GLenum target,
2006 GLint level,
2007 GLint xoffset,
2008 GLint yoffset,
2009 GLint zoffset,
2010 GLsizei width,
2011 GLsizei height,
2012 GLsizei depth,
2013 GLenum format,
2014 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002015 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002016{
Martin Radev1be913c2016-07-11 17:59:16 +03002017 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002018 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002020 return false;
2021 }
2022
Geoff Langca271392017-04-05 12:30:00 -04002023 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002024 if (!formatInfo.compressed)
2025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002026 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002027 return false;
2028 }
2029
Jeff Gilbert48590352017-11-07 16:03:38 -08002030 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002031 if (blockSizeOrErr.isError())
2032 {
2033 context->handleError(blockSizeOrErr.getError());
2034 return false;
2035 }
2036 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002038 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002039 return false;
2040 }
2041
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002042 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2043 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2044 -1, data))
2045 {
2046 return false;
2047 }
2048
Jamie Madill73a84962016-02-12 09:27:23 -05002049 if (!data)
2050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002051 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002052 return false;
2053 }
2054
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002055 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002056}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002057
Corentin Wallezb2931602017-04-11 15:58:57 -04002058bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2059 GLenum target,
2060 GLint level,
2061 GLint xoffset,
2062 GLint yoffset,
2063 GLint zoffset,
2064 GLsizei width,
2065 GLsizei height,
2066 GLsizei depth,
2067 GLenum format,
2068 GLsizei imageSize,
2069 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002070 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002071{
2072 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2073 {
2074 return false;
2075 }
2076
2077 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2078 height, depth, format, imageSize, data);
2079}
Jamie Madill73a84962016-02-12 09:27:23 -05002080
Olli Etuaho41997e72016-03-10 13:38:39 +02002081bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2082{
2083 return ValidateGenOrDeleteES3(context, n);
2084}
2085
2086bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2087{
2088 return ValidateGenOrDeleteES3(context, n);
2089}
2090
2091bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2092{
2093 return ValidateGenOrDeleteCountES3(context, count);
2094}
2095
2096bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2097{
2098 return ValidateGenOrDeleteCountES3(context, count);
2099}
2100
2101bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2102{
2103 return ValidateGenOrDeleteES3(context, n);
2104}
2105
2106bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2107{
2108 if (!ValidateGenOrDeleteES3(context, n))
2109 {
2110 return false;
2111 }
2112 for (GLint i = 0; i < n; ++i)
2113 {
2114 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2115 if (transformFeedback != nullptr && transformFeedback->isActive())
2116 {
2117 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002118 context->handleError(InvalidOperation()
2119 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002120 return false;
2121 }
2122 }
2123 return true;
2124}
2125
2126bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2127{
2128 return ValidateGenOrDeleteES3(context, n);
2129}
2130
2131bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2132{
2133 return ValidateGenOrDeleteES3(context, n);
2134}
2135
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002136bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2137{
Martin Radev1be913c2016-07-11 17:59:16 +03002138 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002139 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002141 return false;
2142 }
2143 switch (primitiveMode)
2144 {
2145 case GL_TRIANGLES:
2146 case GL_LINES:
2147 case GL_POINTS:
2148 break;
2149
2150 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002151 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002152 return false;
2153 }
2154
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002155 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002156 ASSERT(transformFeedback != nullptr);
2157
2158 if (transformFeedback->isActive())
2159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002160 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002161 return false;
2162 }
Geoff Lang79f71042017-08-14 16:43:43 -04002163
2164 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2165 {
2166 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2167 if (buffer.get() && buffer->isMapped())
2168 {
2169 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2170 return false;
2171 }
2172 }
2173
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002174 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002175
2176 if (!program)
2177 {
2178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2179 return false;
2180 }
2181
2182 if (program->getTransformFeedbackVaryingCount() == 0)
2183 {
2184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2185 return false;
2186 }
2187
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002188 return true;
2189}
2190
Corentin Wallez336129f2017-10-17 15:55:40 -04002191bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002192{
Geoff Lang496c02d2016-10-20 11:38:11 -07002193 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2194}
2195
2196bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002197 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002198 GLenum pname,
2199 GLsizei bufSize,
2200 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002201 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002202{
2203 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002204 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002205 return false;
2206 }
2207
Geoff Lang496c02d2016-10-20 11:38:11 -07002208 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2209 {
2210 return false;
2211 }
2212
2213 if (!ValidateRobustBufferSize(context, bufSize, *length))
2214 {
2215 return false;
2216 }
2217
2218 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002219}
2220
Corentin Wallez336129f2017-10-17 15:55:40 -04002221bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002222{
Martin Radev1be913c2016-07-11 17:59:16 +03002223 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002224 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002225 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002226 return false;
2227 }
2228
2229 return ValidateUnmapBufferBase(context, target);
2230}
2231
2232bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002233 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002234 GLintptr offset,
2235 GLsizeiptr length,
2236 GLbitfield access)
2237{
Martin Radev1be913c2016-07-11 17:59:16 +03002238 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002239 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002241 return false;
2242 }
2243
2244 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2245}
2246
2247bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002248 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002249 GLintptr offset,
2250 GLsizeiptr length)
2251{
Martin Radev1be913c2016-07-11 17:59:16 +03002252 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002253 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002255 return false;
2256 }
2257
2258 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2259}
2260
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002261bool ValidateIndexedStateQuery(ValidationContext *context,
2262 GLenum pname,
2263 GLuint index,
2264 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002265{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002266 if (length)
2267 {
2268 *length = 0;
2269 }
2270
Martin Radev66fb8202016-07-28 11:45:20 +03002271 GLenum nativeType;
2272 unsigned int numParams;
2273 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002275 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002276 return false;
2277 }
2278
2279 const Caps &caps = context->getCaps();
2280 switch (pname)
2281 {
2282 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2283 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2284 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2285 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002287 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002288 return false;
2289 }
2290 break;
2291
2292 case GL_UNIFORM_BUFFER_START:
2293 case GL_UNIFORM_BUFFER_SIZE:
2294 case GL_UNIFORM_BUFFER_BINDING:
2295 if (index >= caps.maxUniformBufferBindings)
2296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002298 return false;
2299 }
2300 break;
Shao80957d92017-02-20 21:25:59 +08002301
Martin Radev66fb8202016-07-28 11:45:20 +03002302 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2303 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2304 if (index >= 3u)
2305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002306 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002307 return false;
2308 }
2309 break;
Shao80957d92017-02-20 21:25:59 +08002310
Jiajia Qin6eafb042016-12-27 17:04:07 +08002311 case GL_ATOMIC_COUNTER_BUFFER_START:
2312 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2313 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2314 if (context->getClientVersion() < ES_3_1)
2315 {
2316 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002317 InvalidEnum()
2318 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002319 return false;
2320 }
2321 if (index >= caps.maxAtomicCounterBufferBindings)
2322 {
2323 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002324 InvalidValue()
2325 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002326 return false;
2327 }
2328 break;
Shao80957d92017-02-20 21:25:59 +08002329
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002330 case GL_SHADER_STORAGE_BUFFER_START:
2331 case GL_SHADER_STORAGE_BUFFER_SIZE:
2332 case GL_SHADER_STORAGE_BUFFER_BINDING:
2333 if (context->getClientVersion() < ES_3_1)
2334 {
2335 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002336 InvalidEnum()
2337 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002338 return false;
2339 }
2340 if (index >= caps.maxShaderStorageBufferBindings)
2341 {
2342 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002343 InvalidValue()
2344 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002345 return false;
2346 }
2347 break;
2348
Shao80957d92017-02-20 21:25:59 +08002349 case GL_VERTEX_BINDING_BUFFER:
2350 case GL_VERTEX_BINDING_DIVISOR:
2351 case GL_VERTEX_BINDING_OFFSET:
2352 case GL_VERTEX_BINDING_STRIDE:
2353 if (context->getClientVersion() < ES_3_1)
2354 {
2355 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002356 InvalidEnum()
2357 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002358 return false;
2359 }
2360 if (index >= caps.maxVertexAttribBindings)
2361 {
2362 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 InvalidValue()
2364 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002365 return false;
2366 }
2367 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002368 case GL_SAMPLE_MASK_VALUE:
2369 if (context->getClientVersion() < ES_3_1)
2370 {
2371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2372 return false;
2373 }
2374 if (index >= caps.maxSampleMaskWords)
2375 {
2376 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2377 return false;
2378 }
2379 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002380 case GL_IMAGE_BINDING_NAME:
2381 case GL_IMAGE_BINDING_LEVEL:
2382 case GL_IMAGE_BINDING_LAYERED:
2383 case GL_IMAGE_BINDING_LAYER:
2384 case GL_IMAGE_BINDING_ACCESS:
2385 case GL_IMAGE_BINDING_FORMAT:
2386 if (context->getClientVersion() < ES_3_1)
2387 {
2388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2389 return false;
2390 }
2391 if (index >= caps.maxImageUnits)
2392 {
2393 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2394 return false;
2395 }
2396 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002397 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002399 return false;
2400 }
2401
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002402 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002403 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002404 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002405 }
2406
2407 return true;
2408}
2409
2410bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2411{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002412 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002413 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002415 return false;
2416 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002417 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002418}
2419
Geoff Langcf255ea2016-10-20 11:39:09 -07002420bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2421 GLenum target,
2422 GLuint index,
2423 GLsizei bufSize,
2424 GLsizei *length,
2425 GLint *data)
2426{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002427 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002428 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002430 return false;
2431 }
2432
2433 if (!ValidateRobustEntryPoint(context, bufSize))
2434 {
2435 return false;
2436 }
2437
2438 if (!ValidateIndexedStateQuery(context, target, index, length))
2439 {
2440 return false;
2441 }
2442
2443 if (!ValidateRobustBufferSize(context, bufSize, *length))
2444 {
2445 return false;
2446 }
2447
2448 return true;
2449}
2450
Martin Radev66fb8202016-07-28 11:45:20 +03002451bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2452{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002453 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002454 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002456 return false;
2457 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002458 return ValidateIndexedStateQuery(context, target, index, nullptr);
2459}
2460
2461bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2462 GLenum target,
2463 GLuint index,
2464 GLsizei bufSize,
2465 GLsizei *length,
2466 GLint64 *data)
2467{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002468 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002469 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002471 return false;
2472 }
2473
2474 if (!ValidateRobustEntryPoint(context, bufSize))
2475 {
2476 return false;
2477 }
2478
2479 if (!ValidateIndexedStateQuery(context, target, index, length))
2480 {
2481 return false;
2482 }
2483
2484 if (!ValidateRobustBufferSize(context, bufSize, *length))
2485 {
2486 return false;
2487 }
2488
2489 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002490}
2491
Jamie Madillb0817d12016-11-01 15:48:31 -04002492bool ValidateCopyBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002493 BufferBinding readTarget,
2494 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002495 GLintptr readOffset,
2496 GLintptr writeOffset,
2497 GLsizeiptr size)
2498{
2499 if (context->getClientMajorVersion() < 3)
2500 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002501 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002502 return false;
2503 }
2504
Corentin Walleze4477002017-12-01 14:39:58 -05002505 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002507 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002508 return false;
2509 }
2510
2511 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2512 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2513
2514 if (!readBuffer || !writeBuffer)
2515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002516 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002517 return false;
2518 }
2519
2520 // Verify that readBuffer and writeBuffer are not currently mapped
2521 if (readBuffer->isMapped() || writeBuffer->isMapped())
2522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002523 context->handleError(InvalidOperation()
2524 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002525 return false;
2526 }
2527
Jamie Madilld2f0c742016-11-02 10:34:41 -04002528 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2529 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2530 CheckedNumeric<GLintptr> checkedSize(size);
2531
2532 auto checkedReadSum = checkedReadOffset + checkedSize;
2533 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2534
2535 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2536 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2537 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002540 return false;
2541 }
2542
Jamie Madilld2f0c742016-11-02 10:34:41 -04002543 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue()
2546 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002547 return false;
2548 }
2549
Jamie Madilld2f0c742016-11-02 10:34:41 -04002550 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2551 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002553 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002554 return false;
2555 }
2556
2557 if (readBuffer == writeBuffer)
2558 {
2559 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2560 if (!checkedOffsetDiff.IsValid())
2561 {
2562 // This shold not be possible.
2563 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002564 context->handleError(InvalidValue()
2565 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002566 return false;
2567 }
2568
2569 if (checkedOffsetDiff.ValueOrDie() < size)
2570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002571 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002572 return false;
2573 }
2574 }
2575
Jamie Madillb0817d12016-11-01 15:48:31 -04002576 return true;
2577}
2578
Geoff Langc339c4e2016-11-29 10:37:36 -05002579bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2580{
2581 if (context->getClientMajorVersion() < 3)
2582 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002584 return false;
2585 }
2586
2587 switch (name)
2588 {
2589 case GL_EXTENSIONS:
2590 if (index >= context->getExtensionStringCount())
2591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002592 context->handleError(InvalidValue()
2593 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002594 return false;
2595 }
2596 break;
2597
2598 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2599 if (!context->getExtensions().requestExtension)
2600 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002601 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002602 return false;
2603 }
2604 if (index >= context->getRequestableExtensionStringCount())
2605 {
2606 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002607 InvalidValue()
2608 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002609 return false;
2610 }
2611 break;
2612
2613 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002614 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002615 return false;
2616 }
2617
2618 return true;
2619}
2620
Jamie Madille8fb6402017-02-14 17:56:40 -05002621bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2622 GLenum target,
2623 GLsizei samples,
2624 GLenum internalformat,
2625 GLsizei width,
2626 GLsizei height)
2627{
2628 if (context->getClientMajorVersion() < 3)
2629 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002631 return false;
2632 }
2633
2634 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2635 height))
2636 {
2637 return false;
2638 }
2639
2640 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
Yunchao Hec0810202018-01-22 09:48:48 +08002641 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2642 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002643 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002644 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002645 {
Yunchao Hec0810202018-01-22 09:48:48 +08002646 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2647 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2648 {
2649 context->handleError(InvalidOperation());
2650 return false;
2651 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002652 }
2653
2654 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2655 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2656 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2657 {
2658 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002659 InvalidOperation()
2660 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002661 return false;
2662 }
2663
2664 return true;
2665}
2666
Geoff Langaa086d62017-03-23 16:47:21 -04002667bool ValidateVertexAttribIPointer(ValidationContext *context,
2668 GLuint index,
2669 GLint size,
2670 GLenum type,
2671 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002672 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002673{
2674 if (context->getClientMajorVersion() < 3)
2675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002676 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002677 return false;
2678 }
2679
Shao80957d92017-02-20 21:25:59 +08002680 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002681 {
Geoff Langaa086d62017-03-23 16:47:21 -04002682 return false;
2683 }
2684
Geoff Langaa086d62017-03-23 16:47:21 -04002685 if (stride < 0)
2686 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002687 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002688 return false;
2689 }
2690
Shao80957d92017-02-20 21:25:59 +08002691 const Caps &caps = context->getCaps();
2692 if (context->getClientVersion() >= ES_3_1)
2693 {
2694 if (stride > caps.maxVertexAttribStride)
2695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002696 context->handleError(InvalidValue()
2697 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002698 return false;
2699 }
2700
2701 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2702 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2703 // validation should be inherited.
2704 if (index >= caps.maxVertexAttribBindings)
2705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002706 context->handleError(InvalidValue()
2707 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002708 return false;
2709 }
2710 }
2711
Geoff Langaa086d62017-03-23 16:47:21 -04002712 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2713 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2714 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2715 // and the pointer argument is not NULL.
2716 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002717 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002719 context
2720 ->handleError(InvalidOperation()
2721 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002722 return false;
2723 }
2724
Geoff Lang2d62ab72017-03-23 16:54:40 -04002725 if (context->getExtensions().webglCompatibility)
2726 {
2727 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2728 {
2729 return false;
2730 }
2731 }
2732
Geoff Langaa086d62017-03-23 16:47:21 -04002733 return true;
2734}
2735
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002736bool ValidateGetSynciv(Context *context,
2737 GLsync sync,
2738 GLenum pname,
2739 GLsizei bufSize,
2740 GLsizei *length,
2741 GLint *values)
2742{
2743 if (context->getClientMajorVersion() < 3)
2744 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002746 return false;
2747 }
2748
2749 if (bufSize < 0)
2750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002751 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002752 return false;
2753 }
2754
Jamie Madill70b5bb02017-08-28 13:32:37 -04002755 Sync *syncObject = context->getSync(sync);
2756 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002758 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002759 return false;
2760 }
2761
2762 switch (pname)
2763 {
2764 case GL_OBJECT_TYPE:
2765 case GL_SYNC_CONDITION:
2766 case GL_SYNC_FLAGS:
2767 case GL_SYNC_STATUS:
2768 break;
2769
2770 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002772 return false;
2773 }
2774
2775 return true;
2776}
2777
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002778bool ValidateDrawElementsInstanced(ValidationContext *context,
2779 GLenum mode,
2780 GLsizei count,
2781 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002782 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002783 GLsizei instanceCount)
2784{
2785 if (context->getClientMajorVersion() < 3)
2786 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002788 return false;
2789 }
2790
2791 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2792}
2793
Martin Radev137032d2017-07-13 10:11:12 +03002794bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2795 GLenum target,
2796 GLenum attachment,
2797 GLuint texture,
2798 GLint level,
2799 GLint baseViewIndex,
2800 GLsizei numViews)
2801{
2802
2803 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2804 numViews))
2805 {
2806 return false;
2807 }
2808
Martin Radev137032d2017-07-13 10:11:12 +03002809 if (texture != 0)
2810 {
Martin Radev14b21262017-08-25 13:54:37 +03002811 if (baseViewIndex < 0)
2812 {
2813 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2814 return false;
2815 }
2816
Martin Radev137032d2017-07-13 10:11:12 +03002817 Texture *tex = context->getTexture(texture);
2818 ASSERT(tex);
2819
2820 switch (tex->getTarget())
2821 {
2822 case GL_TEXTURE_2D_ARRAY:
2823 {
2824 const Caps &caps = context->getCaps();
2825 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2826 {
2827 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2828 "greater than "
2829 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2830 return false;
2831 }
2832 }
2833 break;
2834 default:
2835 context->handleError(InvalidOperation()
2836 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2837 return false;
2838 }
2839
2840 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2841 {
2842 return false;
2843 }
2844 }
2845
2846 return true;
2847}
2848
2849bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2850 GLenum target,
2851 GLenum attachment,
2852 GLuint texture,
2853 GLint level,
2854 GLsizei numViews,
2855 const GLint *viewportOffsets)
2856{
2857 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2858 numViews))
2859 {
2860 return false;
2861 }
2862
Martin Radev137032d2017-07-13 10:11:12 +03002863 if (texture != 0)
2864 {
Martin Radev14b21262017-08-25 13:54:37 +03002865 const GLsizei numViewportOffsetValues = numViews * 2;
2866 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2867 {
2868 if (viewportOffsets[i] < 0)
2869 {
2870 context->handleError(InvalidValue()
2871 << "viewportOffsets cannot contain negative values.");
2872 return false;
2873 }
2874 }
2875
Martin Radev137032d2017-07-13 10:11:12 +03002876 Texture *tex = context->getTexture(texture);
2877 ASSERT(tex);
2878
2879 switch (tex->getTarget())
2880 {
2881 case GL_TEXTURE_2D:
2882 break;
2883 default:
2884 context->handleError(InvalidOperation()
2885 << "Texture's target must be GL_TEXTURE_2D.");
2886 return false;
2887 }
2888
2889 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2890 {
2891 return false;
2892 }
2893 }
2894
2895 return true;
2896}
2897
Jamie Madillff325f12017-08-26 15:06:05 -04002898bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2899{
2900 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2901}
2902
2903bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2904{
2905 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2906}
2907
2908bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2909{
2910 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2911}
2912
2913bool ValidateUniform4ui(Context *context,
2914 GLint location,
2915 GLuint v0,
2916 GLuint v1,
2917 GLuint v2,
2918 GLuint v3)
2919{
2920 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2921}
2922
2923bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2924{
2925 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2926}
2927
2928bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2929{
2930 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2931}
2932
2933bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2934{
2935 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2936}
2937
2938bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2939{
2940 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2941}
2942
Jamie Madillf0e04492017-08-26 15:28:42 -04002943bool ValidateIsQuery(Context *context, GLuint id)
2944{
2945 if (context->getClientMajorVersion() < 3)
2946 {
2947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2948 return false;
2949 }
2950
2951 return true;
2952}
2953
Jamie Madillc8c95812017-08-26 18:40:09 -04002954bool ValidateUniformMatrix2x3fv(Context *context,
2955 GLint location,
2956 GLsizei count,
2957 GLboolean transpose,
2958 const GLfloat *value)
2959{
2960 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2961}
2962
2963bool ValidateUniformMatrix3x2fv(Context *context,
2964 GLint location,
2965 GLsizei count,
2966 GLboolean transpose,
2967 const GLfloat *value)
2968{
2969 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2970}
2971
2972bool ValidateUniformMatrix2x4fv(Context *context,
2973 GLint location,
2974 GLsizei count,
2975 GLboolean transpose,
2976 const GLfloat *value)
2977{
2978 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2979}
2980
2981bool ValidateUniformMatrix4x2fv(Context *context,
2982 GLint location,
2983 GLsizei count,
2984 GLboolean transpose,
2985 const GLfloat *value)
2986{
2987 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2988}
2989
2990bool ValidateUniformMatrix3x4fv(Context *context,
2991 GLint location,
2992 GLsizei count,
2993 GLboolean transpose,
2994 const GLfloat *value)
2995{
2996 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2997}
2998
2999bool ValidateUniformMatrix4x3fv(Context *context,
3000 GLint location,
3001 GLsizei count,
3002 GLboolean transpose,
3003 const GLfloat *value)
3004{
3005 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3006}
3007
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003008bool ValidateEndTransformFeedback(Context *context)
3009{
3010 if (context->getClientMajorVersion() < 3)
3011 {
3012 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3013 return false;
3014 }
3015
3016 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3017 ASSERT(transformFeedback != nullptr);
3018
3019 if (!transformFeedback->isActive())
3020 {
3021 context->handleError(InvalidOperation());
3022 return false;
3023 }
3024
3025 return true;
3026}
3027
3028bool ValidateTransformFeedbackVaryings(Context *context,
3029 GLuint program,
3030 GLsizei count,
3031 const GLchar *const *varyings,
3032 GLenum bufferMode)
3033{
3034 if (context->getClientMajorVersion() < 3)
3035 {
3036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3037 return false;
3038 }
3039
3040 if (count < 0)
3041 {
3042 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3043 return false;
3044 }
3045
3046 switch (bufferMode)
3047 {
3048 case GL_INTERLEAVED_ATTRIBS:
3049 break;
3050 case GL_SEPARATE_ATTRIBS:
3051 {
3052 const Caps &caps = context->getCaps();
3053 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3054 {
3055 context->handleError(InvalidValue());
3056 return false;
3057 }
3058 break;
3059 }
3060 default:
3061 context->handleError(InvalidEnum());
3062 return false;
3063 }
3064
3065 Program *programObject = GetValidProgram(context, program);
3066 if (!programObject)
3067 {
3068 return false;
3069 }
3070
3071 return true;
3072}
3073
3074bool ValidateGetTransformFeedbackVarying(Context *context,
3075 GLuint program,
3076 GLuint index,
3077 GLsizei bufSize,
3078 GLsizei *length,
3079 GLsizei *size,
3080 GLenum *type,
3081 GLchar *name)
3082{
3083 if (context->getClientMajorVersion() < 3)
3084 {
3085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3086 return false;
3087 }
3088
3089 if (bufSize < 0)
3090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3092 return false;
3093 }
3094
3095 Program *programObject = GetValidProgram(context, program);
3096 if (!programObject)
3097 {
3098 return false;
3099 }
3100
3101 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3102 {
3103 context->handleError(InvalidValue());
3104 return false;
3105 }
3106
3107 return true;
3108}
3109
3110bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3111{
3112 if (context->getClientMajorVersion() < 3)
3113 {
3114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3115 return false;
3116 }
3117
3118 switch (target)
3119 {
3120 case GL_TRANSFORM_FEEDBACK:
3121 {
3122 // Cannot bind a transform feedback object if the current one is started and not
3123 // paused (3.0.2 pg 85 section 2.14.1)
3124 TransformFeedback *curTransformFeedback =
3125 context->getGLState().getCurrentTransformFeedback();
3126 if (curTransformFeedback && curTransformFeedback->isActive() &&
3127 !curTransformFeedback->isPaused())
3128 {
3129 context->handleError(InvalidOperation());
3130 return false;
3131 }
3132
3133 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3134 // 2.14.1)
3135 if (!context->isTransformFeedbackGenerated(id))
3136 {
3137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3138 return false;
3139 }
3140 }
3141 break;
3142
3143 default:
3144 context->handleError(InvalidEnum());
3145 return false;
3146 }
3147
3148 return true;
3149}
3150
3151bool ValidateIsTransformFeedback(Context *context, GLuint id)
3152{
3153 if (context->getClientMajorVersion() < 3)
3154 {
3155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3156 return false;
3157 }
3158
3159 return true;
3160}
3161
3162bool ValidatePauseTransformFeedback(Context *context)
3163{
3164 if (context->getClientMajorVersion() < 3)
3165 {
3166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3167 return false;
3168 }
3169
3170 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3171 ASSERT(transformFeedback != nullptr);
3172
3173 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3174 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3175 {
3176 context->handleError(InvalidOperation());
3177 return false;
3178 }
3179
3180 return true;
3181}
3182
3183bool ValidateResumeTransformFeedback(Context *context)
3184{
3185 if (context->getClientMajorVersion() < 3)
3186 {
3187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3188 return false;
3189 }
3190
3191 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3192 ASSERT(transformFeedback != nullptr);
3193
3194 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3195 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3196 {
3197 context->handleError(InvalidOperation());
3198 return false;
3199 }
3200
3201 return true;
3202}
3203
Jamie Madill12e957f2017-08-26 21:42:26 -04003204bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3205{
3206 if (context->getClientMajorVersion() < 3)
3207 {
3208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3209 return false;
3210 }
3211
3212 return ValidateVertexAttribIndex(context, index);
3213}
3214
3215bool ValidateVertexAttribI4ui(Context *context,
3216 GLuint index,
3217 GLuint x,
3218 GLuint y,
3219 GLuint z,
3220 GLuint w)
3221{
3222 if (context->getClientMajorVersion() < 3)
3223 {
3224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3225 return false;
3226 }
3227
3228 return ValidateVertexAttribIndex(context, index);
3229}
3230
3231bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3232{
3233 if (context->getClientMajorVersion() < 3)
3234 {
3235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3236 return false;
3237 }
3238
3239 return ValidateVertexAttribIndex(context, index);
3240}
3241
3242bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3243{
3244 if (context->getClientMajorVersion() < 3)
3245 {
3246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3247 return false;
3248 }
3249
3250 return ValidateVertexAttribIndex(context, index);
3251}
3252
3253bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3254{
3255 if (context->getClientMajorVersion() < 3)
3256 {
3257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3258 return false;
3259 }
3260
3261 Program *programObject = GetValidProgram(context, program);
3262 if (!programObject)
3263 {
3264 return false;
3265 }
3266
3267 if (!programObject->isLinked())
3268 {
3269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3270 return false;
3271 }
3272
3273 return true;
3274}
3275
3276bool ValidateGetUniformIndices(Context *context,
3277 GLuint program,
3278 GLsizei uniformCount,
3279 const GLchar *const *uniformNames,
3280 GLuint *uniformIndices)
3281{
3282 if (context->getClientMajorVersion() < 3)
3283 {
3284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3285 return false;
3286 }
3287
3288 if (uniformCount < 0)
3289 {
3290 context->handleError(InvalidValue());
3291 return false;
3292 }
3293
3294 Program *programObject = GetValidProgram(context, program);
3295 if (!programObject)
3296 {
3297 return false;
3298 }
3299
3300 return true;
3301}
3302
3303bool ValidateGetActiveUniformsiv(Context *context,
3304 GLuint program,
3305 GLsizei uniformCount,
3306 const GLuint *uniformIndices,
3307 GLenum pname,
3308 GLint *params)
3309{
3310 if (context->getClientMajorVersion() < 3)
3311 {
3312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3313 return false;
3314 }
3315
3316 if (uniformCount < 0)
3317 {
3318 context->handleError(InvalidValue());
3319 return false;
3320 }
3321
3322 Program *programObject = GetValidProgram(context, program);
3323 if (!programObject)
3324 {
3325 return false;
3326 }
3327
3328 switch (pname)
3329 {
3330 case GL_UNIFORM_TYPE:
3331 case GL_UNIFORM_SIZE:
3332 case GL_UNIFORM_NAME_LENGTH:
3333 case GL_UNIFORM_BLOCK_INDEX:
3334 case GL_UNIFORM_OFFSET:
3335 case GL_UNIFORM_ARRAY_STRIDE:
3336 case GL_UNIFORM_MATRIX_STRIDE:
3337 case GL_UNIFORM_IS_ROW_MAJOR:
3338 break;
3339
3340 default:
3341 context->handleError(InvalidEnum());
3342 return false;
3343 }
3344
3345 if (uniformCount > programObject->getActiveUniformCount())
3346 {
3347 context->handleError(InvalidValue());
3348 return false;
3349 }
3350
3351 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3352 {
3353 const GLuint index = uniformIndices[uniformId];
3354
3355 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3356 {
3357 context->handleError(InvalidValue());
3358 return false;
3359 }
3360 }
3361
3362 return true;
3363}
3364
3365bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3366{
3367 if (context->getClientMajorVersion() < 3)
3368 {
3369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3370 return false;
3371 }
3372
3373 Program *programObject = GetValidProgram(context, program);
3374 if (!programObject)
3375 {
3376 return false;
3377 }
3378
3379 return true;
3380}
3381
3382bool ValidateGetActiveUniformBlockiv(Context *context,
3383 GLuint program,
3384 GLuint uniformBlockIndex,
3385 GLenum pname,
3386 GLint *params)
3387{
3388 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3389}
3390
3391bool ValidateGetActiveUniformBlockName(Context *context,
3392 GLuint program,
3393 GLuint uniformBlockIndex,
3394 GLsizei bufSize,
3395 GLsizei *length,
3396 GLchar *uniformBlockName)
3397{
3398 if (context->getClientMajorVersion() < 3)
3399 {
3400 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3401 return false;
3402 }
3403
3404 Program *programObject = GetValidProgram(context, program);
3405 if (!programObject)
3406 {
3407 return false;
3408 }
3409
3410 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3411 {
3412 context->handleError(InvalidValue());
3413 return false;
3414 }
3415
3416 return true;
3417}
3418
3419bool ValidateUniformBlockBinding(Context *context,
3420 GLuint program,
3421 GLuint uniformBlockIndex,
3422 GLuint uniformBlockBinding)
3423{
3424 if (context->getClientMajorVersion() < 3)
3425 {
3426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3427 return false;
3428 }
3429
3430 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3431 {
3432 context->handleError(InvalidValue());
3433 return false;
3434 }
3435
3436 Program *programObject = GetValidProgram(context, program);
3437 if (!programObject)
3438 {
3439 return false;
3440 }
3441
3442 // if never linked, there won't be any uniform blocks
3443 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3444 {
3445 context->handleError(InvalidValue());
3446 return false;
3447 }
3448
3449 return true;
3450}
3451
3452bool ValidateDrawArraysInstanced(Context *context,
3453 GLenum mode,
3454 GLint first,
3455 GLsizei count,
3456 GLsizei primcount)
3457{
3458 if (context->getClientMajorVersion() < 3)
3459 {
3460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3461 return false;
3462 }
3463
3464 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3465}
3466
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003467bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3468{
3469 if (context->getClientMajorVersion() < 3)
3470 {
3471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3472 return false;
3473 }
3474
3475 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3476 {
3477 context->handleError(InvalidEnum());
3478 return false;
3479 }
3480
3481 if (flags != 0)
3482 {
3483 context->handleError(InvalidValue());
3484 return false;
3485 }
3486
3487 return true;
3488}
3489
3490bool ValidateIsSync(Context *context, GLsync sync)
3491{
3492 if (context->getClientMajorVersion() < 3)
3493 {
3494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3495 return false;
3496 }
3497
3498 return true;
3499}
3500
3501bool ValidateDeleteSync(Context *context, GLsync sync)
3502{
3503 if (context->getClientMajorVersion() < 3)
3504 {
3505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3506 return false;
3507 }
3508
Jamie Madill70b5bb02017-08-28 13:32:37 -04003509 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003510 {
3511 context->handleError(InvalidValue());
3512 return false;
3513 }
3514
3515 return true;
3516}
3517
3518bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3519{
3520 if (context->getClientMajorVersion() < 3)
3521 {
3522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3523 return false;
3524 }
3525
3526 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3527 {
3528 context->handleError(InvalidValue());
3529 return false;
3530 }
3531
Jamie Madill70b5bb02017-08-28 13:32:37 -04003532 Sync *clientWaitSync = context->getSync(sync);
3533 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003534 {
3535 context->handleError(InvalidValue());
3536 return false;
3537 }
3538
3539 return true;
3540}
3541
3542bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3543{
3544 if (context->getClientMajorVersion() < 3)
3545 {
3546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3547 return false;
3548 }
3549
3550 if (flags != 0)
3551 {
3552 context->handleError(InvalidValue());
3553 return false;
3554 }
3555
3556 if (timeout != GL_TIMEOUT_IGNORED)
3557 {
3558 context->handleError(InvalidValue());
3559 return false;
3560 }
3561
Jamie Madill70b5bb02017-08-28 13:32:37 -04003562 Sync *waitSync = context->getSync(sync);
3563 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003564 {
3565 context->handleError(InvalidValue());
3566 return false;
3567 }
3568
3569 return true;
3570}
3571
3572bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3573{
3574 if (context->getClientMajorVersion() < 3)
3575 {
3576 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3577 return false;
3578 }
3579
3580 GLenum nativeType = GL_NONE;
3581 unsigned int numParams = 0;
3582 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3583 {
3584 return false;
3585 }
3586
3587 return true;
3588}
3589
Jamie Madill3ef140a2017-08-26 23:11:21 -04003590bool ValidateIsSampler(Context *context, GLuint sampler)
3591{
3592 if (context->getClientMajorVersion() < 3)
3593 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003595 return false;
3596 }
3597
3598 return true;
3599}
3600
3601bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3602{
3603 if (context->getClientMajorVersion() < 3)
3604 {
3605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3606 return false;
3607 }
3608
3609 if (sampler != 0 && !context->isSampler(sampler))
3610 {
3611 context->handleError(InvalidOperation());
3612 return false;
3613 }
3614
3615 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3616 {
3617 context->handleError(InvalidValue());
3618 return false;
3619 }
3620
3621 return true;
3622}
3623
3624bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3625{
3626 if (context->getClientMajorVersion() < 3)
3627 {
3628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3629 return false;
3630 }
3631
3632 return ValidateVertexAttribIndex(context, index);
3633}
3634
3635bool ValidateTexStorage2D(Context *context,
3636 GLenum target,
3637 GLsizei levels,
3638 GLenum internalformat,
3639 GLsizei width,
3640 GLsizei height)
3641{
3642 if (context->getClientMajorVersion() < 3)
3643 {
3644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3645 return false;
3646 }
3647
3648 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3649 1))
3650 {
3651 return false;
3652 }
3653
3654 return true;
3655}
3656
3657bool ValidateTexStorage3D(Context *context,
3658 GLenum target,
3659 GLsizei levels,
3660 GLenum internalformat,
3661 GLsizei width,
3662 GLsizei height,
3663 GLsizei depth)
3664{
3665 if (context->getClientMajorVersion() < 3)
3666 {
3667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3668 return false;
3669 }
3670
3671 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3672 depth))
3673 {
3674 return false;
3675 }
3676
3677 return true;
3678}
3679
Jamie Madill9696d072017-08-26 23:19:57 -04003680bool ValidateGetBufferParameteri64v(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003681 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003682 GLenum pname,
3683 GLint64 *params)
3684{
3685 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3686}
3687
3688bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3689{
3690 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3691}
3692
3693bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3694{
3695 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3696}
3697
3698bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3699{
3700 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3701}
3702
3703bool ValidateSamplerParameterfv(Context *context,
3704 GLuint sampler,
3705 GLenum pname,
3706 const GLfloat *params)
3707{
3708 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3709}
3710
3711bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3712{
3713 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3714}
3715
3716bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3717{
3718 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3719}
3720
3721bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3722{
3723 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3724}
3725
3726bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3727{
3728 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3729}
3730
3731bool ValidateGetInternalformativ(Context *context,
3732 GLenum target,
3733 GLenum internalformat,
3734 GLenum pname,
3735 GLsizei bufSize,
3736 GLint *params)
3737{
3738 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3739 nullptr);
3740}
3741
Jamie Madillc29968b2016-01-20 11:17:23 -05003742} // namespace gl