blob: 37a76d3262ff7f09bec941f69453bbbcdccaac0d [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 }
365 }
366 else
367 {
368 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500370 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400371 return false;
372 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 }
374
Geoff Langeb66a6e2016-10-31 13:06:12 -0400375 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500377 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400378 return false;
379 }
380
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400381 if (target == GL_TEXTURE_3D)
382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500383 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400385 }
386 }
387 else
388 {
Geoff Langca271392017-04-05 12:30:00 -0400389 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 {
Geoff Lang5d601382014-07-22 15:14:06 -0400391 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400392 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400393 }
394
395 // Validate sub image parameters
396 if (isSubImage)
397 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500398 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500400 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400401 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 }
403
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500406 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
410 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
411 std::numeric_limits<GLsizei>::max() - yoffset < height ||
412 std::numeric_limits<GLsizei>::max() - zoffset < depth)
413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500414 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416 }
417
Geoff Langa9be0dc2014-12-17 12:34:40 -0500418 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
419 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
420 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500422 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400423 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 }
425 }
426
Geoff Langdbcced82017-06-06 15:55:54 -0400427 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
428 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
429 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400430 {
431 return false;
432 }
433
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400434 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700435 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400436 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400437 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800438 // ...data is not evenly divisible into the number of bytes needed to store in memory a
439 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400440 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400441 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400442 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400443 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400444 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
445
Geoff Langff5b2d52016-09-07 11:32:23 -0400446 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500448 context->handleError(InvalidOperation()
449 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400450 return false;
451 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400452 }
453
Jamie Madill7a5f7382014-03-05 15:01:24 -0500454 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700455 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500457 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400458 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500459 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400460 }
461
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400462 return true;
463}
464
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500465bool ValidateES3TexImage2DParameters(Context *context,
466 GLenum target,
467 GLint level,
468 GLenum internalformat,
469 bool isCompressed,
470 bool isSubImage,
471 GLint xoffset,
472 GLint yoffset,
473 GLint zoffset,
474 GLsizei width,
475 GLsizei height,
476 GLsizei depth,
477 GLint border,
478 GLenum format,
479 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400480 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400481 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500482{
483 if (!ValidTexture2DDestinationTarget(context, target))
484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500485 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500486 return false;
487 }
488
489 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
490 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400491 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500492}
493
494bool ValidateES3TexImage3DParameters(Context *context,
495 GLenum target,
496 GLint level,
497 GLenum internalformat,
498 bool isCompressed,
499 bool isSubImage,
500 GLint xoffset,
501 GLint yoffset,
502 GLint zoffset,
503 GLsizei width,
504 GLsizei height,
505 GLsizei depth,
506 GLint border,
507 GLenum format,
508 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400509 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400510 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500511{
512 if (!ValidTexture3DDestinationTarget(context, target))
513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500514 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500515 return false;
516 }
517
518 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
519 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400520 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500521}
522
Geoff Lang5d601382014-07-22 15:14:06 -0400523struct EffectiveInternalFormatInfo
524{
Jamie Madill76648fe2016-10-05 17:01:41 -0400525 GLenum effectiveFormat;
526 GLenum destFormat;
527 GLuint minRedBits;
528 GLuint maxRedBits;
529 GLuint minGreenBits;
530 GLuint maxGreenBits;
531 GLuint minBlueBits;
532 GLuint maxBlueBits;
533 GLuint minAlphaBits;
534 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400535};
536
Jamie Madill76648fe2016-10-05 17:01:41 -0400537static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
538 GLenum targetFormat,
539 const EffectiveInternalFormatInfo *list,
540 size_t size,
541 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400542{
Jamie Madill76648fe2016-10-05 17:01:41 -0400543 for (size_t curFormat = 0; curFormat < size; ++curFormat)
544 {
545 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
546 if ((formatInfo.destFormat == targetFormat) &&
547 (formatInfo.minRedBits <= srcFormat.redBits &&
548 formatInfo.maxRedBits >= srcFormat.redBits) &&
549 (formatInfo.minGreenBits <= srcFormat.greenBits &&
550 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
551 (formatInfo.minBlueBits <= srcFormat.blueBits &&
552 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
553 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
554 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
555 {
556 *outEffectiveFormat = formatInfo.effectiveFormat;
557 return true;
558 }
559 }
Geoff Lang5d601382014-07-22 15:14:06 -0400560
Jamie Madill76648fe2016-10-05 17:01:41 -0400561 *outEffectiveFormat = GL_NONE;
562 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400563}
564
Jamie Madill76648fe2016-10-05 17:01:41 -0400565bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
566 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400567{
Jamie Madill76648fe2016-10-05 17:01:41 -0400568 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
569 // Effective internal format coresponding to destination internal format and linear source
570 // buffer component sizes.
571 // | Source channel min/max sizes |
572 // Effective Internal Format | N/A | R | G | B | A |
573 // clang-format off
574 constexpr EffectiveInternalFormatInfo list[] = {
575 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
576 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
577 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
578 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
579 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
580 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
581 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
582 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
583 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
584 };
585 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400586
Jamie Madill76648fe2016-10-05 17:01:41 -0400587 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
588}
Geoff Lang5d601382014-07-22 15:14:06 -0400589
Jamie Madill76648fe2016-10-05 17:01:41 -0400590bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
591 const InternalFormat &destFormat,
592 GLenum *outEffectiveFormat)
593{
594 constexpr GLuint umax = UINT_MAX;
595
596 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
597 // Effective internal format coresponding to destination internal format andlinear source buffer
598 // component sizes.
599 // | Source channel min/max sizes |
600 // Effective Internal Format | Dest Format | R | G | B | A |
601 // clang-format off
602 constexpr EffectiveInternalFormatInfo list[] = {
603 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
604 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
605 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
606 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
607 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
608 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
609 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
610 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
611 };
612 // clang-format on
613
614 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
615 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400616}
617
He Yunchaoced53ae2016-11-29 15:00:51 +0800618static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
619 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400620 GLenum *outEffectiveFormat)
621{
Geoff Langca271392017-04-05 12:30:00 -0400622 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400623 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400624 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400625 }
626 else
627 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400628 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400629 }
Geoff Lang5d601382014-07-22 15:14:06 -0400630}
631
Corentin Wallez76287682016-04-25 09:23:38 -0400632static bool EqualOrFirstZero(GLuint first, GLuint second)
633{
634 return first == 0 || first == second;
635}
636
Geoff Langca271392017-04-05 12:30:00 -0400637static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
638 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400639 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400640{
Jamie Madill21b786b2016-11-01 17:41:31 -0400641 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400642 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400643 return false;
644 }
Geoff Lang5d601382014-07-22 15:14:06 -0400645
Jamie Madill21b786b2016-11-01 17:41:31 -0400646 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
647 // must both be signed, unsigned, or fixed point and both source and destinations
648 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
649 // conversion between fixed and floating point.
650
651 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
652 (framebufferFormatInfo.colorEncoding == GL_SRGB))
653 {
654 return false;
655 }
656
657 if (((textureFormatInfo.componentType == GL_INT) !=
658 (framebufferFormatInfo.componentType == GL_INT)) ||
659 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
660 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
661 {
662 return false;
663 }
664
665 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
666 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
667 textureFormatInfo.componentType == GL_FLOAT) &&
668 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
669 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
670 framebufferFormatInfo.componentType == GL_FLOAT))
671 {
672 return false;
673 }
674
675 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
676 // The effective internal format of the source buffer is determined with the following rules
677 // applied in order:
678 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
679 // format then the effective internal format is the source buffer's sized internal format.
680 // * If the source buffer is a texture that was created with an unsized base internal format,
681 // then the effective internal format is the source image array's effective internal
682 // format, as specified by table 3.12, which is determined from the <format> and <type>
683 // that were used when the source image array was specified by TexImage*.
684 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
685 // where Destination Internal Format matches internalformat and where the [source channel
686 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
687 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
688 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800689 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400690 if (readBufferHandle != 0)
691 {
692 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
693 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400694 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400695 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400696 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400697 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400698 else
Geoff Lang5d601382014-07-22 15:14:06 -0400699 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400700 // Renderbuffers cannot be created with an unsized internal format, so this must be an
701 // unsized-format texture. We can use the same table we use when creating textures to
702 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400703 sourceEffectiveFormat =
704 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400705 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400706 }
707 else
708 {
709 // The effective internal format must be derived from the source framebuffer's channel
710 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
711 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400712 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400713 GLenum effectiveFormat;
714 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
715 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400716 {
Geoff Langca271392017-04-05 12:30:00 -0400717 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400718 }
719 else
720 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400721 return false;
722 }
723 }
724 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
725 {
726 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400727 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400728 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
729 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
730 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
731 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
732 {
Geoff Langca271392017-04-05 12:30:00 -0400733 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400734 }
735 else
736 {
737 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400738 }
739 }
740 else
741 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400742 UNREACHABLE();
743 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400744 }
Geoff Lang5d601382014-07-22 15:14:06 -0400745 }
746
Geoff Langca271392017-04-05 12:30:00 -0400747 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400748 {
749 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
750 // sized, component sizes of the source and destination formats must exactly match if the
751 // destination format exists.
752 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
753 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
754 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
755 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
756 {
757 return false;
758 }
759 }
760
761 return true; // A conversion function exists, and no rule in the specification has precluded
762 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400763}
764
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500765bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
766 GLenum target,
767 GLint level,
768 GLenum internalformat,
769 bool isSubImage,
770 GLint xoffset,
771 GLint yoffset,
772 GLint zoffset,
773 GLint x,
774 GLint y,
775 GLsizei width,
776 GLsizei height,
777 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400778{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400779 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400780 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400781 xoffset, yoffset, zoffset, x, y, width, height, border,
782 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400783 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400786 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787
Jamie Madill51f40ec2016-06-15 14:06:00 -0400788 const auto &state = context->getGLState();
789 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
790 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400791
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400792 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500794 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400795 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400796 }
797
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400798 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500800 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400802 }
803
Jamie Madill0c8abca2016-07-22 20:21:26 -0400804 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805
806 if (isSubImage)
807 {
Geoff Langca271392017-04-05 12:30:00 -0400808 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500809 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500811 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400812 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400813 }
814 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400815 else
816 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400817 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400818 const InternalFormat &framebufferFormat = *source->getFormat().info;
819 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400820 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500822 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400823 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400824 }
825 }
826
Geoff Lang784a8fd2013-09-24 12:33:16 -0400827 // If width or height is zero, it is a no-op. Return false without setting an error.
828 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829}
830
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500831bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
832 GLenum target,
833 GLint level,
834 GLenum internalformat,
835 bool isSubImage,
836 GLint xoffset,
837 GLint yoffset,
838 GLint zoffset,
839 GLint x,
840 GLint y,
841 GLsizei width,
842 GLsizei height,
843 GLint border)
844{
845 if (!ValidTexture2DDestinationTarget(context, target))
846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500847 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500848 return false;
849 }
850
851 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
852 xoffset, yoffset, zoffset, x, y, width, height,
853 border);
854}
855
856bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
857 GLenum target,
858 GLint level,
859 GLenum internalformat,
860 bool isSubImage,
861 GLint xoffset,
862 GLint yoffset,
863 GLint zoffset,
864 GLint x,
865 GLint y,
866 GLsizei width,
867 GLsizei height,
868 GLint border)
869{
870 if (!ValidTexture3DDestinationTarget(context, target))
871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500872 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500873 return false;
874 }
875
876 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
877 xoffset, yoffset, zoffset, x, y, width, height,
878 border);
879}
880
881bool ValidateES3TexStorageParametersBase(Context *context,
882 GLenum target,
883 GLsizei levels,
884 GLenum internalformat,
885 GLsizei width,
886 GLsizei height,
887 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400888{
889 if (width < 1 || height < 1 || depth < 1 || levels < 1)
890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400892 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 }
894
Geoff Langb92c1332015-09-04 12:54:55 -0400895 GLsizei maxDim = std::max(width, height);
896 if (target != GL_TEXTURE_2D_ARRAY)
897 {
898 maxDim = std::max(maxDim, depth);
899 }
900
901 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500903 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400904 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905 }
906
Geoff Langaae65a42014-05-26 12:43:44 -0400907 const gl::Caps &caps = context->getCaps();
908
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 switch (target)
910 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800911 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 {
Geoff Langaae65a42014-05-26 12:43:44 -0400913 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
914 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918 }
919 }
920 break;
921
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400922 case GL_TEXTURE_RECTANGLE_ANGLE:
923 {
924 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
925 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
926 {
927 context->handleError(InvalidValue());
928 return false;
929 }
930 }
931 break;
932
He Yunchaoced53ae2016-11-29 15:00:51 +0800933 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 if (width != height)
936 {
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
Geoff Langaae65a42014-05-26 12:43:44 -0400941 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500943 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400944 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 }
946 }
947 break;
948
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 {
Geoff Langaae65a42014-05-26 12:43:44 -0400951 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
952 static_cast<GLuint>(height) > caps.max3DTextureSize ||
953 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500955 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400956 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957 }
958 }
959 break;
960
He Yunchaoced53ae2016-11-29 15:00:51 +0800961 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962 {
Geoff Langaae65a42014-05-26 12:43:44 -0400963 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
964 static_cast<GLuint>(height) > caps.max2DTextureSize ||
965 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500967 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400968 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 }
970 }
971 break;
972
He Yunchaoced53ae2016-11-29 15:00:51 +0800973 default:
974 UNREACHABLE();
975 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976 }
977
Geoff Lang691e58c2014-12-19 17:03:25 -0500978 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400979 if (!texture || texture->id() == 0)
980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500981 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 }
984
Geoff Lang69cce582015-09-17 13:20:36 -0400985 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500987 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 }
990
Geoff Langca271392017-04-05 12:30:00 -0400991 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400992 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500994 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 }
997
Geoff Langca271392017-04-05 12:30:00 -0400998 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 }
1003
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001004 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1005 {
1006 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1007 return false;
1008 }
1009
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 return true;
1011}
1012
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001013bool ValidateES3TexStorage2DParameters(Context *context,
1014 GLenum target,
1015 GLsizei levels,
1016 GLenum internalformat,
1017 GLsizei width,
1018 GLsizei height,
1019 GLsizei depth)
1020{
1021 if (!ValidTexture2DTarget(context, target))
1022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001024 return false;
1025 }
1026
1027 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1028 height, depth);
1029}
1030
1031bool ValidateES3TexStorage3DParameters(Context *context,
1032 GLenum target,
1033 GLsizei levels,
1034 GLenum internalformat,
1035 GLsizei width,
1036 GLsizei height,
1037 GLsizei depth)
1038{
1039 if (!ValidTexture3DTarget(context, target))
1040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001041 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001042 return false;
1043 }
1044
1045 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1046 height, depth);
1047}
1048
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001049bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1050{
Martin Radev1be913c2016-07-11 17:59:16 +03001051 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001052 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001054 return false;
1055 }
1056
1057 return ValidateBeginQueryBase(context, target, id);
1058}
1059
1060bool ValidateEndQuery(gl::Context *context, GLenum target)
1061{
Martin Radev1be913c2016-07-11 17:59:16 +03001062 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001063 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001065 return false;
1066 }
1067
1068 return ValidateEndQueryBase(context, target);
1069}
1070
1071bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1072{
Martin Radev1be913c2016-07-11 17:59:16 +03001073 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001074 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001076 return false;
1077 }
1078
Geoff Lang2186c382016-10-14 10:54:54 -04001079 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001080}
1081
1082bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1083{
Martin Radev1be913c2016-07-11 17:59:16 +03001084 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001085 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001086 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001087 return false;
1088 }
1089
Geoff Lang2186c382016-10-14 10:54:54 -04001090 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001091}
1092
He Yunchaoced53ae2016-11-29 15:00:51 +08001093bool ValidateFramebufferTextureLayer(Context *context,
1094 GLenum target,
1095 GLenum attachment,
1096 GLuint texture,
1097 GLint level,
1098 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001099{
Martin Radev1be913c2016-07-11 17:59:16 +03001100 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001101 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001104 }
1105
Jamie Madill55ec3b12014-07-03 10:38:57 -04001106 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1107 {
1108 return false;
1109 }
1110
1111 const gl::Caps &caps = context->getCaps();
1112 if (texture != 0)
1113 {
Geoff Lang23e02842017-10-17 13:24:09 -04001114 if (layer < 0)
1115 {
1116 context->handleError(InvalidValue());
1117 return false;
1118 }
1119
Jamie Madill55ec3b12014-07-03 10:38:57 -04001120 gl::Texture *tex = context->getTexture(texture);
1121 ASSERT(tex);
1122
1123 switch (tex->getTarget())
1124 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001125 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001126 {
1127 if (level > gl::log2(caps.max2DTextureSize))
1128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001129 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001130 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001131 }
1132
1133 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001135 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001137 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001138 }
1139 break;
1140
He Yunchaoced53ae2016-11-29 15:00:51 +08001141 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001142 {
1143 if (level > gl::log2(caps.max3DTextureSize))
1144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001145 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001147 }
1148
1149 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001151 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001153 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001154 }
1155 break;
1156
He Yunchaoced53ae2016-11-29 15:00:51 +08001157 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001158 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001159 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001160 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001161
Jamie Madilla3944d42016-07-22 22:13:26 -04001162 const auto &format = tex->getFormat(tex->getTarget(), level);
1163 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001165 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001166 return false;
1167 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001168 }
1169
1170 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001171}
1172
He Yunchaoced53ae2016-11-29 15:00:51 +08001173bool ValidateInvalidateFramebuffer(Context *context,
1174 GLenum target,
1175 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001176 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001177{
Martin Radev1be913c2016-07-11 17:59:16 +03001178 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001179 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001181 return false;
1182 }
1183
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 bool defaultFramebuffer = false;
1185
1186 switch (target)
1187 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001188 case GL_DRAW_FRAMEBUFFER:
1189 case GL_FRAMEBUFFER:
1190 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1191 break;
1192 case GL_READ_FRAMEBUFFER:
1193 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1194 break;
1195 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001198 }
1199
He Yunchaoced53ae2016-11-29 15:00:51 +08001200 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1201 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202}
1203
Jamie Madill3ef140a2017-08-26 23:11:21 -04001204bool ValidateInvalidateSubFramebuffer(Context *context,
1205 GLenum target,
1206 GLsizei numAttachments,
1207 const GLenum *attachments,
1208 GLint x,
1209 GLint y,
1210 GLsizei width,
1211 GLsizei height)
1212{
1213 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1214}
1215
Jamie Madillc29968b2016-01-20 11:17:23 -05001216bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001217{
Martin Radev1be913c2016-07-11 17:59:16 +03001218 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001219 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001220 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001221 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001222 }
1223
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001224 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001226 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001228 }
1229
1230 return true;
1231}
1232
Olli Etuaho71dfb362016-03-10 14:04:27 +02001233bool ValidateDrawRangeElements(Context *context,
1234 GLenum mode,
1235 GLuint start,
1236 GLuint end,
1237 GLsizei count,
1238 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001239 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001240{
Martin Radev1be913c2016-07-11 17:59:16 +03001241 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001242 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001244 return false;
1245 }
1246
1247 if (end < start)
1248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001249 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001250 return false;
1251 }
1252
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001253 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001254 {
1255 return false;
1256 }
1257
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001258 // Use the parameter buffer to retrieve and cache the index range.
1259 const auto &params = context->getParams<HasIndexRange>();
1260 const auto &indexRangeOpt = params.getIndexRange();
1261 if (!indexRangeOpt.valid())
1262 {
1263 // Unexpected error.
1264 return false;
1265 }
1266
1267 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001268 {
1269 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001271 return false;
1272 }
1273 return true;
1274}
1275
He Yunchaoced53ae2016-11-29 15:00:51 +08001276bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001277{
Martin Radev1be913c2016-07-11 17:59:16 +03001278 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001279 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001281 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001282 }
1283
Jamie Madill78f41802014-08-25 15:47:55 -04001284 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001285}
1286
Jamie Madillb885e572015-02-03 16:16:04 -05001287bool ValidateReadBuffer(Context *context, GLenum src)
1288{
Martin Radev1be913c2016-07-11 17:59:16 +03001289 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001290 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001292 return false;
1293 }
1294
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001295 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001296
1297 if (readFBO == nullptr)
1298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001299 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001300 return false;
1301 }
1302
1303 if (src == GL_NONE)
1304 {
1305 return true;
1306 }
1307
Olli Etuaho84c9f592016-03-09 14:37:25 +02001308 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001310 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001311 return false;
1312 }
1313
1314 if (readFBO->id() == 0)
1315 {
1316 if (src != GL_BACK)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(
1319 InvalidOperation()
1320 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001321 return false;
1322 }
1323 }
1324 else
1325 {
1326 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1327
1328 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001330 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001331 return false;
1332 }
1333 }
1334
1335 return true;
1336}
1337
Jamie Madill86af3d22015-07-21 15:14:07 -04001338bool ValidateCompressedTexImage3D(Context *context,
1339 GLenum target,
1340 GLint level,
1341 GLenum internalformat,
1342 GLsizei width,
1343 GLsizei height,
1344 GLsizei depth,
1345 GLint border,
1346 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001347 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001348{
Martin Radev1be913c2016-07-11 17:59:16 +03001349 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001350 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001351 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001352 return false;
1353 }
1354
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001355 if (!ValidTextureTarget(context, target))
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001358 return false;
1359 }
1360
Jamie Madille2e406c2016-06-02 13:04:10 -04001361 // Validate image size
1362 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001365 return false;
1366 }
1367
Geoff Langca271392017-04-05 12:30:00 -04001368 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001369 if (!formatInfo.compressed)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001372 return false;
1373 }
1374
Jamie Madill513558d2016-06-02 13:04:11 -04001375 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001376 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001377 if (blockSizeOrErr.isError())
1378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001380 return false;
1381 }
1382 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001385 return false;
1386 }
1387
1388 // 3D texture target validation
1389 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001392 return false;
1393 }
1394
1395 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001396 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001397 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1398 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001399 {
1400 return false;
1401 }
1402
1403 return true;
1404}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001405
Corentin Wallezb2931602017-04-11 15:58:57 -04001406bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1407 GLenum target,
1408 GLint level,
1409 GLenum internalformat,
1410 GLsizei width,
1411 GLsizei height,
1412 GLsizei depth,
1413 GLint border,
1414 GLsizei imageSize,
1415 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001416 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001417{
1418 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1419 {
1420 return false;
1421 }
1422
1423 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1424 depth, border, imageSize, data);
1425}
1426
Austin Kinrossbc781f32015-10-26 09:27:38 -07001427bool ValidateBindVertexArray(Context *context, GLuint array)
1428{
Martin Radev1be913c2016-07-11 17:59:16 +03001429 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001430 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001432 return false;
1433 }
1434
1435 return ValidateBindVertexArrayBase(context, array);
1436}
1437
Jamie Madilld7576732017-08-26 18:49:50 -04001438bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001439{
Martin Radev1be913c2016-07-11 17:59:16 +03001440 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001441 {
Jamie Madilld7576732017-08-26 18:49:50 -04001442 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001443 return false;
1444 }
1445
1446 return true;
1447}
Geoff Langc5629752015-12-07 16:29:04 -05001448
Jiajia Qin6eafb042016-12-27 17:04:07 +08001449static bool ValidateBindBufferCommon(Context *context,
1450 GLenum target,
1451 GLuint index,
1452 GLuint buffer,
1453 GLintptr offset,
1454 GLsizeiptr size)
1455{
1456 if (context->getClientMajorVersion() < 3)
1457 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001459 return false;
1460 }
1461
1462 if (buffer != 0 && offset < 0)
1463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001464 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001465 return false;
1466 }
1467
1468 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1469 !context->isBufferGenerated(buffer))
1470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001471 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001472 return false;
1473 }
1474
1475 const Caps &caps = context->getCaps();
1476 switch (target)
1477 {
1478 case GL_TRANSFORM_FEEDBACK_BUFFER:
1479 {
1480 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001482 context->handleError(InvalidValue() << "index is greater than or equal to the "
1483 "number of TRANSFORM_FEEDBACK_BUFFER "
1484 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001485 return false;
1486 }
1487 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001490 return false;
1491 }
1492
1493 TransformFeedback *curTransformFeedback =
1494 context->getGLState().getCurrentTransformFeedback();
1495 if (curTransformFeedback && curTransformFeedback->isActive())
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidOperation()
1498 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1499 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001500 return false;
1501 }
1502 break;
1503 }
1504 case GL_UNIFORM_BUFFER:
1505 {
1506 if (index >= caps.maxUniformBufferBindings)
1507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001508 context->handleError(InvalidValue() << "index is greater than or equal to the "
1509 "number of UNIFORM_BUFFER indexed "
1510 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001511 return false;
1512 }
1513
1514 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1515 {
1516 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 InvalidValue()
1518 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001519 return false;
1520 }
1521 break;
1522 }
1523 case GL_ATOMIC_COUNTER_BUFFER:
1524 {
1525 if (context->getClientVersion() < ES_3_1)
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidEnum()
1528 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001529 return false;
1530 }
1531 if (index >= caps.maxAtomicCounterBufferBindings)
1532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(InvalidValue() << "index is greater than or equal to the "
1534 "number of ATOMIC_COUNTER_BUFFER "
1535 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001536 return false;
1537 }
1538 if (buffer != 0 && (offset % 4) != 0)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001541 return false;
1542 }
1543 break;
1544 }
1545 case GL_SHADER_STORAGE_BUFFER:
1546 {
1547 if (context->getClientVersion() < ES_3_1)
1548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001549 context->handleError(InvalidEnum()
1550 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001551 return false;
1552 }
1553 if (index >= caps.maxShaderStorageBufferBindings)
1554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001555 context->handleError(InvalidValue() << "index is greater than or equal to the "
1556 "number of SHADER_STORAGE_BUFFER "
1557 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001558 return false;
1559 }
1560 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001562 context->handleError(InvalidValue() << "offset must be multiple of value of "
1563 "SHADER_STORAGE_BUFFER_OFFSET_"
1564 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001565 return false;
1566 }
1567 break;
1568 }
1569 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001571 return false;
1572 }
1573
1574 return true;
1575}
1576
1577bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1578{
1579 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1580}
1581
1582bool ValidateBindBufferRange(Context *context,
1583 GLenum target,
1584 GLuint index,
1585 GLuint buffer,
1586 GLintptr offset,
1587 GLsizeiptr size)
1588{
1589 if (buffer != 0 && size <= 0)
1590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001591 context->handleError(InvalidValue()
1592 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001593 return false;
1594 }
1595 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1596}
1597
Geoff Langc5629752015-12-07 16:29:04 -05001598bool ValidateProgramBinary(Context *context,
1599 GLuint program,
1600 GLenum binaryFormat,
1601 const void *binary,
1602 GLint length)
1603{
Martin Radev1be913c2016-07-11 17:59:16 +03001604 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001605 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001606 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001607 return false;
1608 }
1609
1610 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1611}
1612
1613bool ValidateGetProgramBinary(Context *context,
1614 GLuint program,
1615 GLsizei bufSize,
1616 GLsizei *length,
1617 GLenum *binaryFormat,
1618 void *binary)
1619{
Martin Radev1be913c2016-07-11 17:59:16 +03001620 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001621 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001623 return false;
1624 }
1625
1626 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1627}
1628
Olli Etuahof0fee072016-03-30 15:11:58 +03001629bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001630{
Martin Radev1be913c2016-07-11 17:59:16 +03001631 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001633 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001634 return false;
1635 }
1636
1637 if (GetValidProgram(context, program) == nullptr)
1638 {
1639 return false;
1640 }
1641
1642 switch (pname)
1643 {
1644 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001645 if (value != GL_FALSE && value != GL_TRUE)
1646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidValue()
1648 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001649 return false;
1650 }
Geoff Langc5629752015-12-07 16:29:04 -05001651 break;
1652
Yunchao He61afff12017-03-14 15:34:03 +08001653 case GL_PROGRAM_SEPARABLE:
1654 if (context->getClientVersion() < ES_3_1)
1655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidEnum()
1657 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001658 return false;
1659 }
1660
1661 if (value != GL_FALSE && value != GL_TRUE)
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidValue()
1664 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001665 return false;
1666 }
1667 break;
1668
Geoff Langc5629752015-12-07 16:29:04 -05001669 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidEnum()
1671 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001672 return false;
1673 }
1674
1675 return true;
1676}
Jamie Madillc29968b2016-01-20 11:17:23 -05001677
1678bool ValidateBlitFramebuffer(Context *context,
1679 GLint srcX0,
1680 GLint srcY0,
1681 GLint srcX1,
1682 GLint srcY1,
1683 GLint dstX0,
1684 GLint dstY0,
1685 GLint dstX1,
1686 GLint dstY1,
1687 GLbitfield mask,
1688 GLenum filter)
1689{
Martin Radev1be913c2016-07-11 17:59:16 +03001690 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001693 return false;
1694 }
1695
1696 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1697 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001698}
Jamie Madillc29968b2016-01-20 11:17:23 -05001699
1700bool ValidateClearBufferiv(ValidationContext *context,
1701 GLenum buffer,
1702 GLint drawbuffer,
1703 const GLint *value)
1704{
1705 switch (buffer)
1706 {
1707 case GL_COLOR:
1708 if (drawbuffer < 0 ||
1709 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001711 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001712 return false;
1713 }
Geoff Lang76e65652017-03-27 14:58:02 -04001714 if (context->getExtensions().webglCompatibility)
1715 {
1716 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001717 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001718 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1719 {
1720 return false;
1721 }
1722 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 break;
1724
1725 case GL_STENCIL:
1726 if (drawbuffer != 0)
1727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001729 return false;
1730 }
1731 break;
1732
1733 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001734 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001735 return false;
1736 }
1737
1738 return ValidateClearBuffer(context);
1739}
1740
1741bool ValidateClearBufferuiv(ValidationContext *context,
1742 GLenum buffer,
1743 GLint drawbuffer,
1744 const GLuint *value)
1745{
1746 switch (buffer)
1747 {
1748 case GL_COLOR:
1749 if (drawbuffer < 0 ||
1750 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001752 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001753 return false;
1754 }
Geoff Lang76e65652017-03-27 14:58:02 -04001755 if (context->getExtensions().webglCompatibility)
1756 {
1757 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001758 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001759 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1760 {
1761 return false;
1762 }
1763 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001764 break;
1765
1766 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001767 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001768 return false;
1769 }
1770
1771 return ValidateClearBuffer(context);
1772}
1773
1774bool ValidateClearBufferfv(ValidationContext *context,
1775 GLenum buffer,
1776 GLint drawbuffer,
1777 const GLfloat *value)
1778{
1779 switch (buffer)
1780 {
1781 case GL_COLOR:
1782 if (drawbuffer < 0 ||
1783 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001785 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001786 return false;
1787 }
Geoff Lang76e65652017-03-27 14:58:02 -04001788 if (context->getExtensions().webglCompatibility)
1789 {
1790 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1791 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001792 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001793 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1794 {
1795 return false;
1796 }
1797 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 break;
1799
1800 case GL_DEPTH:
1801 if (drawbuffer != 0)
1802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001803 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 return false;
1805 }
1806 break;
1807
1808 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001809 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 return false;
1811 }
1812
1813 return ValidateClearBuffer(context);
1814}
1815
1816bool ValidateClearBufferfi(ValidationContext *context,
1817 GLenum buffer,
1818 GLint drawbuffer,
1819 GLfloat depth,
1820 GLint stencil)
1821{
1822 switch (buffer)
1823 {
1824 case GL_DEPTH_STENCIL:
1825 if (drawbuffer != 0)
1826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001827 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 return false;
1829 }
1830 break;
1831
1832 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001834 return false;
1835 }
1836
1837 return ValidateClearBuffer(context);
1838}
1839
1840bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1841{
Martin Radev1be913c2016-07-11 17:59:16 +03001842 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001843 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 return false;
1846 }
1847
1848 return ValidateDrawBuffersBase(context, n, bufs);
1849}
1850
1851bool ValidateCopyTexSubImage3D(Context *context,
1852 GLenum target,
1853 GLint level,
1854 GLint xoffset,
1855 GLint yoffset,
1856 GLint zoffset,
1857 GLint x,
1858 GLint y,
1859 GLsizei width,
1860 GLsizei height)
1861{
Martin Radev1be913c2016-07-11 17:59:16 +03001862 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001865 return false;
1866 }
1867
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001868 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1869 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001870}
1871
Jamie Madill73a84962016-02-12 09:27:23 -05001872bool ValidateTexImage3D(Context *context,
1873 GLenum target,
1874 GLint level,
1875 GLint internalformat,
1876 GLsizei width,
1877 GLsizei height,
1878 GLsizei depth,
1879 GLint border,
1880 GLenum format,
1881 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001882 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001883{
Martin Radev1be913c2016-07-11 17:59:16 +03001884 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001885 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001887 return false;
1888 }
1889
1890 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001891 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001892 pixels);
1893}
1894
Geoff Langc52f6f12016-10-14 10:18:00 -04001895bool ValidateTexImage3DRobustANGLE(Context *context,
1896 GLenum target,
1897 GLint level,
1898 GLint internalformat,
1899 GLsizei width,
1900 GLsizei height,
1901 GLsizei depth,
1902 GLint border,
1903 GLenum format,
1904 GLenum type,
1905 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001906 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001907{
1908 if (context->getClientMajorVersion() < 3)
1909 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001910 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001911 return false;
1912 }
1913
1914 if (!ValidateRobustEntryPoint(context, bufSize))
1915 {
1916 return false;
1917 }
1918
1919 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1920 0, 0, width, height, depth, border, format, type,
1921 bufSize, pixels);
1922}
1923
Jamie Madill73a84962016-02-12 09:27:23 -05001924bool ValidateTexSubImage3D(Context *context,
1925 GLenum target,
1926 GLint level,
1927 GLint xoffset,
1928 GLint yoffset,
1929 GLint zoffset,
1930 GLsizei width,
1931 GLsizei height,
1932 GLsizei depth,
1933 GLenum format,
1934 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001935 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001936{
Martin Radev1be913c2016-07-11 17:59:16 +03001937 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001938 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001940 return false;
1941 }
1942
1943 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1944 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001945 -1, pixels);
1946}
1947
1948bool ValidateTexSubImage3DRobustANGLE(Context *context,
1949 GLenum target,
1950 GLint level,
1951 GLint xoffset,
1952 GLint yoffset,
1953 GLint zoffset,
1954 GLsizei width,
1955 GLsizei height,
1956 GLsizei depth,
1957 GLenum format,
1958 GLenum type,
1959 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001960 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001961{
1962 if (context->getClientMajorVersion() < 3)
1963 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04001965 return false;
1966 }
1967
1968 if (!ValidateRobustEntryPoint(context, bufSize))
1969 {
1970 return false;
1971 }
1972
1973 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1974 yoffset, zoffset, width, height, depth, 0, format, type,
1975 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001976}
1977
1978bool ValidateCompressedTexSubImage3D(Context *context,
1979 GLenum target,
1980 GLint level,
1981 GLint xoffset,
1982 GLint yoffset,
1983 GLint zoffset,
1984 GLsizei width,
1985 GLsizei height,
1986 GLsizei depth,
1987 GLenum format,
1988 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001989 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001990{
Martin Radev1be913c2016-07-11 17:59:16 +03001991 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001992 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05001994 return false;
1995 }
1996
Geoff Langca271392017-04-05 12:30:00 -04001997 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001998 if (!formatInfo.compressed)
1999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002000 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002001 return false;
2002 }
2003
Jamie Madill513558d2016-06-02 13:04:11 -04002004 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002005 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04002006 if (blockSizeOrErr.isError())
2007 {
2008 context->handleError(blockSizeOrErr.getError());
2009 return false;
2010 }
2011 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002013 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002014 return false;
2015 }
2016
2017 if (!data)
2018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002019 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002020 return false;
2021 }
2022
2023 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04002024 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002025}
Corentin Wallezb2931602017-04-11 15:58:57 -04002026bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2027 GLenum target,
2028 GLint level,
2029 GLint xoffset,
2030 GLint yoffset,
2031 GLint zoffset,
2032 GLsizei width,
2033 GLsizei height,
2034 GLsizei depth,
2035 GLenum format,
2036 GLsizei imageSize,
2037 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002038 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002039{
2040 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2041 {
2042 return false;
2043 }
2044
2045 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2046 height, depth, format, imageSize, data);
2047}
Jamie Madill73a84962016-02-12 09:27:23 -05002048
Olli Etuaho41997e72016-03-10 13:38:39 +02002049bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2050{
2051 return ValidateGenOrDeleteES3(context, n);
2052}
2053
2054bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2055{
2056 return ValidateGenOrDeleteES3(context, n);
2057}
2058
2059bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2060{
2061 return ValidateGenOrDeleteCountES3(context, count);
2062}
2063
2064bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2065{
2066 return ValidateGenOrDeleteCountES3(context, count);
2067}
2068
2069bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2070{
2071 return ValidateGenOrDeleteES3(context, n);
2072}
2073
2074bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2075{
2076 if (!ValidateGenOrDeleteES3(context, n))
2077 {
2078 return false;
2079 }
2080 for (GLint i = 0; i < n; ++i)
2081 {
2082 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2083 if (transformFeedback != nullptr && transformFeedback->isActive())
2084 {
2085 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002086 context->handleError(InvalidOperation()
2087 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002088 return false;
2089 }
2090 }
2091 return true;
2092}
2093
2094bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2095{
2096 return ValidateGenOrDeleteES3(context, n);
2097}
2098
2099bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2100{
2101 return ValidateGenOrDeleteES3(context, n);
2102}
2103
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002104bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2105{
Martin Radev1be913c2016-07-11 17:59:16 +03002106 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002107 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002109 return false;
2110 }
2111 switch (primitiveMode)
2112 {
2113 case GL_TRIANGLES:
2114 case GL_LINES:
2115 case GL_POINTS:
2116 break;
2117
2118 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002119 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002120 return false;
2121 }
2122
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002123 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002124 ASSERT(transformFeedback != nullptr);
2125
2126 if (transformFeedback->isActive())
2127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002128 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002129 return false;
2130 }
Geoff Lang79f71042017-08-14 16:43:43 -04002131
2132 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2133 {
2134 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2135 if (buffer.get() && buffer->isMapped())
2136 {
2137 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2138 return false;
2139 }
2140 }
2141
Olli Etuaho02032bd2017-10-13 18:10:17 +03002142 auto program = context->getGLState().getProgram();
2143
2144 if (!program)
2145 {
2146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2147 return false;
2148 }
2149
2150 if (program->getTransformFeedbackVaryingCount() == 0)
2151 {
2152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2153 return false;
2154 }
2155
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002156 return true;
2157}
2158
Jamie Madill876429b2017-04-20 15:46:24 -04002159bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002160{
Geoff Lang496c02d2016-10-20 11:38:11 -07002161 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2162}
2163
2164bool ValidateGetBufferPointervRobustANGLE(Context *context,
2165 GLenum target,
2166 GLenum pname,
2167 GLsizei bufSize,
2168 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002169 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002170{
2171 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002172 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002173 return false;
2174 }
2175
Geoff Lang496c02d2016-10-20 11:38:11 -07002176 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2177 {
2178 return false;
2179 }
2180
2181 if (!ValidateRobustBufferSize(context, bufSize, *length))
2182 {
2183 return false;
2184 }
2185
2186 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002187}
2188
2189bool ValidateUnmapBuffer(Context *context, GLenum target)
2190{
Martin Radev1be913c2016-07-11 17:59:16 +03002191 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002192 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002194 return false;
2195 }
2196
2197 return ValidateUnmapBufferBase(context, target);
2198}
2199
2200bool ValidateMapBufferRange(Context *context,
2201 GLenum target,
2202 GLintptr offset,
2203 GLsizeiptr length,
2204 GLbitfield access)
2205{
Martin Radev1be913c2016-07-11 17:59:16 +03002206 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002209 return false;
2210 }
2211
2212 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2213}
2214
2215bool ValidateFlushMappedBufferRange(Context *context,
2216 GLenum target,
2217 GLintptr offset,
2218 GLsizeiptr length)
2219{
Martin Radev1be913c2016-07-11 17:59:16 +03002220 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002221 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002223 return false;
2224 }
2225
2226 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2227}
2228
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002229bool ValidateIndexedStateQuery(ValidationContext *context,
2230 GLenum pname,
2231 GLuint index,
2232 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002233{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002234 if (length)
2235 {
2236 *length = 0;
2237 }
2238
Martin Radev66fb8202016-07-28 11:45:20 +03002239 GLenum nativeType;
2240 unsigned int numParams;
2241 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002244 return false;
2245 }
2246
2247 const Caps &caps = context->getCaps();
2248 switch (pname)
2249 {
2250 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2251 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2252 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2253 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002255 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002256 return false;
2257 }
2258 break;
2259
2260 case GL_UNIFORM_BUFFER_START:
2261 case GL_UNIFORM_BUFFER_SIZE:
2262 case GL_UNIFORM_BUFFER_BINDING:
2263 if (index >= caps.maxUniformBufferBindings)
2264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002265 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002266 return false;
2267 }
2268 break;
Shao80957d92017-02-20 21:25:59 +08002269
Martin Radev66fb8202016-07-28 11:45:20 +03002270 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2271 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2272 if (index >= 3u)
2273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002275 return false;
2276 }
2277 break;
Shao80957d92017-02-20 21:25:59 +08002278
Jiajia Qin6eafb042016-12-27 17:04:07 +08002279 case GL_ATOMIC_COUNTER_BUFFER_START:
2280 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2281 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2282 if (context->getClientVersion() < ES_3_1)
2283 {
2284 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002285 InvalidEnum()
2286 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002287 return false;
2288 }
2289 if (index >= caps.maxAtomicCounterBufferBindings)
2290 {
2291 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002292 InvalidValue()
2293 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002294 return false;
2295 }
2296 break;
Shao80957d92017-02-20 21:25:59 +08002297
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002298 case GL_SHADER_STORAGE_BUFFER_START:
2299 case GL_SHADER_STORAGE_BUFFER_SIZE:
2300 case GL_SHADER_STORAGE_BUFFER_BINDING:
2301 if (context->getClientVersion() < ES_3_1)
2302 {
2303 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002304 InvalidEnum()
2305 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002306 return false;
2307 }
2308 if (index >= caps.maxShaderStorageBufferBindings)
2309 {
2310 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002311 InvalidValue()
2312 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002313 return false;
2314 }
2315 break;
2316
Shao80957d92017-02-20 21:25:59 +08002317 case GL_VERTEX_BINDING_BUFFER:
2318 case GL_VERTEX_BINDING_DIVISOR:
2319 case GL_VERTEX_BINDING_OFFSET:
2320 case GL_VERTEX_BINDING_STRIDE:
2321 if (context->getClientVersion() < ES_3_1)
2322 {
2323 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002324 InvalidEnum()
2325 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002326 return false;
2327 }
2328 if (index >= caps.maxVertexAttribBindings)
2329 {
2330 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002331 InvalidValue()
2332 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002333 return false;
2334 }
2335 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002336 case GL_SAMPLE_MASK_VALUE:
2337 if (context->getClientVersion() < ES_3_1)
2338 {
2339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2340 return false;
2341 }
2342 if (index >= caps.maxSampleMaskWords)
2343 {
2344 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2345 return false;
2346 }
2347 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002348 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002349 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002350 return false;
2351 }
2352
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002353 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002354 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002355 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002356 }
2357
2358 return true;
2359}
2360
2361bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2362{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002363 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002364 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002365 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002366 return false;
2367 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002368 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002369}
2370
Geoff Langcf255ea2016-10-20 11:39:09 -07002371bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2372 GLenum target,
2373 GLuint index,
2374 GLsizei bufSize,
2375 GLsizei *length,
2376 GLint *data)
2377{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002378 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002379 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002381 return false;
2382 }
2383
2384 if (!ValidateRobustEntryPoint(context, bufSize))
2385 {
2386 return false;
2387 }
2388
2389 if (!ValidateIndexedStateQuery(context, target, index, length))
2390 {
2391 return false;
2392 }
2393
2394 if (!ValidateRobustBufferSize(context, bufSize, *length))
2395 {
2396 return false;
2397 }
2398
2399 return true;
2400}
2401
Martin Radev66fb8202016-07-28 11:45:20 +03002402bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2403{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002404 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002405 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002406 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002407 return false;
2408 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002409 return ValidateIndexedStateQuery(context, target, index, nullptr);
2410}
2411
2412bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2413 GLenum target,
2414 GLuint index,
2415 GLsizei bufSize,
2416 GLsizei *length,
2417 GLint64 *data)
2418{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002419 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002420 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002421 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002422 return false;
2423 }
2424
2425 if (!ValidateRobustEntryPoint(context, bufSize))
2426 {
2427 return false;
2428 }
2429
2430 if (!ValidateIndexedStateQuery(context, target, index, length))
2431 {
2432 return false;
2433 }
2434
2435 if (!ValidateRobustBufferSize(context, bufSize, *length))
2436 {
2437 return false;
2438 }
2439
2440 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002441}
2442
Jamie Madillb0817d12016-11-01 15:48:31 -04002443bool ValidateCopyBufferSubData(ValidationContext *context,
2444 GLenum readTarget,
2445 GLenum writeTarget,
2446 GLintptr readOffset,
2447 GLintptr writeOffset,
2448 GLsizeiptr size)
2449{
2450 if (context->getClientMajorVersion() < 3)
2451 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002452 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002453 return false;
2454 }
2455
2456 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002458 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002459 return false;
2460 }
2461
2462 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2463 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2464
2465 if (!readBuffer || !writeBuffer)
2466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002467 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002468 return false;
2469 }
2470
2471 // Verify that readBuffer and writeBuffer are not currently mapped
2472 if (readBuffer->isMapped() || writeBuffer->isMapped())
2473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002474 context->handleError(InvalidOperation()
2475 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002476 return false;
2477 }
2478
Jamie Madilld2f0c742016-11-02 10:34:41 -04002479 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2480 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2481 CheckedNumeric<GLintptr> checkedSize(size);
2482
2483 auto checkedReadSum = checkedReadOffset + checkedSize;
2484 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2485
2486 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2487 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2488 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002490 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002491 return false;
2492 }
2493
Jamie Madilld2f0c742016-11-02 10:34:41 -04002494 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002496 context->handleError(InvalidValue()
2497 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002498 return false;
2499 }
2500
Jamie Madilld2f0c742016-11-02 10:34:41 -04002501 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2502 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002505 return false;
2506 }
2507
2508 if (readBuffer == writeBuffer)
2509 {
2510 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2511 if (!checkedOffsetDiff.IsValid())
2512 {
2513 // This shold not be possible.
2514 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002515 context->handleError(InvalidValue()
2516 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002517 return false;
2518 }
2519
2520 if (checkedOffsetDiff.ValueOrDie() < size)
2521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002523 return false;
2524 }
2525 }
2526
Jamie Madillb0817d12016-11-01 15:48:31 -04002527 return true;
2528}
2529
Geoff Langc339c4e2016-11-29 10:37:36 -05002530bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2531{
2532 if (context->getClientMajorVersion() < 3)
2533 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002534 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002535 return false;
2536 }
2537
2538 switch (name)
2539 {
2540 case GL_EXTENSIONS:
2541 if (index >= context->getExtensionStringCount())
2542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002543 context->handleError(InvalidValue()
2544 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002545 return false;
2546 }
2547 break;
2548
2549 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2550 if (!context->getExtensions().requestExtension)
2551 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002552 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002553 return false;
2554 }
2555 if (index >= context->getRequestableExtensionStringCount())
2556 {
2557 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002558 InvalidValue()
2559 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002560 return false;
2561 }
2562 break;
2563
2564 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002566 return false;
2567 }
2568
2569 return true;
2570}
2571
Jamie Madille8fb6402017-02-14 17:56:40 -05002572bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2573 GLenum target,
2574 GLsizei samples,
2575 GLenum internalformat,
2576 GLsizei width,
2577 GLsizei height)
2578{
2579 if (context->getClientMajorVersion() < 3)
2580 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002582 return false;
2583 }
2584
2585 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2586 height))
2587 {
2588 return false;
2589 }
2590
2591 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2592 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002593 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002594 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2595 samples > 0)
2596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002597 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002598 return false;
2599 }
2600
2601 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2602 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2603 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2604 {
2605 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002606 InvalidOperation()
2607 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002608 return false;
2609 }
2610
2611 return true;
2612}
2613
Geoff Langaa086d62017-03-23 16:47:21 -04002614bool ValidateVertexAttribIPointer(ValidationContext *context,
2615 GLuint index,
2616 GLint size,
2617 GLenum type,
2618 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002619 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002620{
2621 if (context->getClientMajorVersion() < 3)
2622 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002623 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002624 return false;
2625 }
2626
Shao80957d92017-02-20 21:25:59 +08002627 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002628 {
Geoff Langaa086d62017-03-23 16:47:21 -04002629 return false;
2630 }
2631
Geoff Langaa086d62017-03-23 16:47:21 -04002632 if (stride < 0)
2633 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002634 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002635 return false;
2636 }
2637
Shao80957d92017-02-20 21:25:59 +08002638 const Caps &caps = context->getCaps();
2639 if (context->getClientVersion() >= ES_3_1)
2640 {
2641 if (stride > caps.maxVertexAttribStride)
2642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002643 context->handleError(InvalidValue()
2644 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002645 return false;
2646 }
2647
2648 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2649 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2650 // validation should be inherited.
2651 if (index >= caps.maxVertexAttribBindings)
2652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002653 context->handleError(InvalidValue()
2654 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002655 return false;
2656 }
2657 }
2658
Geoff Langaa086d62017-03-23 16:47:21 -04002659 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2660 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2661 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2662 // and the pointer argument is not NULL.
2663 if (context->getGLState().getVertexArrayId() != 0 &&
2664 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002666 context
2667 ->handleError(InvalidOperation()
2668 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002669 return false;
2670 }
2671
Geoff Lang2d62ab72017-03-23 16:54:40 -04002672 if (context->getExtensions().webglCompatibility)
2673 {
2674 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2675 {
2676 return false;
2677 }
2678 }
2679
Geoff Langaa086d62017-03-23 16:47:21 -04002680 return true;
2681}
2682
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002683bool ValidateGetSynciv(Context *context,
2684 GLsync sync,
2685 GLenum pname,
2686 GLsizei bufSize,
2687 GLsizei *length,
2688 GLint *values)
2689{
2690 if (context->getClientMajorVersion() < 3)
2691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002693 return false;
2694 }
2695
2696 if (bufSize < 0)
2697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002698 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002699 return false;
2700 }
2701
Jamie Madill70b5bb02017-08-28 13:32:37 -04002702 Sync *syncObject = context->getSync(sync);
2703 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002705 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002706 return false;
2707 }
2708
2709 switch (pname)
2710 {
2711 case GL_OBJECT_TYPE:
2712 case GL_SYNC_CONDITION:
2713 case GL_SYNC_FLAGS:
2714 case GL_SYNC_STATUS:
2715 break;
2716
2717 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002718 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002719 return false;
2720 }
2721
2722 return true;
2723}
2724
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002725bool ValidateDrawElementsInstanced(ValidationContext *context,
2726 GLenum mode,
2727 GLsizei count,
2728 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002729 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002730 GLsizei instanceCount)
2731{
2732 if (context->getClientMajorVersion() < 3)
2733 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002734 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002735 return false;
2736 }
2737
2738 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2739}
2740
Martin Radev137032d2017-07-13 10:11:12 +03002741bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2742 GLenum target,
2743 GLenum attachment,
2744 GLuint texture,
2745 GLint level,
2746 GLint baseViewIndex,
2747 GLsizei numViews)
2748{
2749
2750 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2751 numViews))
2752 {
2753 return false;
2754 }
2755
Martin Radev137032d2017-07-13 10:11:12 +03002756 if (texture != 0)
2757 {
Martin Radev14b21262017-08-25 13:54:37 +03002758 if (baseViewIndex < 0)
2759 {
2760 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2761 return false;
2762 }
2763
Martin Radev137032d2017-07-13 10:11:12 +03002764 Texture *tex = context->getTexture(texture);
2765 ASSERT(tex);
2766
2767 switch (tex->getTarget())
2768 {
2769 case GL_TEXTURE_2D_ARRAY:
2770 {
2771 const Caps &caps = context->getCaps();
2772 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2773 {
2774 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2775 "greater than "
2776 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2777 return false;
2778 }
2779 }
2780 break;
2781 default:
2782 context->handleError(InvalidOperation()
2783 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2784 return false;
2785 }
2786
2787 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2788 {
2789 return false;
2790 }
2791 }
2792
2793 return true;
2794}
2795
2796bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2797 GLenum target,
2798 GLenum attachment,
2799 GLuint texture,
2800 GLint level,
2801 GLsizei numViews,
2802 const GLint *viewportOffsets)
2803{
2804 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2805 numViews))
2806 {
2807 return false;
2808 }
2809
Martin Radev137032d2017-07-13 10:11:12 +03002810 if (texture != 0)
2811 {
Martin Radev14b21262017-08-25 13:54:37 +03002812 const GLsizei numViewportOffsetValues = numViews * 2;
2813 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2814 {
2815 if (viewportOffsets[i] < 0)
2816 {
2817 context->handleError(InvalidValue()
2818 << "viewportOffsets cannot contain negative values.");
2819 return false;
2820 }
2821 }
2822
Martin Radev137032d2017-07-13 10:11:12 +03002823 Texture *tex = context->getTexture(texture);
2824 ASSERT(tex);
2825
2826 switch (tex->getTarget())
2827 {
2828 case GL_TEXTURE_2D:
2829 break;
2830 default:
2831 context->handleError(InvalidOperation()
2832 << "Texture's target must be GL_TEXTURE_2D.");
2833 return false;
2834 }
2835
2836 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2837 {
2838 return false;
2839 }
2840 }
2841
2842 return true;
2843}
2844
Jamie Madillff325f12017-08-26 15:06:05 -04002845bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2846{
2847 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2848}
2849
2850bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2851{
2852 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2853}
2854
2855bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2856{
2857 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2858}
2859
2860bool ValidateUniform4ui(Context *context,
2861 GLint location,
2862 GLuint v0,
2863 GLuint v1,
2864 GLuint v2,
2865 GLuint v3)
2866{
2867 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2868}
2869
2870bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2871{
2872 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2873}
2874
2875bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2876{
2877 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2878}
2879
2880bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2881{
2882 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2883}
2884
2885bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2886{
2887 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2888}
2889
Jamie Madillf0e04492017-08-26 15:28:42 -04002890bool ValidateIsQuery(Context *context, GLuint id)
2891{
2892 if (context->getClientMajorVersion() < 3)
2893 {
2894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2895 return false;
2896 }
2897
2898 return true;
2899}
2900
Jamie Madillc8c95812017-08-26 18:40:09 -04002901bool ValidateUniformMatrix2x3fv(Context *context,
2902 GLint location,
2903 GLsizei count,
2904 GLboolean transpose,
2905 const GLfloat *value)
2906{
2907 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2908}
2909
2910bool ValidateUniformMatrix3x2fv(Context *context,
2911 GLint location,
2912 GLsizei count,
2913 GLboolean transpose,
2914 const GLfloat *value)
2915{
2916 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2917}
2918
2919bool ValidateUniformMatrix2x4fv(Context *context,
2920 GLint location,
2921 GLsizei count,
2922 GLboolean transpose,
2923 const GLfloat *value)
2924{
2925 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2926}
2927
2928bool ValidateUniformMatrix4x2fv(Context *context,
2929 GLint location,
2930 GLsizei count,
2931 GLboolean transpose,
2932 const GLfloat *value)
2933{
2934 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2935}
2936
2937bool ValidateUniformMatrix3x4fv(Context *context,
2938 GLint location,
2939 GLsizei count,
2940 GLboolean transpose,
2941 const GLfloat *value)
2942{
2943 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2944}
2945
2946bool ValidateUniformMatrix4x3fv(Context *context,
2947 GLint location,
2948 GLsizei count,
2949 GLboolean transpose,
2950 const GLfloat *value)
2951{
2952 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2953}
2954
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002955bool ValidateEndTransformFeedback(Context *context)
2956{
2957 if (context->getClientMajorVersion() < 3)
2958 {
2959 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2960 return false;
2961 }
2962
2963 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2964 ASSERT(transformFeedback != nullptr);
2965
2966 if (!transformFeedback->isActive())
2967 {
2968 context->handleError(InvalidOperation());
2969 return false;
2970 }
2971
2972 return true;
2973}
2974
2975bool ValidateTransformFeedbackVaryings(Context *context,
2976 GLuint program,
2977 GLsizei count,
2978 const GLchar *const *varyings,
2979 GLenum bufferMode)
2980{
2981 if (context->getClientMajorVersion() < 3)
2982 {
2983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2984 return false;
2985 }
2986
2987 if (count < 0)
2988 {
2989 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2990 return false;
2991 }
2992
2993 switch (bufferMode)
2994 {
2995 case GL_INTERLEAVED_ATTRIBS:
2996 break;
2997 case GL_SEPARATE_ATTRIBS:
2998 {
2999 const Caps &caps = context->getCaps();
3000 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3001 {
3002 context->handleError(InvalidValue());
3003 return false;
3004 }
3005 break;
3006 }
3007 default:
3008 context->handleError(InvalidEnum());
3009 return false;
3010 }
3011
3012 Program *programObject = GetValidProgram(context, program);
3013 if (!programObject)
3014 {
3015 return false;
3016 }
3017
3018 return true;
3019}
3020
3021bool ValidateGetTransformFeedbackVarying(Context *context,
3022 GLuint program,
3023 GLuint index,
3024 GLsizei bufSize,
3025 GLsizei *length,
3026 GLsizei *size,
3027 GLenum *type,
3028 GLchar *name)
3029{
3030 if (context->getClientMajorVersion() < 3)
3031 {
3032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3033 return false;
3034 }
3035
3036 if (bufSize < 0)
3037 {
3038 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3039 return false;
3040 }
3041
3042 Program *programObject = GetValidProgram(context, program);
3043 if (!programObject)
3044 {
3045 return false;
3046 }
3047
3048 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3049 {
3050 context->handleError(InvalidValue());
3051 return false;
3052 }
3053
3054 return true;
3055}
3056
3057bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3058{
3059 if (context->getClientMajorVersion() < 3)
3060 {
3061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3062 return false;
3063 }
3064
3065 switch (target)
3066 {
3067 case GL_TRANSFORM_FEEDBACK:
3068 {
3069 // Cannot bind a transform feedback object if the current one is started and not
3070 // paused (3.0.2 pg 85 section 2.14.1)
3071 TransformFeedback *curTransformFeedback =
3072 context->getGLState().getCurrentTransformFeedback();
3073 if (curTransformFeedback && curTransformFeedback->isActive() &&
3074 !curTransformFeedback->isPaused())
3075 {
3076 context->handleError(InvalidOperation());
3077 return false;
3078 }
3079
3080 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3081 // 2.14.1)
3082 if (!context->isTransformFeedbackGenerated(id))
3083 {
3084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3085 return false;
3086 }
3087 }
3088 break;
3089
3090 default:
3091 context->handleError(InvalidEnum());
3092 return false;
3093 }
3094
3095 return true;
3096}
3097
3098bool ValidateIsTransformFeedback(Context *context, GLuint id)
3099{
3100 if (context->getClientMajorVersion() < 3)
3101 {
3102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3103 return false;
3104 }
3105
3106 return true;
3107}
3108
3109bool ValidatePauseTransformFeedback(Context *context)
3110{
3111 if (context->getClientMajorVersion() < 3)
3112 {
3113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3114 return false;
3115 }
3116
3117 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3118 ASSERT(transformFeedback != nullptr);
3119
3120 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3121 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3122 {
3123 context->handleError(InvalidOperation());
3124 return false;
3125 }
3126
3127 return true;
3128}
3129
3130bool ValidateResumeTransformFeedback(Context *context)
3131{
3132 if (context->getClientMajorVersion() < 3)
3133 {
3134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3135 return false;
3136 }
3137
3138 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3139 ASSERT(transformFeedback != nullptr);
3140
3141 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3142 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3143 {
3144 context->handleError(InvalidOperation());
3145 return false;
3146 }
3147
3148 return true;
3149}
3150
Jamie Madill12e957f2017-08-26 21:42:26 -04003151bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3152{
3153 if (context->getClientMajorVersion() < 3)
3154 {
3155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3156 return false;
3157 }
3158
3159 return ValidateVertexAttribIndex(context, index);
3160}
3161
3162bool ValidateVertexAttribI4ui(Context *context,
3163 GLuint index,
3164 GLuint x,
3165 GLuint y,
3166 GLuint z,
3167 GLuint w)
3168{
3169 if (context->getClientMajorVersion() < 3)
3170 {
3171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3172 return false;
3173 }
3174
3175 return ValidateVertexAttribIndex(context, index);
3176}
3177
3178bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3179{
3180 if (context->getClientMajorVersion() < 3)
3181 {
3182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3183 return false;
3184 }
3185
3186 return ValidateVertexAttribIndex(context, index);
3187}
3188
3189bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3190{
3191 if (context->getClientMajorVersion() < 3)
3192 {
3193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3194 return false;
3195 }
3196
3197 return ValidateVertexAttribIndex(context, index);
3198}
3199
3200bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3201{
3202 if (context->getClientMajorVersion() < 3)
3203 {
3204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3205 return false;
3206 }
3207
3208 Program *programObject = GetValidProgram(context, program);
3209 if (!programObject)
3210 {
3211 return false;
3212 }
3213
3214 if (!programObject->isLinked())
3215 {
3216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3217 return false;
3218 }
3219
3220 return true;
3221}
3222
3223bool ValidateGetUniformIndices(Context *context,
3224 GLuint program,
3225 GLsizei uniformCount,
3226 const GLchar *const *uniformNames,
3227 GLuint *uniformIndices)
3228{
3229 if (context->getClientMajorVersion() < 3)
3230 {
3231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3232 return false;
3233 }
3234
3235 if (uniformCount < 0)
3236 {
3237 context->handleError(InvalidValue());
3238 return false;
3239 }
3240
3241 Program *programObject = GetValidProgram(context, program);
3242 if (!programObject)
3243 {
3244 return false;
3245 }
3246
3247 return true;
3248}
3249
3250bool ValidateGetActiveUniformsiv(Context *context,
3251 GLuint program,
3252 GLsizei uniformCount,
3253 const GLuint *uniformIndices,
3254 GLenum pname,
3255 GLint *params)
3256{
3257 if (context->getClientMajorVersion() < 3)
3258 {
3259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3260 return false;
3261 }
3262
3263 if (uniformCount < 0)
3264 {
3265 context->handleError(InvalidValue());
3266 return false;
3267 }
3268
3269 Program *programObject = GetValidProgram(context, program);
3270 if (!programObject)
3271 {
3272 return false;
3273 }
3274
3275 switch (pname)
3276 {
3277 case GL_UNIFORM_TYPE:
3278 case GL_UNIFORM_SIZE:
3279 case GL_UNIFORM_NAME_LENGTH:
3280 case GL_UNIFORM_BLOCK_INDEX:
3281 case GL_UNIFORM_OFFSET:
3282 case GL_UNIFORM_ARRAY_STRIDE:
3283 case GL_UNIFORM_MATRIX_STRIDE:
3284 case GL_UNIFORM_IS_ROW_MAJOR:
3285 break;
3286
3287 default:
3288 context->handleError(InvalidEnum());
3289 return false;
3290 }
3291
3292 if (uniformCount > programObject->getActiveUniformCount())
3293 {
3294 context->handleError(InvalidValue());
3295 return false;
3296 }
3297
3298 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3299 {
3300 const GLuint index = uniformIndices[uniformId];
3301
3302 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3303 {
3304 context->handleError(InvalidValue());
3305 return false;
3306 }
3307 }
3308
3309 return true;
3310}
3311
3312bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3313{
3314 if (context->getClientMajorVersion() < 3)
3315 {
3316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3317 return false;
3318 }
3319
3320 Program *programObject = GetValidProgram(context, program);
3321 if (!programObject)
3322 {
3323 return false;
3324 }
3325
3326 return true;
3327}
3328
3329bool ValidateGetActiveUniformBlockiv(Context *context,
3330 GLuint program,
3331 GLuint uniformBlockIndex,
3332 GLenum pname,
3333 GLint *params)
3334{
3335 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3336}
3337
3338bool ValidateGetActiveUniformBlockName(Context *context,
3339 GLuint program,
3340 GLuint uniformBlockIndex,
3341 GLsizei bufSize,
3342 GLsizei *length,
3343 GLchar *uniformBlockName)
3344{
3345 if (context->getClientMajorVersion() < 3)
3346 {
3347 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3348 return false;
3349 }
3350
3351 Program *programObject = GetValidProgram(context, program);
3352 if (!programObject)
3353 {
3354 return false;
3355 }
3356
3357 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3358 {
3359 context->handleError(InvalidValue());
3360 return false;
3361 }
3362
3363 return true;
3364}
3365
3366bool ValidateUniformBlockBinding(Context *context,
3367 GLuint program,
3368 GLuint uniformBlockIndex,
3369 GLuint uniformBlockBinding)
3370{
3371 if (context->getClientMajorVersion() < 3)
3372 {
3373 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3374 return false;
3375 }
3376
3377 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3378 {
3379 context->handleError(InvalidValue());
3380 return false;
3381 }
3382
3383 Program *programObject = GetValidProgram(context, program);
3384 if (!programObject)
3385 {
3386 return false;
3387 }
3388
3389 // if never linked, there won't be any uniform blocks
3390 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3391 {
3392 context->handleError(InvalidValue());
3393 return false;
3394 }
3395
3396 return true;
3397}
3398
3399bool ValidateDrawArraysInstanced(Context *context,
3400 GLenum mode,
3401 GLint first,
3402 GLsizei count,
3403 GLsizei primcount)
3404{
3405 if (context->getClientMajorVersion() < 3)
3406 {
3407 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3408 return false;
3409 }
3410
3411 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3412}
3413
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003414bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3415{
3416 if (context->getClientMajorVersion() < 3)
3417 {
3418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3419 return false;
3420 }
3421
3422 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3423 {
3424 context->handleError(InvalidEnum());
3425 return false;
3426 }
3427
3428 if (flags != 0)
3429 {
3430 context->handleError(InvalidValue());
3431 return false;
3432 }
3433
3434 return true;
3435}
3436
3437bool ValidateIsSync(Context *context, GLsync sync)
3438{
3439 if (context->getClientMajorVersion() < 3)
3440 {
3441 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3442 return false;
3443 }
3444
3445 return true;
3446}
3447
3448bool ValidateDeleteSync(Context *context, GLsync sync)
3449{
3450 if (context->getClientMajorVersion() < 3)
3451 {
3452 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3453 return false;
3454 }
3455
Jamie Madill70b5bb02017-08-28 13:32:37 -04003456 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003457 {
3458 context->handleError(InvalidValue());
3459 return false;
3460 }
3461
3462 return true;
3463}
3464
3465bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3466{
3467 if (context->getClientMajorVersion() < 3)
3468 {
3469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3470 return false;
3471 }
3472
3473 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3474 {
3475 context->handleError(InvalidValue());
3476 return false;
3477 }
3478
Jamie Madill70b5bb02017-08-28 13:32:37 -04003479 Sync *clientWaitSync = context->getSync(sync);
3480 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003481 {
3482 context->handleError(InvalidValue());
3483 return false;
3484 }
3485
3486 return true;
3487}
3488
3489bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3490{
3491 if (context->getClientMajorVersion() < 3)
3492 {
3493 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3494 return false;
3495 }
3496
3497 if (flags != 0)
3498 {
3499 context->handleError(InvalidValue());
3500 return false;
3501 }
3502
3503 if (timeout != GL_TIMEOUT_IGNORED)
3504 {
3505 context->handleError(InvalidValue());
3506 return false;
3507 }
3508
Jamie Madill70b5bb02017-08-28 13:32:37 -04003509 Sync *waitSync = context->getSync(sync);
3510 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003511 {
3512 context->handleError(InvalidValue());
3513 return false;
3514 }
3515
3516 return true;
3517}
3518
3519bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3520{
3521 if (context->getClientMajorVersion() < 3)
3522 {
3523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3524 return false;
3525 }
3526
3527 GLenum nativeType = GL_NONE;
3528 unsigned int numParams = 0;
3529 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3530 {
3531 return false;
3532 }
3533
3534 return true;
3535}
3536
Jamie Madill3ef140a2017-08-26 23:11:21 -04003537bool ValidateIsSampler(Context *context, GLuint sampler)
3538{
3539 if (context->getClientMajorVersion() < 3)
3540 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003541 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003542 return false;
3543 }
3544
3545 return true;
3546}
3547
3548bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3549{
3550 if (context->getClientMajorVersion() < 3)
3551 {
3552 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3553 return false;
3554 }
3555
3556 if (sampler != 0 && !context->isSampler(sampler))
3557 {
3558 context->handleError(InvalidOperation());
3559 return false;
3560 }
3561
3562 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3563 {
3564 context->handleError(InvalidValue());
3565 return false;
3566 }
3567
3568 return true;
3569}
3570
3571bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3572{
3573 if (context->getClientMajorVersion() < 3)
3574 {
3575 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3576 return false;
3577 }
3578
3579 return ValidateVertexAttribIndex(context, index);
3580}
3581
3582bool ValidateTexStorage2D(Context *context,
3583 GLenum target,
3584 GLsizei levels,
3585 GLenum internalformat,
3586 GLsizei width,
3587 GLsizei height)
3588{
3589 if (context->getClientMajorVersion() < 3)
3590 {
3591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3592 return false;
3593 }
3594
3595 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3596 1))
3597 {
3598 return false;
3599 }
3600
3601 return true;
3602}
3603
3604bool ValidateTexStorage3D(Context *context,
3605 GLenum target,
3606 GLsizei levels,
3607 GLenum internalformat,
3608 GLsizei width,
3609 GLsizei height,
3610 GLsizei depth)
3611{
3612 if (context->getClientMajorVersion() < 3)
3613 {
3614 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3615 return false;
3616 }
3617
3618 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3619 depth))
3620 {
3621 return false;
3622 }
3623
3624 return true;
3625}
3626
Jamie Madill9696d072017-08-26 23:19:57 -04003627bool ValidateGetBufferParameteri64v(ValidationContext *context,
3628 GLenum target,
3629 GLenum pname,
3630 GLint64 *params)
3631{
3632 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3633}
3634
3635bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3636{
3637 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3638}
3639
3640bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3641{
3642 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3643}
3644
3645bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3646{
3647 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3648}
3649
3650bool ValidateSamplerParameterfv(Context *context,
3651 GLuint sampler,
3652 GLenum pname,
3653 const GLfloat *params)
3654{
3655 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3656}
3657
3658bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3659{
3660 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3661}
3662
3663bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3664{
3665 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3666}
3667
3668bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3669{
3670 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3671}
3672
3673bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3674{
3675 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3676}
3677
3678bool ValidateGetInternalformativ(Context *context,
3679 GLenum target,
3680 GLenum internalformat,
3681 GLenum pname,
3682 GLsizei bufSize,
3683 GLint *params)
3684{
3685 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3686 nullptr);
3687}
3688
Jamie Madillc29968b2016-01-20 11:17:23 -05003689} // namespace gl