blob: 2e0c02f33cd0f110dd963df00c712d842dcc96d8 [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 Madill9c9b40a2017-04-26 16:31:57 -04001279 // Use the parameter buffer to retrieve and cache the index range.
1280 const auto &params = context->getParams<HasIndexRange>();
1281 const auto &indexRangeOpt = params.getIndexRange();
1282 if (!indexRangeOpt.valid())
1283 {
1284 // Unexpected error.
1285 return false;
1286 }
1287
1288 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001289 {
1290 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001291 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001292 return false;
1293 }
1294 return true;
1295}
1296
He Yunchaoced53ae2016-11-29 15:00:51 +08001297bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001298{
Martin Radev1be913c2016-07-11 17:59:16 +03001299 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001300 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001302 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001303 }
1304
Jamie Madill78f41802014-08-25 15:47:55 -04001305 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001306}
1307
Jamie Madillb885e572015-02-03 16:16:04 -05001308bool ValidateReadBuffer(Context *context, GLenum src)
1309{
Martin Radev1be913c2016-07-11 17:59:16 +03001310 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001311 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001313 return false;
1314 }
1315
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001316 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001317
1318 if (readFBO == nullptr)
1319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001321 return false;
1322 }
1323
1324 if (src == GL_NONE)
1325 {
1326 return true;
1327 }
1328
Olli Etuaho84c9f592016-03-09 14:37:25 +02001329 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001332 return false;
1333 }
1334
1335 if (readFBO->id() == 0)
1336 {
1337 if (src != GL_BACK)
1338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 context->handleError(
1340 InvalidOperation()
1341 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001342 return false;
1343 }
1344 }
1345 else
1346 {
1347 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1348
1349 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001352 return false;
1353 }
1354 }
1355
1356 return true;
1357}
1358
Jamie Madill86af3d22015-07-21 15:14:07 -04001359bool ValidateCompressedTexImage3D(Context *context,
1360 GLenum target,
1361 GLint level,
1362 GLenum internalformat,
1363 GLsizei width,
1364 GLsizei height,
1365 GLsizei depth,
1366 GLint border,
1367 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001368 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001369{
Martin Radev1be913c2016-07-11 17:59:16 +03001370 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001371 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001372 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001373 return false;
1374 }
1375
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001376 if (!ValidTextureTarget(context, target))
1377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001379 return false;
1380 }
1381
Jamie Madille2e406c2016-06-02 13:04:10 -04001382 // Validate image size
1383 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001386 return false;
1387 }
1388
Geoff Langca271392017-04-05 12:30:00 -04001389 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001390 if (!formatInfo.compressed)
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001393 return false;
1394 }
1395
Jeff Gilbert48590352017-11-07 16:03:38 -08001396 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001397 if (blockSizeOrErr.isError())
1398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001400 return false;
1401 }
1402 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001405 return false;
1406 }
1407
1408 // 3D texture target validation
1409 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001412 return false;
1413 }
1414
1415 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001416 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001417 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1418 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001419 {
1420 return false;
1421 }
1422
1423 return true;
1424}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001425
Corentin Wallezb2931602017-04-11 15:58:57 -04001426bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1427 GLenum target,
1428 GLint level,
1429 GLenum internalformat,
1430 GLsizei width,
1431 GLsizei height,
1432 GLsizei depth,
1433 GLint border,
1434 GLsizei imageSize,
1435 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001436 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001437{
1438 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1439 {
1440 return false;
1441 }
1442
1443 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1444 depth, border, imageSize, data);
1445}
1446
Austin Kinrossbc781f32015-10-26 09:27:38 -07001447bool ValidateBindVertexArray(Context *context, GLuint array)
1448{
Martin Radev1be913c2016-07-11 17:59:16 +03001449 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001450 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001452 return false;
1453 }
1454
1455 return ValidateBindVertexArrayBase(context, array);
1456}
1457
Jamie Madilld7576732017-08-26 18:49:50 -04001458bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001459{
Martin Radev1be913c2016-07-11 17:59:16 +03001460 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001461 {
Jamie Madilld7576732017-08-26 18:49:50 -04001462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001463 return false;
1464 }
1465
1466 return true;
1467}
Geoff Langc5629752015-12-07 16:29:04 -05001468
Jiajia Qin6eafb042016-12-27 17:04:07 +08001469static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001470 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001471 GLuint index,
1472 GLuint buffer,
1473 GLintptr offset,
1474 GLsizeiptr size)
1475{
1476 if (context->getClientMajorVersion() < 3)
1477 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001479 return false;
1480 }
1481
1482 if (buffer != 0 && offset < 0)
1483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001484 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001485 return false;
1486 }
1487
1488 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1489 !context->isBufferGenerated(buffer))
1490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001492 return false;
1493 }
1494
1495 const Caps &caps = context->getCaps();
1496 switch (target)
1497 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001498 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001499 {
1500 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidValue() << "index is greater than or equal to the "
1503 "number of TRANSFORM_FEEDBACK_BUFFER "
1504 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001505 return false;
1506 }
1507 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001510 return false;
1511 }
1512
1513 TransformFeedback *curTransformFeedback =
1514 context->getGLState().getCurrentTransformFeedback();
1515 if (curTransformFeedback && curTransformFeedback->isActive())
1516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidOperation()
1518 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1519 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001520 return false;
1521 }
1522 break;
1523 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001524 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001525 {
1526 if (index >= caps.maxUniformBufferBindings)
1527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001528 context->handleError(InvalidValue() << "index is greater than or equal to the "
1529 "number of UNIFORM_BUFFER indexed "
1530 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001531 return false;
1532 }
1533
1534 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1535 {
1536 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001537 InvalidValue()
1538 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001539 return false;
1540 }
1541 break;
1542 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001543 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001544 {
1545 if (context->getClientVersion() < ES_3_1)
1546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 context->handleError(InvalidEnum()
1548 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001549 return false;
1550 }
1551 if (index >= caps.maxAtomicCounterBufferBindings)
1552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidValue() << "index is greater than or equal to the "
1554 "number of ATOMIC_COUNTER_BUFFER "
1555 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001556 return false;
1557 }
1558 if (buffer != 0 && (offset % 4) != 0)
1559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001561 return false;
1562 }
1563 break;
1564 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001565 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001566 {
1567 if (context->getClientVersion() < ES_3_1)
1568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001569 context->handleError(InvalidEnum()
1570 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001571 return false;
1572 }
1573 if (index >= caps.maxShaderStorageBufferBindings)
1574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001575 context->handleError(InvalidValue() << "index is greater than or equal to the "
1576 "number of SHADER_STORAGE_BUFFER "
1577 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001578 return false;
1579 }
1580 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidValue() << "offset must be multiple of value of "
1583 "SHADER_STORAGE_BUFFER_OFFSET_"
1584 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001585 return false;
1586 }
1587 break;
1588 }
1589 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001590 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001591 return false;
1592 }
1593
1594 return true;
1595}
1596
Corentin Wallez336129f2017-10-17 15:55:40 -04001597bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001598{
1599 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1600}
1601
1602bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001603 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001604 GLuint index,
1605 GLuint buffer,
1606 GLintptr offset,
1607 GLsizeiptr size)
1608{
1609 if (buffer != 0 && size <= 0)
1610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001611 context->handleError(InvalidValue()
1612 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001613 return false;
1614 }
1615 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1616}
1617
Geoff Langc5629752015-12-07 16:29:04 -05001618bool ValidateProgramBinary(Context *context,
1619 GLuint program,
1620 GLenum binaryFormat,
1621 const void *binary,
1622 GLint length)
1623{
Martin Radev1be913c2016-07-11 17:59:16 +03001624 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001625 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001627 return false;
1628 }
1629
1630 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1631}
1632
1633bool ValidateGetProgramBinary(Context *context,
1634 GLuint program,
1635 GLsizei bufSize,
1636 GLsizei *length,
1637 GLenum *binaryFormat,
1638 void *binary)
1639{
Martin Radev1be913c2016-07-11 17:59:16 +03001640 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001641 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001643 return false;
1644 }
1645
1646 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1647}
1648
Olli Etuahof0fee072016-03-30 15:11:58 +03001649bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001650{
Martin Radev1be913c2016-07-11 17:59:16 +03001651 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001654 return false;
1655 }
1656
1657 if (GetValidProgram(context, program) == nullptr)
1658 {
1659 return false;
1660 }
1661
1662 switch (pname)
1663 {
1664 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001665 if (value != GL_FALSE && value != GL_TRUE)
1666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001667 context->handleError(InvalidValue()
1668 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001669 return false;
1670 }
Geoff Langc5629752015-12-07 16:29:04 -05001671 break;
1672
Yunchao He61afff12017-03-14 15:34:03 +08001673 case GL_PROGRAM_SEPARABLE:
1674 if (context->getClientVersion() < ES_3_1)
1675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidEnum()
1677 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001678 return false;
1679 }
1680
1681 if (value != GL_FALSE && value != GL_TRUE)
1682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001683 context->handleError(InvalidValue()
1684 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001685 return false;
1686 }
1687 break;
1688
Geoff Langc5629752015-12-07 16:29:04 -05001689 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001690 context->handleError(InvalidEnum()
1691 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001692 return false;
1693 }
1694
1695 return true;
1696}
Jamie Madillc29968b2016-01-20 11:17:23 -05001697
1698bool ValidateBlitFramebuffer(Context *context,
1699 GLint srcX0,
1700 GLint srcY0,
1701 GLint srcX1,
1702 GLint srcY1,
1703 GLint dstX0,
1704 GLint dstY0,
1705 GLint dstX1,
1706 GLint dstY1,
1707 GLbitfield mask,
1708 GLenum filter)
1709{
Martin Radev1be913c2016-07-11 17:59:16 +03001710 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001711 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001713 return false;
1714 }
1715
1716 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1717 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718}
Jamie Madillc29968b2016-01-20 11:17:23 -05001719
1720bool ValidateClearBufferiv(ValidationContext *context,
1721 GLenum buffer,
1722 GLint drawbuffer,
1723 const GLint *value)
1724{
1725 switch (buffer)
1726 {
1727 case GL_COLOR:
1728 if (drawbuffer < 0 ||
1729 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001732 return false;
1733 }
Geoff Lang76e65652017-03-27 14:58:02 -04001734 if (context->getExtensions().webglCompatibility)
1735 {
1736 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001737 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001738 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1739 {
1740 return false;
1741 }
1742 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 break;
1744
1745 case GL_STENCIL:
1746 if (drawbuffer != 0)
1747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001749 return false;
1750 }
1751 break;
1752
1753 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001754 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001755 return false;
1756 }
1757
1758 return ValidateClearBuffer(context);
1759}
1760
1761bool ValidateClearBufferuiv(ValidationContext *context,
1762 GLenum buffer,
1763 GLint drawbuffer,
1764 const GLuint *value)
1765{
1766 switch (buffer)
1767 {
1768 case GL_COLOR:
1769 if (drawbuffer < 0 ||
1770 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001772 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 return false;
1774 }
Geoff Lang76e65652017-03-27 14:58:02 -04001775 if (context->getExtensions().webglCompatibility)
1776 {
1777 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001778 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001779 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1780 {
1781 return false;
1782 }
1783 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001784 break;
1785
1786 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001788 return false;
1789 }
1790
1791 return ValidateClearBuffer(context);
1792}
1793
1794bool ValidateClearBufferfv(ValidationContext *context,
1795 GLenum buffer,
1796 GLint drawbuffer,
1797 const GLfloat *value)
1798{
1799 switch (buffer)
1800 {
1801 case GL_COLOR:
1802 if (drawbuffer < 0 ||
1803 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001805 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001806 return false;
1807 }
Geoff Lang76e65652017-03-27 14:58:02 -04001808 if (context->getExtensions().webglCompatibility)
1809 {
1810 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1811 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001812 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001813 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1814 {
1815 return false;
1816 }
1817 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001818 break;
1819
1820 case GL_DEPTH:
1821 if (drawbuffer != 0)
1822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001823 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 return false;
1825 }
1826 break;
1827
1828 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001829 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832
1833 return ValidateClearBuffer(context);
1834}
1835
1836bool ValidateClearBufferfi(ValidationContext *context,
1837 GLenum buffer,
1838 GLint drawbuffer,
1839 GLfloat depth,
1840 GLint stencil)
1841{
1842 switch (buffer)
1843 {
1844 case GL_DEPTH_STENCIL:
1845 if (drawbuffer != 0)
1846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001847 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001848 return false;
1849 }
1850 break;
1851
1852 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001853 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001854 return false;
1855 }
1856
1857 return ValidateClearBuffer(context);
1858}
1859
1860bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1861{
Martin Radev1be913c2016-07-11 17:59:16 +03001862 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001865 return false;
1866 }
1867
1868 return ValidateDrawBuffersBase(context, n, bufs);
1869}
1870
1871bool ValidateCopyTexSubImage3D(Context *context,
1872 GLenum target,
1873 GLint level,
1874 GLint xoffset,
1875 GLint yoffset,
1876 GLint zoffset,
1877 GLint x,
1878 GLint y,
1879 GLsizei width,
1880 GLsizei height)
1881{
Martin Radev1be913c2016-07-11 17:59:16 +03001882 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001883 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001885 return false;
1886 }
1887
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001888 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1889 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001890}
1891
Jamie Madill73a84962016-02-12 09:27:23 -05001892bool ValidateTexImage3D(Context *context,
1893 GLenum target,
1894 GLint level,
1895 GLint internalformat,
1896 GLsizei width,
1897 GLsizei height,
1898 GLsizei depth,
1899 GLint border,
1900 GLenum format,
1901 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001902 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001903{
Martin Radev1be913c2016-07-11 17:59:16 +03001904 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001905 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001907 return false;
1908 }
1909
1910 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001911 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001912 pixels);
1913}
1914
Geoff Langc52f6f12016-10-14 10:18:00 -04001915bool ValidateTexImage3DRobustANGLE(Context *context,
1916 GLenum target,
1917 GLint level,
1918 GLint internalformat,
1919 GLsizei width,
1920 GLsizei height,
1921 GLsizei depth,
1922 GLint border,
1923 GLenum format,
1924 GLenum type,
1925 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001926 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001927{
1928 if (context->getClientMajorVersion() < 3)
1929 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001931 return false;
1932 }
1933
1934 if (!ValidateRobustEntryPoint(context, bufSize))
1935 {
1936 return false;
1937 }
1938
1939 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1940 0, 0, width, height, depth, border, format, type,
1941 bufSize, pixels);
1942}
1943
Jamie Madill73a84962016-02-12 09:27:23 -05001944bool ValidateTexSubImage3D(Context *context,
1945 GLenum target,
1946 GLint level,
1947 GLint xoffset,
1948 GLint yoffset,
1949 GLint zoffset,
1950 GLsizei width,
1951 GLsizei height,
1952 GLsizei depth,
1953 GLenum format,
1954 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001955 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001956{
Martin Radev1be913c2016-07-11 17:59:16 +03001957 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001958 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001959 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001960 return false;
1961 }
1962
1963 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1964 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001965 -1, pixels);
1966}
1967
1968bool ValidateTexSubImage3DRobustANGLE(Context *context,
1969 GLenum target,
1970 GLint level,
1971 GLint xoffset,
1972 GLint yoffset,
1973 GLint zoffset,
1974 GLsizei width,
1975 GLsizei height,
1976 GLsizei depth,
1977 GLenum format,
1978 GLenum type,
1979 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001980 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001981{
1982 if (context->getClientMajorVersion() < 3)
1983 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001985 return false;
1986 }
1987
1988 if (!ValidateRobustEntryPoint(context, bufSize))
1989 {
1990 return false;
1991 }
1992
1993 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1994 yoffset, zoffset, width, height, depth, 0, format, type,
1995 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001996}
1997
1998bool ValidateCompressedTexSubImage3D(Context *context,
1999 GLenum target,
2000 GLint level,
2001 GLint xoffset,
2002 GLint yoffset,
2003 GLint zoffset,
2004 GLsizei width,
2005 GLsizei height,
2006 GLsizei depth,
2007 GLenum format,
2008 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002009 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002010{
Martin Radev1be913c2016-07-11 17:59:16 +03002011 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002012 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002014 return false;
2015 }
2016
Geoff Langca271392017-04-05 12:30:00 -04002017 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002018 if (!formatInfo.compressed)
2019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002020 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002021 return false;
2022 }
2023
Jeff Gilbert48590352017-11-07 16:03:38 -08002024 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002025 if (blockSizeOrErr.isError())
2026 {
2027 context->handleError(blockSizeOrErr.getError());
2028 return false;
2029 }
2030 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002032 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002033 return false;
2034 }
2035
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002036 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2037 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2038 -1, data))
2039 {
2040 return false;
2041 }
2042
Jamie Madill73a84962016-02-12 09:27:23 -05002043 if (!data)
2044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002045 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002046 return false;
2047 }
2048
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002049 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002050}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002051
Corentin Wallezb2931602017-04-11 15:58:57 -04002052bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2053 GLenum target,
2054 GLint level,
2055 GLint xoffset,
2056 GLint yoffset,
2057 GLint zoffset,
2058 GLsizei width,
2059 GLsizei height,
2060 GLsizei depth,
2061 GLenum format,
2062 GLsizei imageSize,
2063 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002064 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002065{
2066 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2067 {
2068 return false;
2069 }
2070
2071 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2072 height, depth, format, imageSize, data);
2073}
Jamie Madill73a84962016-02-12 09:27:23 -05002074
Olli Etuaho41997e72016-03-10 13:38:39 +02002075bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2076{
2077 return ValidateGenOrDeleteES3(context, n);
2078}
2079
2080bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2081{
2082 return ValidateGenOrDeleteES3(context, n);
2083}
2084
2085bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2086{
2087 return ValidateGenOrDeleteCountES3(context, count);
2088}
2089
2090bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2091{
2092 return ValidateGenOrDeleteCountES3(context, count);
2093}
2094
2095bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2096{
2097 return ValidateGenOrDeleteES3(context, n);
2098}
2099
2100bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2101{
2102 if (!ValidateGenOrDeleteES3(context, n))
2103 {
2104 return false;
2105 }
2106 for (GLint i = 0; i < n; ++i)
2107 {
2108 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2109 if (transformFeedback != nullptr && transformFeedback->isActive())
2110 {
2111 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context->handleError(InvalidOperation()
2113 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002114 return false;
2115 }
2116 }
2117 return true;
2118}
2119
2120bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2121{
2122 return ValidateGenOrDeleteES3(context, n);
2123}
2124
2125bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2126{
2127 return ValidateGenOrDeleteES3(context, n);
2128}
2129
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002130bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2131{
Martin Radev1be913c2016-07-11 17:59:16 +03002132 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002133 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002135 return false;
2136 }
2137 switch (primitiveMode)
2138 {
2139 case GL_TRIANGLES:
2140 case GL_LINES:
2141 case GL_POINTS:
2142 break;
2143
2144 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002145 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002146 return false;
2147 }
2148
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002149 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002150 ASSERT(transformFeedback != nullptr);
2151
2152 if (transformFeedback->isActive())
2153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002154 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002155 return false;
2156 }
Geoff Lang79f71042017-08-14 16:43:43 -04002157
2158 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2159 {
2160 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2161 if (buffer.get() && buffer->isMapped())
2162 {
2163 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2164 return false;
2165 }
2166 }
2167
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002168 Program *program = context->getGLState().getProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002169
2170 if (!program)
2171 {
2172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2173 return false;
2174 }
2175
2176 if (program->getTransformFeedbackVaryingCount() == 0)
2177 {
2178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2179 return false;
2180 }
2181
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002182 return true;
2183}
2184
Corentin Wallez336129f2017-10-17 15:55:40 -04002185bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002186{
Geoff Lang496c02d2016-10-20 11:38:11 -07002187 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2188}
2189
2190bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002191 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002192 GLenum pname,
2193 GLsizei bufSize,
2194 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002195 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002196{
2197 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002198 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002199 return false;
2200 }
2201
Geoff Lang496c02d2016-10-20 11:38:11 -07002202 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2203 {
2204 return false;
2205 }
2206
2207 if (!ValidateRobustBufferSize(context, bufSize, *length))
2208 {
2209 return false;
2210 }
2211
2212 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002213}
2214
Corentin Wallez336129f2017-10-17 15:55:40 -04002215bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002216{
Martin Radev1be913c2016-07-11 17:59:16 +03002217 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002218 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002220 return false;
2221 }
2222
2223 return ValidateUnmapBufferBase(context, target);
2224}
2225
2226bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002227 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002228 GLintptr offset,
2229 GLsizeiptr length,
2230 GLbitfield access)
2231{
Martin Radev1be913c2016-07-11 17:59:16 +03002232 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002233 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002235 return false;
2236 }
2237
2238 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2239}
2240
2241bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002242 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002243 GLintptr offset,
2244 GLsizeiptr length)
2245{
Martin Radev1be913c2016-07-11 17:59:16 +03002246 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002247 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002249 return false;
2250 }
2251
2252 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2253}
2254
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002255bool ValidateIndexedStateQuery(ValidationContext *context,
2256 GLenum pname,
2257 GLuint index,
2258 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002259{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002260 if (length)
2261 {
2262 *length = 0;
2263 }
2264
Martin Radev66fb8202016-07-28 11:45:20 +03002265 GLenum nativeType;
2266 unsigned int numParams;
2267 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002269 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002270 return false;
2271 }
2272
2273 const Caps &caps = context->getCaps();
2274 switch (pname)
2275 {
2276 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2277 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2278 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2279 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002281 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002282 return false;
2283 }
2284 break;
2285
2286 case GL_UNIFORM_BUFFER_START:
2287 case GL_UNIFORM_BUFFER_SIZE:
2288 case GL_UNIFORM_BUFFER_BINDING:
2289 if (index >= caps.maxUniformBufferBindings)
2290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002291 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002292 return false;
2293 }
2294 break;
Shao80957d92017-02-20 21:25:59 +08002295
Martin Radev66fb8202016-07-28 11:45:20 +03002296 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2297 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2298 if (index >= 3u)
2299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002300 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002301 return false;
2302 }
2303 break;
Shao80957d92017-02-20 21:25:59 +08002304
Jiajia Qin6eafb042016-12-27 17:04:07 +08002305 case GL_ATOMIC_COUNTER_BUFFER_START:
2306 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2307 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2308 if (context->getClientVersion() < ES_3_1)
2309 {
2310 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002311 InvalidEnum()
2312 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002313 return false;
2314 }
2315 if (index >= caps.maxAtomicCounterBufferBindings)
2316 {
2317 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002318 InvalidValue()
2319 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002320 return false;
2321 }
2322 break;
Shao80957d92017-02-20 21:25:59 +08002323
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002324 case GL_SHADER_STORAGE_BUFFER_START:
2325 case GL_SHADER_STORAGE_BUFFER_SIZE:
2326 case GL_SHADER_STORAGE_BUFFER_BINDING:
2327 if (context->getClientVersion() < ES_3_1)
2328 {
2329 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002330 InvalidEnum()
2331 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002332 return false;
2333 }
2334 if (index >= caps.maxShaderStorageBufferBindings)
2335 {
2336 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002337 InvalidValue()
2338 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002339 return false;
2340 }
2341 break;
2342
Shao80957d92017-02-20 21:25:59 +08002343 case GL_VERTEX_BINDING_BUFFER:
2344 case GL_VERTEX_BINDING_DIVISOR:
2345 case GL_VERTEX_BINDING_OFFSET:
2346 case GL_VERTEX_BINDING_STRIDE:
2347 if (context->getClientVersion() < ES_3_1)
2348 {
2349 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002350 InvalidEnum()
2351 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002352 return false;
2353 }
2354 if (index >= caps.maxVertexAttribBindings)
2355 {
2356 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002357 InvalidValue()
2358 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002359 return false;
2360 }
2361 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002362 case GL_SAMPLE_MASK_VALUE:
2363 if (context->getClientVersion() < ES_3_1)
2364 {
2365 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2366 return false;
2367 }
2368 if (index >= caps.maxSampleMaskWords)
2369 {
2370 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2371 return false;
2372 }
2373 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002374 case GL_IMAGE_BINDING_NAME:
2375 case GL_IMAGE_BINDING_LEVEL:
2376 case GL_IMAGE_BINDING_LAYERED:
2377 case GL_IMAGE_BINDING_LAYER:
2378 case GL_IMAGE_BINDING_ACCESS:
2379 case GL_IMAGE_BINDING_FORMAT:
2380 if (context->getClientVersion() < ES_3_1)
2381 {
2382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2383 return false;
2384 }
2385 if (index >= caps.maxImageUnits)
2386 {
2387 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2388 return false;
2389 }
2390 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002391 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002393 return false;
2394 }
2395
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002396 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002397 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002398 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002399 }
2400
2401 return true;
2402}
2403
2404bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2405{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002406 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002407 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002409 return false;
2410 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002411 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002412}
2413
Geoff Langcf255ea2016-10-20 11:39:09 -07002414bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2415 GLenum target,
2416 GLuint index,
2417 GLsizei bufSize,
2418 GLsizei *length,
2419 GLint *data)
2420{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002421 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002422 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002423 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002424 return false;
2425 }
2426
2427 if (!ValidateRobustEntryPoint(context, bufSize))
2428 {
2429 return false;
2430 }
2431
2432 if (!ValidateIndexedStateQuery(context, target, index, length))
2433 {
2434 return false;
2435 }
2436
2437 if (!ValidateRobustBufferSize(context, bufSize, *length))
2438 {
2439 return false;
2440 }
2441
2442 return true;
2443}
2444
Martin Radev66fb8202016-07-28 11:45:20 +03002445bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2446{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002447 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002448 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002449 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002450 return false;
2451 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002452 return ValidateIndexedStateQuery(context, target, index, nullptr);
2453}
2454
2455bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2456 GLenum target,
2457 GLuint index,
2458 GLsizei bufSize,
2459 GLsizei *length,
2460 GLint64 *data)
2461{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002462 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002463 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002465 return false;
2466 }
2467
2468 if (!ValidateRobustEntryPoint(context, bufSize))
2469 {
2470 return false;
2471 }
2472
2473 if (!ValidateIndexedStateQuery(context, target, index, length))
2474 {
2475 return false;
2476 }
2477
2478 if (!ValidateRobustBufferSize(context, bufSize, *length))
2479 {
2480 return false;
2481 }
2482
2483 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002484}
2485
Jamie Madillb0817d12016-11-01 15:48:31 -04002486bool ValidateCopyBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002487 BufferBinding readTarget,
2488 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002489 GLintptr readOffset,
2490 GLintptr writeOffset,
2491 GLsizeiptr size)
2492{
2493 if (context->getClientMajorVersion() < 3)
2494 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002496 return false;
2497 }
2498
Corentin Walleze4477002017-12-01 14:39:58 -05002499 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002501 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002502 return false;
2503 }
2504
2505 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2506 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2507
2508 if (!readBuffer || !writeBuffer)
2509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002510 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002511 return false;
2512 }
2513
2514 // Verify that readBuffer and writeBuffer are not currently mapped
2515 if (readBuffer->isMapped() || writeBuffer->isMapped())
2516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002517 context->handleError(InvalidOperation()
2518 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002519 return false;
2520 }
2521
Jamie Madilld2f0c742016-11-02 10:34:41 -04002522 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2523 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2524 CheckedNumeric<GLintptr> checkedSize(size);
2525
2526 auto checkedReadSum = checkedReadOffset + checkedSize;
2527 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2528
2529 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2530 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2531 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002533 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002534 return false;
2535 }
2536
Jamie Madilld2f0c742016-11-02 10:34:41 -04002537 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidValue()
2540 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002541 return false;
2542 }
2543
Jamie Madilld2f0c742016-11-02 10:34:41 -04002544 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2545 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002547 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002548 return false;
2549 }
2550
2551 if (readBuffer == writeBuffer)
2552 {
2553 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2554 if (!checkedOffsetDiff.IsValid())
2555 {
2556 // This shold not be possible.
2557 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002558 context->handleError(InvalidValue()
2559 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002560 return false;
2561 }
2562
2563 if (checkedOffsetDiff.ValueOrDie() < size)
2564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002566 return false;
2567 }
2568 }
2569
Jamie Madillb0817d12016-11-01 15:48:31 -04002570 return true;
2571}
2572
Geoff Langc339c4e2016-11-29 10:37:36 -05002573bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2574{
2575 if (context->getClientMajorVersion() < 3)
2576 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002578 return false;
2579 }
2580
2581 switch (name)
2582 {
2583 case GL_EXTENSIONS:
2584 if (index >= context->getExtensionStringCount())
2585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002586 context->handleError(InvalidValue()
2587 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002588 return false;
2589 }
2590 break;
2591
2592 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2593 if (!context->getExtensions().requestExtension)
2594 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002596 return false;
2597 }
2598 if (index >= context->getRequestableExtensionStringCount())
2599 {
2600 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002601 InvalidValue()
2602 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002603 return false;
2604 }
2605 break;
2606
2607 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002609 return false;
2610 }
2611
2612 return true;
2613}
2614
Jamie Madille8fb6402017-02-14 17:56:40 -05002615bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2616 GLenum target,
2617 GLsizei samples,
2618 GLenum internalformat,
2619 GLsizei width,
2620 GLsizei height)
2621{
2622 if (context->getClientMajorVersion() < 3)
2623 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002624 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002625 return false;
2626 }
2627
2628 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2629 height))
2630 {
2631 return false;
2632 }
2633
2634 // 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 +08002635 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2636 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002637 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002638 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002639 {
Yunchao Hec0810202018-01-22 09:48:48 +08002640 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2641 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2642 {
2643 context->handleError(InvalidOperation());
2644 return false;
2645 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002646 }
2647
2648 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2649 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2650 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2651 {
2652 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002653 InvalidOperation()
2654 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002655 return false;
2656 }
2657
2658 return true;
2659}
2660
Geoff Langaa086d62017-03-23 16:47:21 -04002661bool ValidateVertexAttribIPointer(ValidationContext *context,
2662 GLuint index,
2663 GLint size,
2664 GLenum type,
2665 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002666 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002667{
2668 if (context->getClientMajorVersion() < 3)
2669 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002671 return false;
2672 }
2673
Shao80957d92017-02-20 21:25:59 +08002674 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002675 {
Geoff Langaa086d62017-03-23 16:47:21 -04002676 return false;
2677 }
2678
Geoff Langaa086d62017-03-23 16:47:21 -04002679 if (stride < 0)
2680 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002681 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002682 return false;
2683 }
2684
Shao80957d92017-02-20 21:25:59 +08002685 const Caps &caps = context->getCaps();
2686 if (context->getClientVersion() >= ES_3_1)
2687 {
2688 if (stride > caps.maxVertexAttribStride)
2689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002690 context->handleError(InvalidValue()
2691 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002692 return false;
2693 }
2694
2695 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2696 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2697 // validation should be inherited.
2698 if (index >= caps.maxVertexAttribBindings)
2699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002700 context->handleError(InvalidValue()
2701 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002702 return false;
2703 }
2704 }
2705
Geoff Langaa086d62017-03-23 16:47:21 -04002706 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2707 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2708 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2709 // and the pointer argument is not NULL.
2710 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04002711 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04002712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002713 context
2714 ->handleError(InvalidOperation()
2715 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002716 return false;
2717 }
2718
Geoff Lang2d62ab72017-03-23 16:54:40 -04002719 if (context->getExtensions().webglCompatibility)
2720 {
2721 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2722 {
2723 return false;
2724 }
2725 }
2726
Geoff Langaa086d62017-03-23 16:47:21 -04002727 return true;
2728}
2729
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002730bool ValidateGetSynciv(Context *context,
2731 GLsync sync,
2732 GLenum pname,
2733 GLsizei bufSize,
2734 GLsizei *length,
2735 GLint *values)
2736{
2737 if (context->getClientMajorVersion() < 3)
2738 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002740 return false;
2741 }
2742
2743 if (bufSize < 0)
2744 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002745 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002746 return false;
2747 }
2748
Jamie Madill70b5bb02017-08-28 13:32:37 -04002749 Sync *syncObject = context->getSync(sync);
2750 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002752 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002753 return false;
2754 }
2755
2756 switch (pname)
2757 {
2758 case GL_OBJECT_TYPE:
2759 case GL_SYNC_CONDITION:
2760 case GL_SYNC_FLAGS:
2761 case GL_SYNC_STATUS:
2762 break;
2763
2764 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002765 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002766 return false;
2767 }
2768
2769 return true;
2770}
2771
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002772bool ValidateDrawElementsInstanced(ValidationContext *context,
2773 GLenum mode,
2774 GLsizei count,
2775 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002776 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002777 GLsizei instanceCount)
2778{
2779 if (context->getClientMajorVersion() < 3)
2780 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002781 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002782 return false;
2783 }
2784
2785 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2786}
2787
Martin Radev137032d2017-07-13 10:11:12 +03002788bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2789 GLenum target,
2790 GLenum attachment,
2791 GLuint texture,
2792 GLint level,
2793 GLint baseViewIndex,
2794 GLsizei numViews)
2795{
2796
2797 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2798 numViews))
2799 {
2800 return false;
2801 }
2802
Martin Radev137032d2017-07-13 10:11:12 +03002803 if (texture != 0)
2804 {
Martin Radev14b21262017-08-25 13:54:37 +03002805 if (baseViewIndex < 0)
2806 {
2807 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2808 return false;
2809 }
2810
Martin Radev137032d2017-07-13 10:11:12 +03002811 Texture *tex = context->getTexture(texture);
2812 ASSERT(tex);
2813
2814 switch (tex->getTarget())
2815 {
2816 case GL_TEXTURE_2D_ARRAY:
2817 {
2818 const Caps &caps = context->getCaps();
2819 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2820 {
2821 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2822 "greater than "
2823 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2824 return false;
2825 }
2826 }
2827 break;
2828 default:
2829 context->handleError(InvalidOperation()
2830 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2831 return false;
2832 }
2833
2834 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2835 {
2836 return false;
2837 }
2838 }
2839
2840 return true;
2841}
2842
2843bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2844 GLenum target,
2845 GLenum attachment,
2846 GLuint texture,
2847 GLint level,
2848 GLsizei numViews,
2849 const GLint *viewportOffsets)
2850{
2851 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2852 numViews))
2853 {
2854 return false;
2855 }
2856
Martin Radev137032d2017-07-13 10:11:12 +03002857 if (texture != 0)
2858 {
Martin Radev14b21262017-08-25 13:54:37 +03002859 const GLsizei numViewportOffsetValues = numViews * 2;
2860 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2861 {
2862 if (viewportOffsets[i] < 0)
2863 {
2864 context->handleError(InvalidValue()
2865 << "viewportOffsets cannot contain negative values.");
2866 return false;
2867 }
2868 }
2869
Martin Radev137032d2017-07-13 10:11:12 +03002870 Texture *tex = context->getTexture(texture);
2871 ASSERT(tex);
2872
2873 switch (tex->getTarget())
2874 {
2875 case GL_TEXTURE_2D:
2876 break;
2877 default:
2878 context->handleError(InvalidOperation()
2879 << "Texture's target must be GL_TEXTURE_2D.");
2880 return false;
2881 }
2882
2883 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2884 {
2885 return false;
2886 }
2887 }
2888
2889 return true;
2890}
2891
Jamie Madillff325f12017-08-26 15:06:05 -04002892bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2893{
2894 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2895}
2896
2897bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2898{
2899 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2900}
2901
2902bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2903{
2904 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2905}
2906
2907bool ValidateUniform4ui(Context *context,
2908 GLint location,
2909 GLuint v0,
2910 GLuint v1,
2911 GLuint v2,
2912 GLuint v3)
2913{
2914 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2915}
2916
2917bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2918{
2919 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2920}
2921
2922bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2923{
2924 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2925}
2926
2927bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2928{
2929 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2930}
2931
2932bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2933{
2934 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2935}
2936
Jamie Madillf0e04492017-08-26 15:28:42 -04002937bool ValidateIsQuery(Context *context, GLuint id)
2938{
2939 if (context->getClientMajorVersion() < 3)
2940 {
2941 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2942 return false;
2943 }
2944
2945 return true;
2946}
2947
Jamie Madillc8c95812017-08-26 18:40:09 -04002948bool ValidateUniformMatrix2x3fv(Context *context,
2949 GLint location,
2950 GLsizei count,
2951 GLboolean transpose,
2952 const GLfloat *value)
2953{
2954 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2955}
2956
2957bool ValidateUniformMatrix3x2fv(Context *context,
2958 GLint location,
2959 GLsizei count,
2960 GLboolean transpose,
2961 const GLfloat *value)
2962{
2963 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2964}
2965
2966bool ValidateUniformMatrix2x4fv(Context *context,
2967 GLint location,
2968 GLsizei count,
2969 GLboolean transpose,
2970 const GLfloat *value)
2971{
2972 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2973}
2974
2975bool ValidateUniformMatrix4x2fv(Context *context,
2976 GLint location,
2977 GLsizei count,
2978 GLboolean transpose,
2979 const GLfloat *value)
2980{
2981 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2982}
2983
2984bool ValidateUniformMatrix3x4fv(Context *context,
2985 GLint location,
2986 GLsizei count,
2987 GLboolean transpose,
2988 const GLfloat *value)
2989{
2990 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2991}
2992
2993bool ValidateUniformMatrix4x3fv(Context *context,
2994 GLint location,
2995 GLsizei count,
2996 GLboolean transpose,
2997 const GLfloat *value)
2998{
2999 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3000}
3001
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003002bool ValidateEndTransformFeedback(Context *context)
3003{
3004 if (context->getClientMajorVersion() < 3)
3005 {
3006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3007 return false;
3008 }
3009
3010 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3011 ASSERT(transformFeedback != nullptr);
3012
3013 if (!transformFeedback->isActive())
3014 {
3015 context->handleError(InvalidOperation());
3016 return false;
3017 }
3018
3019 return true;
3020}
3021
3022bool ValidateTransformFeedbackVaryings(Context *context,
3023 GLuint program,
3024 GLsizei count,
3025 const GLchar *const *varyings,
3026 GLenum bufferMode)
3027{
3028 if (context->getClientMajorVersion() < 3)
3029 {
3030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3031 return false;
3032 }
3033
3034 if (count < 0)
3035 {
3036 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3037 return false;
3038 }
3039
3040 switch (bufferMode)
3041 {
3042 case GL_INTERLEAVED_ATTRIBS:
3043 break;
3044 case GL_SEPARATE_ATTRIBS:
3045 {
3046 const Caps &caps = context->getCaps();
3047 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3048 {
3049 context->handleError(InvalidValue());
3050 return false;
3051 }
3052 break;
3053 }
3054 default:
3055 context->handleError(InvalidEnum());
3056 return false;
3057 }
3058
3059 Program *programObject = GetValidProgram(context, program);
3060 if (!programObject)
3061 {
3062 return false;
3063 }
3064
3065 return true;
3066}
3067
3068bool ValidateGetTransformFeedbackVarying(Context *context,
3069 GLuint program,
3070 GLuint index,
3071 GLsizei bufSize,
3072 GLsizei *length,
3073 GLsizei *size,
3074 GLenum *type,
3075 GLchar *name)
3076{
3077 if (context->getClientMajorVersion() < 3)
3078 {
3079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3080 return false;
3081 }
3082
3083 if (bufSize < 0)
3084 {
3085 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3086 return false;
3087 }
3088
3089 Program *programObject = GetValidProgram(context, program);
3090 if (!programObject)
3091 {
3092 return false;
3093 }
3094
3095 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3096 {
3097 context->handleError(InvalidValue());
3098 return false;
3099 }
3100
3101 return true;
3102}
3103
3104bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3105{
3106 if (context->getClientMajorVersion() < 3)
3107 {
3108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3109 return false;
3110 }
3111
3112 switch (target)
3113 {
3114 case GL_TRANSFORM_FEEDBACK:
3115 {
3116 // Cannot bind a transform feedback object if the current one is started and not
3117 // paused (3.0.2 pg 85 section 2.14.1)
3118 TransformFeedback *curTransformFeedback =
3119 context->getGLState().getCurrentTransformFeedback();
3120 if (curTransformFeedback && curTransformFeedback->isActive() &&
3121 !curTransformFeedback->isPaused())
3122 {
3123 context->handleError(InvalidOperation());
3124 return false;
3125 }
3126
3127 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3128 // 2.14.1)
3129 if (!context->isTransformFeedbackGenerated(id))
3130 {
3131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3132 return false;
3133 }
3134 }
3135 break;
3136
3137 default:
3138 context->handleError(InvalidEnum());
3139 return false;
3140 }
3141
3142 return true;
3143}
3144
3145bool ValidateIsTransformFeedback(Context *context, GLuint id)
3146{
3147 if (context->getClientMajorVersion() < 3)
3148 {
3149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3150 return false;
3151 }
3152
3153 return true;
3154}
3155
3156bool ValidatePauseTransformFeedback(Context *context)
3157{
3158 if (context->getClientMajorVersion() < 3)
3159 {
3160 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3161 return false;
3162 }
3163
3164 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3165 ASSERT(transformFeedback != nullptr);
3166
3167 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3168 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3169 {
3170 context->handleError(InvalidOperation());
3171 return false;
3172 }
3173
3174 return true;
3175}
3176
3177bool ValidateResumeTransformFeedback(Context *context)
3178{
3179 if (context->getClientMajorVersion() < 3)
3180 {
3181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3182 return false;
3183 }
3184
3185 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3186 ASSERT(transformFeedback != nullptr);
3187
3188 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3189 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3190 {
3191 context->handleError(InvalidOperation());
3192 return false;
3193 }
3194
3195 return true;
3196}
3197
Jamie Madill12e957f2017-08-26 21:42:26 -04003198bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3199{
3200 if (context->getClientMajorVersion() < 3)
3201 {
3202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3203 return false;
3204 }
3205
3206 return ValidateVertexAttribIndex(context, index);
3207}
3208
3209bool ValidateVertexAttribI4ui(Context *context,
3210 GLuint index,
3211 GLuint x,
3212 GLuint y,
3213 GLuint z,
3214 GLuint w)
3215{
3216 if (context->getClientMajorVersion() < 3)
3217 {
3218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3219 return false;
3220 }
3221
3222 return ValidateVertexAttribIndex(context, index);
3223}
3224
3225bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3226{
3227 if (context->getClientMajorVersion() < 3)
3228 {
3229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3230 return false;
3231 }
3232
3233 return ValidateVertexAttribIndex(context, index);
3234}
3235
3236bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3237{
3238 if (context->getClientMajorVersion() < 3)
3239 {
3240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3241 return false;
3242 }
3243
3244 return ValidateVertexAttribIndex(context, index);
3245}
3246
3247bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3248{
3249 if (context->getClientMajorVersion() < 3)
3250 {
3251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3252 return false;
3253 }
3254
3255 Program *programObject = GetValidProgram(context, program);
3256 if (!programObject)
3257 {
3258 return false;
3259 }
3260
3261 if (!programObject->isLinked())
3262 {
3263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3264 return false;
3265 }
3266
3267 return true;
3268}
3269
3270bool ValidateGetUniformIndices(Context *context,
3271 GLuint program,
3272 GLsizei uniformCount,
3273 const GLchar *const *uniformNames,
3274 GLuint *uniformIndices)
3275{
3276 if (context->getClientMajorVersion() < 3)
3277 {
3278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3279 return false;
3280 }
3281
3282 if (uniformCount < 0)
3283 {
3284 context->handleError(InvalidValue());
3285 return false;
3286 }
3287
3288 Program *programObject = GetValidProgram(context, program);
3289 if (!programObject)
3290 {
3291 return false;
3292 }
3293
3294 return true;
3295}
3296
3297bool ValidateGetActiveUniformsiv(Context *context,
3298 GLuint program,
3299 GLsizei uniformCount,
3300 const GLuint *uniformIndices,
3301 GLenum pname,
3302 GLint *params)
3303{
3304 if (context->getClientMajorVersion() < 3)
3305 {
3306 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3307 return false;
3308 }
3309
3310 if (uniformCount < 0)
3311 {
3312 context->handleError(InvalidValue());
3313 return false;
3314 }
3315
3316 Program *programObject = GetValidProgram(context, program);
3317 if (!programObject)
3318 {
3319 return false;
3320 }
3321
3322 switch (pname)
3323 {
3324 case GL_UNIFORM_TYPE:
3325 case GL_UNIFORM_SIZE:
3326 case GL_UNIFORM_NAME_LENGTH:
3327 case GL_UNIFORM_BLOCK_INDEX:
3328 case GL_UNIFORM_OFFSET:
3329 case GL_UNIFORM_ARRAY_STRIDE:
3330 case GL_UNIFORM_MATRIX_STRIDE:
3331 case GL_UNIFORM_IS_ROW_MAJOR:
3332 break;
3333
3334 default:
3335 context->handleError(InvalidEnum());
3336 return false;
3337 }
3338
3339 if (uniformCount > programObject->getActiveUniformCount())
3340 {
3341 context->handleError(InvalidValue());
3342 return false;
3343 }
3344
3345 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3346 {
3347 const GLuint index = uniformIndices[uniformId];
3348
3349 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3350 {
3351 context->handleError(InvalidValue());
3352 return false;
3353 }
3354 }
3355
3356 return true;
3357}
3358
3359bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3360{
3361 if (context->getClientMajorVersion() < 3)
3362 {
3363 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3364 return false;
3365 }
3366
3367 Program *programObject = GetValidProgram(context, program);
3368 if (!programObject)
3369 {
3370 return false;
3371 }
3372
3373 return true;
3374}
3375
3376bool ValidateGetActiveUniformBlockiv(Context *context,
3377 GLuint program,
3378 GLuint uniformBlockIndex,
3379 GLenum pname,
3380 GLint *params)
3381{
3382 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3383}
3384
3385bool ValidateGetActiveUniformBlockName(Context *context,
3386 GLuint program,
3387 GLuint uniformBlockIndex,
3388 GLsizei bufSize,
3389 GLsizei *length,
3390 GLchar *uniformBlockName)
3391{
3392 if (context->getClientMajorVersion() < 3)
3393 {
3394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3395 return false;
3396 }
3397
3398 Program *programObject = GetValidProgram(context, program);
3399 if (!programObject)
3400 {
3401 return false;
3402 }
3403
3404 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3405 {
3406 context->handleError(InvalidValue());
3407 return false;
3408 }
3409
3410 return true;
3411}
3412
3413bool ValidateUniformBlockBinding(Context *context,
3414 GLuint program,
3415 GLuint uniformBlockIndex,
3416 GLuint uniformBlockBinding)
3417{
3418 if (context->getClientMajorVersion() < 3)
3419 {
3420 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3421 return false;
3422 }
3423
3424 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3425 {
3426 context->handleError(InvalidValue());
3427 return false;
3428 }
3429
3430 Program *programObject = GetValidProgram(context, program);
3431 if (!programObject)
3432 {
3433 return false;
3434 }
3435
3436 // if never linked, there won't be any uniform blocks
3437 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3438 {
3439 context->handleError(InvalidValue());
3440 return false;
3441 }
3442
3443 return true;
3444}
3445
3446bool ValidateDrawArraysInstanced(Context *context,
3447 GLenum mode,
3448 GLint first,
3449 GLsizei count,
3450 GLsizei primcount)
3451{
3452 if (context->getClientMajorVersion() < 3)
3453 {
3454 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3455 return false;
3456 }
3457
3458 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3459}
3460
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003461bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3462{
3463 if (context->getClientMajorVersion() < 3)
3464 {
3465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3466 return false;
3467 }
3468
3469 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3470 {
3471 context->handleError(InvalidEnum());
3472 return false;
3473 }
3474
3475 if (flags != 0)
3476 {
3477 context->handleError(InvalidValue());
3478 return false;
3479 }
3480
3481 return true;
3482}
3483
3484bool ValidateIsSync(Context *context, GLsync sync)
3485{
3486 if (context->getClientMajorVersion() < 3)
3487 {
3488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3489 return false;
3490 }
3491
3492 return true;
3493}
3494
3495bool ValidateDeleteSync(Context *context, GLsync sync)
3496{
3497 if (context->getClientMajorVersion() < 3)
3498 {
3499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3500 return false;
3501 }
3502
Jamie Madill70b5bb02017-08-28 13:32:37 -04003503 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003504 {
3505 context->handleError(InvalidValue());
3506 return false;
3507 }
3508
3509 return true;
3510}
3511
3512bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3513{
3514 if (context->getClientMajorVersion() < 3)
3515 {
3516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3517 return false;
3518 }
3519
3520 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3521 {
3522 context->handleError(InvalidValue());
3523 return false;
3524 }
3525
Jamie Madill70b5bb02017-08-28 13:32:37 -04003526 Sync *clientWaitSync = context->getSync(sync);
3527 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003528 {
3529 context->handleError(InvalidValue());
3530 return false;
3531 }
3532
3533 return true;
3534}
3535
3536bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3537{
3538 if (context->getClientMajorVersion() < 3)
3539 {
3540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3541 return false;
3542 }
3543
3544 if (flags != 0)
3545 {
3546 context->handleError(InvalidValue());
3547 return false;
3548 }
3549
3550 if (timeout != GL_TIMEOUT_IGNORED)
3551 {
3552 context->handleError(InvalidValue());
3553 return false;
3554 }
3555
Jamie Madill70b5bb02017-08-28 13:32:37 -04003556 Sync *waitSync = context->getSync(sync);
3557 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003558 {
3559 context->handleError(InvalidValue());
3560 return false;
3561 }
3562
3563 return true;
3564}
3565
3566bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3567{
3568 if (context->getClientMajorVersion() < 3)
3569 {
3570 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3571 return false;
3572 }
3573
3574 GLenum nativeType = GL_NONE;
3575 unsigned int numParams = 0;
3576 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3577 {
3578 return false;
3579 }
3580
3581 return true;
3582}
3583
Jamie Madill3ef140a2017-08-26 23:11:21 -04003584bool ValidateIsSampler(Context *context, GLuint sampler)
3585{
3586 if (context->getClientMajorVersion() < 3)
3587 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003588 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003589 return false;
3590 }
3591
3592 return true;
3593}
3594
3595bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3596{
3597 if (context->getClientMajorVersion() < 3)
3598 {
3599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3600 return false;
3601 }
3602
3603 if (sampler != 0 && !context->isSampler(sampler))
3604 {
3605 context->handleError(InvalidOperation());
3606 return false;
3607 }
3608
3609 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3610 {
3611 context->handleError(InvalidValue());
3612 return false;
3613 }
3614
3615 return true;
3616}
3617
3618bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3619{
3620 if (context->getClientMajorVersion() < 3)
3621 {
3622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3623 return false;
3624 }
3625
3626 return ValidateVertexAttribIndex(context, index);
3627}
3628
3629bool ValidateTexStorage2D(Context *context,
3630 GLenum target,
3631 GLsizei levels,
3632 GLenum internalformat,
3633 GLsizei width,
3634 GLsizei height)
3635{
3636 if (context->getClientMajorVersion() < 3)
3637 {
3638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3639 return false;
3640 }
3641
3642 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3643 1))
3644 {
3645 return false;
3646 }
3647
3648 return true;
3649}
3650
3651bool ValidateTexStorage3D(Context *context,
3652 GLenum target,
3653 GLsizei levels,
3654 GLenum internalformat,
3655 GLsizei width,
3656 GLsizei height,
3657 GLsizei depth)
3658{
3659 if (context->getClientMajorVersion() < 3)
3660 {
3661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3662 return false;
3663 }
3664
3665 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3666 depth))
3667 {
3668 return false;
3669 }
3670
3671 return true;
3672}
3673
Jamie Madill9696d072017-08-26 23:19:57 -04003674bool ValidateGetBufferParameteri64v(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003675 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04003676 GLenum pname,
3677 GLint64 *params)
3678{
3679 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3680}
3681
3682bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3683{
3684 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3685}
3686
3687bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3688{
3689 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3690}
3691
3692bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3693{
3694 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3695}
3696
3697bool ValidateSamplerParameterfv(Context *context,
3698 GLuint sampler,
3699 GLenum pname,
3700 const GLfloat *params)
3701{
3702 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3703}
3704
3705bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3706{
3707 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3708}
3709
3710bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3711{
3712 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3713}
3714
3715bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3716{
3717 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3718}
3719
3720bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3721{
3722 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3723}
3724
3725bool ValidateGetInternalformativ(Context *context,
3726 GLenum target,
3727 GLenum internalformat,
3728 GLenum pname,
3729 GLsizei bufSize,
3730 GLint *params)
3731{
3732 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3733 nullptr);
3734}
3735
Jamie Madillc29968b2016-01-20 11:17:23 -05003736} // namespace gl