blob: db9829ea9b5509ae87ce3db74d68d82cb9b0b580 [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{
Corentin Wallezf0e89be2017-11-08 14:00:32 -080069 TextureType type = texture->getType();
70 if (!ValidMipLevel(context, type, level))
Martin Radev137032d2017-07-13 10:11:12 +030071 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
Corentin Wallezf0e89be2017-11-08 14:00:32 -080076 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
Martin Radev137032d2017-07-13 10:11:12 +030077 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
Brandon Jones4e6f2ae2018-09-19 11:09:51 -0700137bool ValidateCopyTexture3DCommon(Context *context,
138 const Texture *source,
139 GLint sourceLevel,
140 GLint srcInternalFormat,
141 const Texture *dest,
142 GLint destLevel,
143 GLint internalFormat,
144 TextureTarget destTarget)
145{
146 if (context->getClientMajorVersion() < 3)
147 {
148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
149 return false;
150 }
151
152 if (!context->getExtensions().copyTexture3d)
153 {
154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ANGLECopyTexture3DUnavailable);
155 return false;
156 }
157
158 if (!ValidTexture3DTarget(context, source->getType()))
159 {
160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
161 return false;
162 }
163
164 // Table 1.1 from the ANGLE_copy_texture_3d spec
165 switch (GetUnsizedFormat(srcInternalFormat))
166 {
167 case GL_ALPHA:
168 case GL_LUMINANCE:
169 case GL_LUMINANCE_ALPHA:
170 case GL_RED:
171 case GL_RED_INTEGER:
172 case GL_RG:
173 case GL_RG_INTEGER:
174 case GL_RGB:
175 case GL_RGB_INTEGER:
176 case GL_RGBA:
177 case GL_RGBA_INTEGER:
178 case GL_DEPTH_COMPONENT:
179 case GL_DEPTH_STENCIL:
180 break;
181 default:
182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
183 return false;
184 }
185
186 if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
187 {
188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
189 return false;
190 }
191
192 // Table 1.0 from the ANGLE_copy_texture_3d spec
193 switch (internalFormat)
194 {
195 case GL_RGB:
196 case GL_RGBA:
197 case GL_LUMINANCE:
198 case GL_LUMINANCE_ALPHA:
199 case GL_ALPHA:
200 case GL_R8:
201 case GL_R8_SNORM:
202 case GL_R16F:
203 case GL_R32F:
204 case GL_R8UI:
205 case GL_R8I:
206 case GL_R16UI:
207 case GL_R16I:
208 case GL_R32UI:
209 case GL_R32I:
210 case GL_RG:
211 case GL_RG8:
212 case GL_RG8_SNORM:
213 case GL_RG16F:
214 case GL_RG32F:
215 case GL_RG8UI:
216 case GL_RG8I:
217 case GL_RG16UI:
218 case GL_RG16I:
219 case GL_RG32UI:
220 case GL_RG32I:
221 case GL_RGB8:
222 case GL_SRGB8:
223 case GL_RGB565:
224 case GL_RGB8_SNORM:
225 case GL_R11F_G11F_B10F:
226 case GL_RGB9_E5:
227 case GL_RGB16F:
228 case GL_RGB32F:
229 case GL_RGB8UI:
230 case GL_RGB8I:
231 case GL_RGB16UI:
232 case GL_RGB16I:
233 case GL_RGB32UI:
234 case GL_RGB32I:
235 case GL_RGBA8:
236 case GL_SRGB8_ALPHA8:
237 case GL_RGBA8_SNORM:
238 case GL_RGB5_A1:
239 case GL_RGBA4:
240 case GL_RGB10_A2:
241 case GL_RGBA16F:
242 case GL_RGBA32F:
243 case GL_RGBA8UI:
244 case GL_RGBA8I:
245 case GL_RGB10_A2UI:
246 case GL_RGBA16UI:
247 case GL_RGBA16I:
248 case GL_RGBA32I:
249 case GL_RGBA32UI:
250 break;
251 default:
252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
253 return false;
254 }
255
256 return true;
257}
Jamie Madillff325f12017-08-26 15:06:05 -0400258} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300259
He Yunchaoced53ae2016-11-29 15:00:51 +0800260static bool ValidateTexImageFormatCombination(gl::Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800261 TextureType target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800262 GLenum internalFormat,
263 GLenum format,
264 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400265{
Geoff Lang5d601382014-07-22 15:14:06 -0400266
267 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400268 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400269 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400271 return false;
272 }
273
274 if (!ValidES3Type(type))
275 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400277 return false;
278 }
279
280 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
281 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
282 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
283 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
284 if (!ValidES3InternalFormat(internalFormat))
285 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700286 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400287 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400288 }
289
Geoff Langca271392017-04-05 12:30:00 -0400290 // From the ES 3.0 spec section 3.8.3:
291 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
292 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
293 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
294 // INVALID_OPERATION error.
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800295 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
Geoff Langca271392017-04-05 12:30:00 -0400296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500297 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
298 "GL_DEPTH_STENCIL if target is "
299 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400300 return false;
301 }
302
Geoff Lang5d601382014-07-22 15:14:06 -0400303 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400304 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500306 context->handleError(InvalidOperation()
307 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400308 return false;
309 }
310
311 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
312 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400315 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400316 }
317
318 return true;
319}
320
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500321bool ValidateES3TexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800322 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500323 GLint level,
324 GLenum internalformat,
325 bool isCompressed,
326 bool isSubImage,
327 GLint xoffset,
328 GLint yoffset,
329 GLint zoffset,
330 GLsizei width,
331 GLsizei height,
332 GLsizei depth,
333 GLint border,
334 GLenum format,
335 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400336 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400337 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400338{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800339 TextureType texType = TextureTargetToType(target);
340
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400341 // Validate image size
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800342 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 }
347
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348 // Verify zero border
349 if (border != 0)
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400352 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400353 }
354
Jamie Madill6f38f822014-06-06 17:12:20 -0400355 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
356 std::numeric_limits<GLsizei>::max() - xoffset < width ||
357 std::numeric_limits<GLsizei>::max() - yoffset < height ||
358 std::numeric_limits<GLsizei>::max() - zoffset < depth)
359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500360 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400361 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400362 }
363
Geoff Langaae65a42014-05-26 12:43:44 -0400364 const gl::Caps &caps = context->getCaps();
365
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800366 switch (texType)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800368 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800369 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
370 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500372 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800373 return false;
374 }
375 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800377 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400378 ASSERT(level == 0);
379 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
380 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
381 {
382 context->handleError(InvalidValue());
383 return false;
384 }
385 if (isCompressed)
386 {
387 context->handleError(InvalidEnum()
388 << "Rectangle texture cannot have a compressed format.");
389 return false;
390 }
391 break;
392
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800393 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800394 if (!isSubImage && width != height)
395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500396 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800397 return false;
398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399
He Yunchaoced53ae2016-11-29 15:00:51 +0800400 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500402 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800403 return false;
404 }
405 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400406
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800407 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800408 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
409 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
410 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500412 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800413 return false;
414 }
415 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800417 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800418 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
419 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
420 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500422 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800423 return false;
424 }
425 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400426
He Yunchaoced53ae2016-11-29 15:00:51 +0800427 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500428 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
431
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800432 gl::Texture *texture = context->getTargetTexture(texType);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400433 if (!texture)
434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500435 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400436 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400437 }
438
Geoff Lang69cce582015-09-17 13:20:36 -0400439 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500441 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400442 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400443 }
444
445 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400446 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400447 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500448 if (isSubImage && actualInternalFormat == GL_NONE)
449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500450 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500451 return false;
452 }
453
Geoff Langc4e93662017-05-01 10:45:59 -0400454 const gl::InternalFormat &actualFormatInfo = isSubImage
455 ? *texture->getFormat(target, level).info
456 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400457 if (isCompressed)
458 {
tmartino7c102692015-10-02 16:43:40 -0400459 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500461 context->handleError(
462 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400463 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400464 }
465
Geoff Lang966c9402017-04-18 12:38:27 -0400466 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400467 {
Geoff Lang966c9402017-04-18 12:38:27 -0400468 if (!ValidCompressedSubImageSize(
469 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
470 texture->getWidth(target, level), texture->getHeight(target, level)))
471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500472 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400473 return false;
474 }
475
476 if (format != actualInternalFormat)
477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500478 context->handleError(InvalidOperation()
479 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400480 return false;
481 }
Geoff Lang86f81162017-10-30 15:10:45 -0400482
483 if (actualInternalFormat == GL_ETC1_RGB8_OES)
484 {
485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
486 return false;
487 }
Geoff Lang966c9402017-04-18 12:38:27 -0400488 }
489 else
490 {
491 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500493 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400494 return false;
495 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400496 }
497
Geoff Langeb66a6e2016-10-31 13:06:12 -0400498 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400499 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500500 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400501 return false;
502 }
503
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800504 if (texType == TextureType::_3D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500506 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400507 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400508 }
509 }
510 else
511 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800512 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
513 type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400514 {
Geoff Lang5d601382014-07-22 15:14:06 -0400515 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400516 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400517 }
518
519 // Validate sub image parameters
520 if (isSubImage)
521 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500522 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500524 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400525 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400526 }
527
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400528 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500530 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400531 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400532 }
533
534 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
535 std::numeric_limits<GLsizei>::max() - yoffset < height ||
536 std::numeric_limits<GLsizei>::max() - zoffset < depth)
537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500538 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400539 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400540 }
541
Geoff Langa9be0dc2014-12-17 12:34:40 -0500542 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
543 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
544 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500546 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400547 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400548 }
Geoff Langfb052642017-10-24 13:42:09 -0400549
550 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400551 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400552 {
553 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
554 return false;
555 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400556 }
557
Geoff Langdbcced82017-06-06 15:55:54 -0400558 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
Geoff Langdbcced82017-06-06 15:55:54 -0400560 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400561 {
562 return false;
563 }
564
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400565 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400566 gl::Buffer *pixelUnpackBuffer =
567 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400568 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400569 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800570 // ...data is not evenly divisible into the number of bytes needed to store in memory a
571 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400572 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400573 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400574 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400575 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400576 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
577
Geoff Langff5b2d52016-09-07 11:32:23 -0400578 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500580 context->handleError(InvalidOperation()
581 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400582 return false;
583 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400584 }
585
Jamie Madill7a5f7382014-03-05 15:01:24 -0500586 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700587 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500589 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400590 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500591 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400592 }
593
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400594 return true;
595}
596
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597bool ValidateES3TexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800598 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599 GLint level,
600 GLenum internalformat,
601 bool isCompressed,
602 bool isSubImage,
603 GLint xoffset,
604 GLint yoffset,
605 GLint zoffset,
606 GLsizei width,
607 GLsizei height,
608 GLsizei depth,
609 GLint border,
610 GLenum format,
611 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400612 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400613 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500614{
615 if (!ValidTexture2DDestinationTarget(context, target))
616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500617 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500618 return false;
619 }
620
621 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
622 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400623 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500624}
625
626bool ValidateES3TexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800627 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500628 GLint level,
629 GLenum internalformat,
630 bool isCompressed,
631 bool isSubImage,
632 GLint xoffset,
633 GLint yoffset,
634 GLint zoffset,
635 GLsizei width,
636 GLsizei height,
637 GLsizei depth,
638 GLint border,
639 GLenum format,
640 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400641 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400642 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500643{
644 if (!ValidTexture3DDestinationTarget(context, target))
645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500646 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500647 return false;
648 }
649
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800650 if (IsETC2EACFormat(format) && target != TextureType::_2DArray)
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500651 {
652 // ES 3.1, Section 8.7, page 169.
653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
654 return false;
655 }
656
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800657 return ValidateES3TexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
658 internalformat, isCompressed, isSubImage, xoffset,
659 yoffset, zoffset, width, height, depth, border, format,
660 type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500661}
662
Geoff Lang5d601382014-07-22 15:14:06 -0400663struct EffectiveInternalFormatInfo
664{
Jamie Madill76648fe2016-10-05 17:01:41 -0400665 GLenum effectiveFormat;
666 GLenum destFormat;
667 GLuint minRedBits;
668 GLuint maxRedBits;
669 GLuint minGreenBits;
670 GLuint maxGreenBits;
671 GLuint minBlueBits;
672 GLuint maxBlueBits;
673 GLuint minAlphaBits;
674 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400675};
676
Jamie Madill76648fe2016-10-05 17:01:41 -0400677static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
678 GLenum targetFormat,
679 const EffectiveInternalFormatInfo *list,
680 size_t size,
681 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400682{
Jamie Madill76648fe2016-10-05 17:01:41 -0400683 for (size_t curFormat = 0; curFormat < size; ++curFormat)
684 {
685 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
686 if ((formatInfo.destFormat == targetFormat) &&
687 (formatInfo.minRedBits <= srcFormat.redBits &&
688 formatInfo.maxRedBits >= srcFormat.redBits) &&
689 (formatInfo.minGreenBits <= srcFormat.greenBits &&
690 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
691 (formatInfo.minBlueBits <= srcFormat.blueBits &&
692 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
693 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
694 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
695 {
696 *outEffectiveFormat = formatInfo.effectiveFormat;
697 return true;
698 }
699 }
Geoff Lang5d601382014-07-22 15:14:06 -0400700
Jamie Madill76648fe2016-10-05 17:01:41 -0400701 *outEffectiveFormat = GL_NONE;
702 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400703}
704
Jamie Madill76648fe2016-10-05 17:01:41 -0400705bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
706 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400707{
Jamie Madill76648fe2016-10-05 17:01:41 -0400708 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
709 // Effective internal format coresponding to destination internal format and linear source
710 // buffer component sizes.
711 // | Source channel min/max sizes |
712 // Effective Internal Format | N/A | R | G | B | A |
713 // clang-format off
714 constexpr EffectiveInternalFormatInfo list[] = {
715 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
716 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
717 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
718 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
719 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
720 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
721 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
722 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
723 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
724 };
725 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400726
Jamie Madill76648fe2016-10-05 17:01:41 -0400727 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
728}
Geoff Lang5d601382014-07-22 15:14:06 -0400729
Jamie Madill76648fe2016-10-05 17:01:41 -0400730bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
731 const InternalFormat &destFormat,
732 GLenum *outEffectiveFormat)
733{
734 constexpr GLuint umax = UINT_MAX;
735
736 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
737 // Effective internal format coresponding to destination internal format andlinear source buffer
738 // component sizes.
739 // | Source channel min/max sizes |
740 // Effective Internal Format | Dest Format | R | G | B | A |
741 // clang-format off
742 constexpr EffectiveInternalFormatInfo list[] = {
743 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
744 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
745 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
746 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
747 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
748 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
749 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
750 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
751 };
752 // clang-format on
753
754 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
755 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400756}
757
He Yunchaoced53ae2016-11-29 15:00:51 +0800758static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
759 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400760 GLenum *outEffectiveFormat)
761{
Geoff Langca271392017-04-05 12:30:00 -0400762 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400763 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400764 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400765 }
766 else
767 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400768 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400769 }
Geoff Lang5d601382014-07-22 15:14:06 -0400770}
771
Corentin Wallez76287682016-04-25 09:23:38 -0400772static bool EqualOrFirstZero(GLuint first, GLuint second)
773{
774 return first == 0 || first == second;
775}
776
Geoff Langca271392017-04-05 12:30:00 -0400777static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
778 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400779 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400780{
Jamie Madill21b786b2016-11-01 17:41:31 -0400781 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400782 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400783 return false;
784 }
Geoff Lang5d601382014-07-22 15:14:06 -0400785
Jamie Madill21b786b2016-11-01 17:41:31 -0400786 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
787 // must both be signed, unsigned, or fixed point and both source and destinations
788 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
789 // conversion between fixed and floating point.
790
791 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
792 (framebufferFormatInfo.colorEncoding == GL_SRGB))
793 {
794 return false;
795 }
796
797 if (((textureFormatInfo.componentType == GL_INT) !=
798 (framebufferFormatInfo.componentType == GL_INT)) ||
799 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
800 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
801 {
802 return false;
803 }
804
805 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
806 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
807 textureFormatInfo.componentType == GL_FLOAT) &&
808 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
809 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
810 framebufferFormatInfo.componentType == GL_FLOAT))
811 {
812 return false;
813 }
814
815 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
816 // The effective internal format of the source buffer is determined with the following rules
817 // applied in order:
818 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
819 // format then the effective internal format is the source buffer's sized internal format.
820 // * If the source buffer is a texture that was created with an unsized base internal format,
821 // then the effective internal format is the source image array's effective internal
822 // format, as specified by table 3.12, which is determined from the <format> and <type>
823 // that were used when the source image array was specified by TexImage*.
824 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
825 // where Destination Internal Format matches internalformat and where the [source channel
826 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
827 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
828 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800829 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400830 if (readBufferHandle != 0)
831 {
832 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
833 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400834 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400835 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400836 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400837 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400838 else
Geoff Lang5d601382014-07-22 15:14:06 -0400839 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400840 // Renderbuffers cannot be created with an unsized internal format, so this must be an
841 // unsized-format texture. We can use the same table we use when creating textures to
842 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400843 sourceEffectiveFormat =
844 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400845 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400846 }
847 else
848 {
849 // The effective internal format must be derived from the source framebuffer's channel
850 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
851 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400852 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400853 GLenum effectiveFormat;
854 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
855 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400856 {
Geoff Langca271392017-04-05 12:30:00 -0400857 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400858 }
859 else
860 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400861 return false;
862 }
863 }
864 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
865 {
866 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400867 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400868 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
869 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
870 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
871 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
872 {
Geoff Langca271392017-04-05 12:30:00 -0400873 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400874 }
875 else
876 {
877 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400878 }
879 }
880 else
881 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400882 UNREACHABLE();
883 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400884 }
Geoff Lang5d601382014-07-22 15:14:06 -0400885 }
886
Geoff Langca271392017-04-05 12:30:00 -0400887 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400888 {
889 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
890 // sized, component sizes of the source and destination formats must exactly match if the
891 // destination format exists.
892 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
893 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
894 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
895 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
896 {
897 return false;
898 }
899 }
900
901 return true; // A conversion function exists, and no rule in the specification has precluded
902 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400903}
904
Jamie Madill5b772312018-03-08 20:28:32 -0500905bool ValidateES3CopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800906 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500907 GLint level,
908 GLenum internalformat,
909 bool isSubImage,
910 GLint xoffset,
911 GLint yoffset,
912 GLint zoffset,
913 GLint x,
914 GLint y,
915 GLsizei width,
916 GLsizei height,
917 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400918{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400919 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400920 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400921 xoffset, yoffset, zoffset, x, y, width, height, border,
922 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400923 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400924 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400926 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927
Jamie Madill51f40ec2016-06-15 14:06:00 -0400928 const auto &state = context->getGLState();
929 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
930 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400931
Jamie Madill427064d2018-04-13 16:20:34 -0400932 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400933 {
Geoff Langb1196682014-07-23 13:47:29 -0400934 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400935 }
936
Jamie Madille98b1b52018-03-08 09:47:23 -0500937 if (readFramebufferID != 0 && !ValidateFramebufferNotMultisampled(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400938 {
Geoff Langb1196682014-07-23 13:47:29 -0400939 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400940 }
941
Jamie Madill0c8abca2016-07-22 20:21:26 -0400942 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943
Yunchao He096a6c82018-02-27 23:48:21 +0800944 // According to ES 3.x spec, if the internalformat of the texture
945 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
946 if (textureFormat.info->internalFormat == GL_RGB9_E5)
947 {
948 context->handleError(InvalidOperation());
949 return false;
950 }
951
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 if (isSubImage)
953 {
Geoff Langca271392017-04-05 12:30:00 -0400954 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500955 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500957 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400958 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 }
960 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400961 else
962 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400963 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400964 const InternalFormat &framebufferFormat = *source->getFormat().info;
965 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400966 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400969 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400970 }
971 }
972
Geoff Lang784a8fd2013-09-24 12:33:16 -0400973 // If width or height is zero, it is a no-op. Return false without setting an error.
974 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975}
976
Jamie Madill5b772312018-03-08 20:28:32 -0500977bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800978 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500979 GLint level,
980 GLenum internalformat,
981 bool isSubImage,
982 GLint xoffset,
983 GLint yoffset,
984 GLint zoffset,
985 GLint x,
986 GLint y,
987 GLsizei width,
988 GLsizei height,
989 GLint border)
990{
991 if (!ValidTexture2DDestinationTarget(context, target))
992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500993 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500994 return false;
995 }
996
997 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
998 xoffset, yoffset, zoffset, x, y, width, height,
999 border);
1000}
1001
Jamie Madill5b772312018-03-08 20:28:32 -05001002bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001003 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001004 GLint level,
1005 GLenum internalformat,
1006 bool isSubImage,
1007 GLint xoffset,
1008 GLint yoffset,
1009 GLint zoffset,
1010 GLint x,
1011 GLint y,
1012 GLsizei width,
1013 GLsizei height,
1014 GLint border)
1015{
1016 if (!ValidTexture3DDestinationTarget(context, target))
1017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001018 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001019 return false;
1020 }
1021
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001022 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
1023 internalformat, isSubImage, xoffset, yoffset,
1024 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001025}
1026
1027bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001028 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001029 GLsizei levels,
1030 GLenum internalformat,
1031 GLsizei width,
1032 GLsizei height,
1033 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034{
1035 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001037 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001038 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 }
1040
Geoff Langb92c1332015-09-04 12:54:55 -04001041 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001042 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -04001043 {
1044 maxDim = std::max(maxDim, depth);
1045 }
1046
1047 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001049 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052
Geoff Langaae65a42014-05-26 12:43:44 -04001053 const gl::Caps &caps = context->getCaps();
1054
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 switch (target)
1056 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001057 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 {
Geoff Langaae65a42014-05-26 12:43:44 -04001059 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1060 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001062 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001063 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 }
1065 }
1066 break;
1067
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001068 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001069 {
1070 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1071 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1072 {
1073 context->handleError(InvalidValue());
1074 return false;
1075 }
1076 }
1077 break;
1078
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001079 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 if (width != height)
1082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001083 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 }
1086
Geoff Langaae65a42014-05-26 12:43:44 -04001087 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001089 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092 }
1093 break;
1094
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001095 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096 {
Geoff Langaae65a42014-05-26 12:43:44 -04001097 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1098 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1099 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001101 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 }
1104 }
1105 break;
1106
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001107 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 {
Geoff Langaae65a42014-05-26 12:43:44 -04001109 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1110 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1111 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001113 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001114 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 }
1116 }
1117 break;
1118
He Yunchaoced53ae2016-11-29 15:00:51 +08001119 default:
1120 UNREACHABLE();
1121 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001122 }
1123
Geoff Lang691e58c2014-12-19 17:03:25 -05001124 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 if (!texture || texture->id() == 0)
1126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001127 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001128 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001129 }
1130
Geoff Lang69cce582015-09-17 13:20:36 -04001131 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001133 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001134 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135 }
1136
Geoff Langca271392017-04-05 12:30:00 -04001137 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001138 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001140 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001141 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 }
1143
Geoff Langca271392017-04-05 12:30:00 -04001144 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001146 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001148 }
1149
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001150 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001151 {
1152 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1153 return false;
1154 }
1155
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 return true;
1157}
1158
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001159bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001160 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001161 GLsizei levels,
1162 GLenum internalformat,
1163 GLsizei width,
1164 GLsizei height,
1165 GLsizei depth)
1166{
1167 if (!ValidTexture2DTarget(context, target))
1168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001169 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001170 return false;
1171 }
1172
1173 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1174 height, depth);
1175}
1176
1177bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001178 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001179 GLsizei levels,
1180 GLenum internalformat,
1181 GLsizei width,
1182 GLsizei height,
1183 GLsizei depth)
1184{
1185 if (!ValidTexture3DTarget(context, target))
1186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001187 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001188 return false;
1189 }
1190
1191 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1192 height, depth);
1193}
1194
Corentin Wallezad3ae902018-03-09 13:40:42 -05001195bool ValidateBeginQuery(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001196{
Martin Radev1be913c2016-07-11 17:59:16 +03001197 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001198 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001200 return false;
1201 }
1202
1203 return ValidateBeginQueryBase(context, target, id);
1204}
1205
Corentin Wallezad3ae902018-03-09 13:40:42 -05001206bool ValidateEndQuery(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001207{
Martin Radev1be913c2016-07-11 17:59:16 +03001208 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001209 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001211 return false;
1212 }
1213
1214 return ValidateEndQueryBase(context, target);
1215}
1216
Corentin Wallezad3ae902018-03-09 13:40:42 -05001217bool ValidateGetQueryiv(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001218{
Martin Radev1be913c2016-07-11 17:59:16 +03001219 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001220 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001222 return false;
1223 }
1224
Geoff Lang2186c382016-10-14 10:54:54 -04001225 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001226}
1227
1228bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1229{
Martin Radev1be913c2016-07-11 17:59:16 +03001230 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001231 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001232 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001233 return false;
1234 }
1235
Geoff Lang2186c382016-10-14 10:54:54 -04001236 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001237}
1238
He Yunchaoced53ae2016-11-29 15:00:51 +08001239bool ValidateFramebufferTextureLayer(Context *context,
1240 GLenum target,
1241 GLenum attachment,
1242 GLuint texture,
1243 GLint level,
1244 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001245{
Martin Radev1be913c2016-07-11 17:59:16 +03001246 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001247 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001250 }
1251
Jamie Madill55ec3b12014-07-03 10:38:57 -04001252 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1253 {
1254 return false;
1255 }
1256
1257 const gl::Caps &caps = context->getCaps();
1258 if (texture != 0)
1259 {
Geoff Lang23e02842017-10-17 13:24:09 -04001260 if (layer < 0)
1261 {
1262 context->handleError(InvalidValue());
1263 return false;
1264 }
1265
Jamie Madill55ec3b12014-07-03 10:38:57 -04001266 gl::Texture *tex = context->getTexture(texture);
1267 ASSERT(tex);
1268
Corentin Wallez99d492c2018-02-27 15:17:10 -05001269 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001270 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001271 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001272 {
1273 if (level > gl::log2(caps.max2DTextureSize))
1274 {
Olli Etuahofd162102018-08-27 16:14:57 +03001275 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1276 FramebufferTextureInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04001277 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001278 }
1279
1280 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1281 {
Olli Etuahofd162102018-08-27 16:14:57 +03001282 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
Geoff Langb1196682014-07-23 13:47:29 -04001283 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001284 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001285 }
1286 break;
1287
Corentin Wallez99d492c2018-02-27 15:17:10 -05001288 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001289 {
1290 if (level > gl::log2(caps.max3DTextureSize))
1291 {
Olli Etuahofd162102018-08-27 16:14:57 +03001292 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1293 FramebufferTextureInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04001294 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001295 }
1296
1297 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1298 {
Olli Etuahofd162102018-08-27 16:14:57 +03001299 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
1300 return false;
1301 }
1302 }
1303 break;
1304
1305 case TextureType::_2DMultisampleArray:
1306 {
1307 if (level != 0)
1308 {
1309 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1310 FramebufferTextureInvalidMipLevel);
1311 return false;
1312 }
1313
1314 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1315 {
1316 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
Geoff Langb1196682014-07-23 13:47:29 -04001317 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001318 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001319 }
1320 break;
1321
He Yunchaoced53ae2016-11-29 15:00:51 +08001322 default:
Olli Etuahofd162102018-08-27 16:14:57 +03001323 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1324 FramebufferTextureLayerIncorrectTextureType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001326 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001327
Corentin Wallez99d492c2018-02-27 15:17:10 -05001328 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001329 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001332 return false;
1333 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001334 }
1335
1336 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001337}
1338
He Yunchaoced53ae2016-11-29 15:00:51 +08001339bool ValidateInvalidateFramebuffer(Context *context,
1340 GLenum target,
1341 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001342 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343{
Martin Radev1be913c2016-07-11 17:59:16 +03001344 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001345 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001346 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001347 return false;
1348 }
1349
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 bool defaultFramebuffer = false;
1351
1352 switch (target)
1353 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001354 case GL_DRAW_FRAMEBUFFER:
1355 case GL_FRAMEBUFFER:
1356 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1357 break;
1358 case GL_READ_FRAMEBUFFER:
1359 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1360 break;
1361 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001362 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 }
1365
He Yunchaoced53ae2016-11-29 15:00:51 +08001366 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1367 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368}
1369
Jamie Madill3ef140a2017-08-26 23:11:21 -04001370bool ValidateInvalidateSubFramebuffer(Context *context,
1371 GLenum target,
1372 GLsizei numAttachments,
1373 const GLenum *attachments,
1374 GLint x,
1375 GLint y,
1376 GLsizei width,
1377 GLsizei height)
1378{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001379 if (width < 0 || height < 0)
1380 {
1381 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1382 return false;
1383 }
1384
Jamie Madill3ef140a2017-08-26 23:11:21 -04001385 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1386}
1387
Jamie Madill5b772312018-03-08 20:28:32 -05001388bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001389{
Martin Radev1be913c2016-07-11 17:59:16 +03001390 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001391 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001393 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001394 }
1395
Jamie Madill427064d2018-04-13 16:20:34 -04001396 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001397 {
Geoff Langb1196682014-07-23 13:47:29 -04001398 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001399 }
1400
1401 return true;
1402}
1403
Olli Etuaho71dfb362016-03-10 14:04:27 +02001404bool ValidateDrawRangeElements(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001405 PrimitiveMode mode,
Olli Etuaho71dfb362016-03-10 14:04:27 +02001406 GLuint start,
1407 GLuint end,
1408 GLsizei count,
1409 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001410 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001411{
Martin Radev1be913c2016-07-11 17:59:16 +03001412 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001413 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001415 return false;
1416 }
1417
1418 if (end < start)
1419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001420 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001421 return false;
1422 }
1423
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001424 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001425 {
1426 return false;
1427 }
1428
Jamie Madill9fdaa492018-02-16 10:52:11 -05001429 // Skip range checks for no-op calls.
1430 if (count <= 0)
1431 {
1432 return true;
1433 }
1434
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001435 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04001436 const DrawCallParams &params = context->getParams<DrawCallParams>();
1437 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001438
Jamie Madill6f5444d2018-03-14 10:08:11 -04001439 const IndexRange &indexRange = params.getIndexRange();
1440
1441 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001442 {
1443 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001445 return false;
1446 }
1447 return true;
1448}
1449
He Yunchaoced53ae2016-11-29 15:00:51 +08001450bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001451{
Martin Radev1be913c2016-07-11 17:59:16 +03001452 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001453 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001454 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001455 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001456 }
1457
Jamie Madill78f41802014-08-25 15:47:55 -04001458 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001459}
1460
Jamie Madillb885e572015-02-03 16:16:04 -05001461bool ValidateReadBuffer(Context *context, GLenum src)
1462{
Martin Radev1be913c2016-07-11 17:59:16 +03001463 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001464 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001466 return false;
1467 }
1468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001469 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001470
1471 if (readFBO == nullptr)
1472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001473 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001474 return false;
1475 }
1476
1477 if (src == GL_NONE)
1478 {
1479 return true;
1480 }
1481
Olli Etuaho84c9f592016-03-09 14:37:25 +02001482 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001484 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001485 return false;
1486 }
1487
1488 if (readFBO->id() == 0)
1489 {
1490 if (src != GL_BACK)
1491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001492 context->handleError(
1493 InvalidOperation()
1494 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001495 return false;
1496 }
1497 }
1498 else
1499 {
1500 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1501
1502 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001504 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001505 return false;
1506 }
1507 }
1508
1509 return true;
1510}
1511
Jamie Madill86af3d22015-07-21 15:14:07 -04001512bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001513 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001514 GLint level,
1515 GLenum internalformat,
1516 GLsizei width,
1517 GLsizei height,
1518 GLsizei depth,
1519 GLint border,
1520 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001521 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001522{
Martin Radev1be913c2016-07-11 17:59:16 +03001523 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001524 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001525 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001526 return false;
1527 }
1528
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001529 if (!ValidTextureTarget(context, target))
1530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001531 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001532 return false;
1533 }
1534
Jamie Madille2e406c2016-06-02 13:04:10 -04001535 // Validate image size
1536 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001539 return false;
1540 }
1541
Geoff Langca271392017-04-05 12:30:00 -04001542 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001543 if (!formatInfo.compressed)
1544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001545 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001546 return false;
1547 }
1548
Jamie Madillca2ff382018-07-11 09:01:17 -04001549 GLuint blockSize = 0;
1550 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001552 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001553 return false;
1554 }
Jamie Madillca2ff382018-07-11 09:01:17 -04001555
1556 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill86af3d22015-07-21 15:14:07 -04001557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001558 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001559 return false;
1560 }
1561
1562 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001563 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001565 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001566 return false;
1567 }
1568
1569 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001570 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001571 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1572 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001573 {
1574 return false;
1575 }
1576
1577 return true;
1578}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001579
Corentin Wallezb2931602017-04-11 15:58:57 -04001580bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001581 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001582 GLint level,
1583 GLenum internalformat,
1584 GLsizei width,
1585 GLsizei height,
1586 GLsizei depth,
1587 GLint border,
1588 GLsizei imageSize,
1589 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001590 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001591{
1592 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1593 {
1594 return false;
1595 }
1596
1597 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1598 depth, border, imageSize, data);
1599}
1600
Austin Kinrossbc781f32015-10-26 09:27:38 -07001601bool ValidateBindVertexArray(Context *context, GLuint array)
1602{
Martin Radev1be913c2016-07-11 17:59:16 +03001603 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001604 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001606 return false;
1607 }
1608
1609 return ValidateBindVertexArrayBase(context, array);
1610}
1611
Jamie Madilld7576732017-08-26 18:49:50 -04001612bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001613{
Martin Radev1be913c2016-07-11 17:59:16 +03001614 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001615 {
Jamie Madilld7576732017-08-26 18:49:50 -04001616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001617 return false;
1618 }
1619
1620 return true;
1621}
Geoff Langc5629752015-12-07 16:29:04 -05001622
Jiajia Qin6eafb042016-12-27 17:04:07 +08001623static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001624 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001625 GLuint index,
1626 GLuint buffer,
1627 GLintptr offset,
1628 GLsizeiptr size)
1629{
1630 if (context->getClientMajorVersion() < 3)
1631 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001633 return false;
1634 }
1635
1636 if (buffer != 0 && offset < 0)
1637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001639 return false;
1640 }
1641
1642 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1643 !context->isBufferGenerated(buffer))
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001646 return false;
1647 }
1648
1649 const Caps &caps = context->getCaps();
1650 switch (target)
1651 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001652 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001653 {
1654 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidValue() << "index is greater than or equal to the "
1657 "number of TRANSFORM_FEEDBACK_BUFFER "
1658 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001659 return false;
1660 }
1661 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001664 return false;
1665 }
1666
1667 TransformFeedback *curTransformFeedback =
1668 context->getGLState().getCurrentTransformFeedback();
1669 if (curTransformFeedback && curTransformFeedback->isActive())
1670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001671 context->handleError(InvalidOperation()
1672 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1673 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001674 return false;
1675 }
1676 break;
1677 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001678 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001679 {
1680 if (index >= caps.maxUniformBufferBindings)
1681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001682 context->handleError(InvalidValue() << "index is greater than or equal to the "
1683 "number of UNIFORM_BUFFER indexed "
1684 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001685 return false;
1686 }
1687
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001688 ASSERT(caps.uniformBufferOffsetAlignment);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001689 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1690 {
1691 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001692 InvalidValue()
1693 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001694 return false;
1695 }
1696 break;
1697 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001698 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001699 {
1700 if (context->getClientVersion() < ES_3_1)
1701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(InvalidEnum()
1703 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001704 return false;
1705 }
1706 if (index >= caps.maxAtomicCounterBufferBindings)
1707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001708 context->handleError(InvalidValue() << "index is greater than or equal to the "
1709 "number of ATOMIC_COUNTER_BUFFER "
1710 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001711 return false;
1712 }
1713 if (buffer != 0 && (offset % 4) != 0)
1714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001716 return false;
1717 }
1718 break;
1719 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001720 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001721 {
1722 if (context->getClientVersion() < ES_3_1)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidEnum()
1725 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001726 return false;
1727 }
1728 if (index >= caps.maxShaderStorageBufferBindings)
1729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidValue() << "index is greater than or equal to the "
1731 "number of SHADER_STORAGE_BUFFER "
1732 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001733 return false;
1734 }
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001735 ASSERT(caps.shaderStorageBufferOffsetAlignment);
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001736 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001738 context->handleError(InvalidValue() << "offset must be multiple of value of "
1739 "SHADER_STORAGE_BUFFER_OFFSET_"
1740 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001741 return false;
1742 }
1743 break;
1744 }
1745 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001746 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001747 return false;
1748 }
1749
1750 return true;
1751}
1752
Corentin Wallez336129f2017-10-17 15:55:40 -04001753bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001754{
1755 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1756}
1757
1758bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001759 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001760 GLuint index,
1761 GLuint buffer,
1762 GLintptr offset,
1763 GLsizeiptr size)
1764{
1765 if (buffer != 0 && size <= 0)
1766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001767 context->handleError(InvalidValue()
1768 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001769 return false;
1770 }
1771 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1772}
1773
Geoff Langc5629752015-12-07 16:29:04 -05001774bool ValidateProgramBinary(Context *context,
1775 GLuint program,
1776 GLenum binaryFormat,
1777 const void *binary,
1778 GLint length)
1779{
Martin Radev1be913c2016-07-11 17:59:16 +03001780 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001781 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001783 return false;
1784 }
1785
1786 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1787}
1788
1789bool ValidateGetProgramBinary(Context *context,
1790 GLuint program,
1791 GLsizei bufSize,
1792 GLsizei *length,
1793 GLenum *binaryFormat,
1794 void *binary)
1795{
Martin Radev1be913c2016-07-11 17:59:16 +03001796 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001797 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001799 return false;
1800 }
1801
1802 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1803}
1804
Olli Etuahof0fee072016-03-30 15:11:58 +03001805bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001806{
Martin Radev1be913c2016-07-11 17:59:16 +03001807 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001808 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001809 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001810 return false;
1811 }
1812
1813 if (GetValidProgram(context, program) == nullptr)
1814 {
1815 return false;
1816 }
1817
1818 switch (pname)
1819 {
1820 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001821 if (value != GL_FALSE && value != GL_TRUE)
1822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001823 context->handleError(InvalidValue()
1824 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001825 return false;
1826 }
Geoff Langc5629752015-12-07 16:29:04 -05001827 break;
1828
Yunchao He61afff12017-03-14 15:34:03 +08001829 case GL_PROGRAM_SEPARABLE:
1830 if (context->getClientVersion() < ES_3_1)
1831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001832 context->handleError(InvalidEnum()
1833 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001834 return false;
1835 }
1836
1837 if (value != GL_FALSE && value != GL_TRUE)
1838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidValue()
1840 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001841 return false;
1842 }
1843 break;
1844
Geoff Langc5629752015-12-07 16:29:04 -05001845 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001846 context->handleError(InvalidEnum()
1847 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001848 return false;
1849 }
1850
1851 return true;
1852}
Jamie Madillc29968b2016-01-20 11:17:23 -05001853
1854bool ValidateBlitFramebuffer(Context *context,
1855 GLint srcX0,
1856 GLint srcY0,
1857 GLint srcX1,
1858 GLint srcY1,
1859 GLint dstX0,
1860 GLint dstY0,
1861 GLint dstX1,
1862 GLint dstY1,
1863 GLbitfield mask,
1864 GLenum filter)
1865{
Martin Radev1be913c2016-07-11 17:59:16 +03001866 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001867 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 return false;
1870 }
1871
1872 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1873 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001874}
Jamie Madillc29968b2016-01-20 11:17:23 -05001875
Jamie Madill5b772312018-03-08 20:28:32 -05001876bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001877{
1878 switch (buffer)
1879 {
1880 case GL_COLOR:
1881 if (drawbuffer < 0 ||
1882 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001884 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001885 return false;
1886 }
Geoff Lang76e65652017-03-27 14:58:02 -04001887 if (context->getExtensions().webglCompatibility)
1888 {
1889 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001890 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001891 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1892 {
1893 return false;
1894 }
1895 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001896 break;
1897
1898 case GL_STENCIL:
1899 if (drawbuffer != 0)
1900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001901 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001902 return false;
1903 }
1904 break;
1905
1906 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001907 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
1909 }
1910
1911 return ValidateClearBuffer(context);
1912}
1913
Jamie Madill5b772312018-03-08 20:28:32 -05001914bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001915{
1916 switch (buffer)
1917 {
1918 case GL_COLOR:
1919 if (drawbuffer < 0 ||
1920 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001922 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001923 return false;
1924 }
Geoff Lang76e65652017-03-27 14:58:02 -04001925 if (context->getExtensions().webglCompatibility)
1926 {
1927 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001928 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001929 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1930 {
1931 return false;
1932 }
1933 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001934 break;
1935
1936 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001937 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001938 return false;
1939 }
1940
1941 return ValidateClearBuffer(context);
1942}
1943
Jamie Madill5b772312018-03-08 20:28:32 -05001944bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001945{
1946 switch (buffer)
1947 {
1948 case GL_COLOR:
1949 if (drawbuffer < 0 ||
1950 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001953 return false;
1954 }
Geoff Lang76e65652017-03-27 14:58:02 -04001955 if (context->getExtensions().webglCompatibility)
1956 {
1957 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1958 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001959 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001960 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1961 {
1962 return false;
1963 }
1964 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001965 break;
1966
1967 case GL_DEPTH:
1968 if (drawbuffer != 0)
1969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001970 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001971 return false;
1972 }
1973 break;
1974
1975 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001976 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001977 return false;
1978 }
1979
1980 return ValidateClearBuffer(context);
1981}
1982
Jamie Madill5b772312018-03-08 20:28:32 -05001983bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001984 GLenum buffer,
1985 GLint drawbuffer,
1986 GLfloat depth,
1987 GLint stencil)
1988{
1989 switch (buffer)
1990 {
1991 case GL_DEPTH_STENCIL:
1992 if (drawbuffer != 0)
1993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001994 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001995 return false;
1996 }
1997 break;
1998
1999 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002000 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05002001 return false;
2002 }
2003
2004 return ValidateClearBuffer(context);
2005}
2006
Jamie Madill5b772312018-03-08 20:28:32 -05002007bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05002008{
Martin Radev1be913c2016-07-11 17:59:16 +03002009 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002010 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05002012 return false;
2013 }
2014
2015 return ValidateDrawBuffersBase(context, n, bufs);
2016}
2017
2018bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002019 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002020 GLint level,
2021 GLint xoffset,
2022 GLint yoffset,
2023 GLint zoffset,
2024 GLint x,
2025 GLint y,
2026 GLsizei width,
2027 GLsizei height)
2028{
Martin Radev1be913c2016-07-11 17:59:16 +03002029 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002030 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 return false;
2033 }
2034
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002035 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
2036 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05002037}
2038
Brandon Jones4e6f2ae2018-09-19 11:09:51 -07002039bool ValidateCopyTexture3DANGLE(Context *context,
2040 GLuint sourceId,
2041 GLint sourceLevel,
2042 TextureTarget destTarget,
2043 GLuint destId,
2044 GLint destLevel,
2045 GLint internalFormat,
2046 GLenum destType,
2047 GLboolean unpackFlipY,
2048 GLboolean unpackPremultiplyAlpha,
2049 GLboolean unpackUnmultiplyAlpha)
2050{
2051 const Texture *source = context->getTexture(sourceId);
2052 if (source == nullptr)
2053 {
2054 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSourceTexture);
2055 return false;
2056 }
2057
2058 TextureType sourceType = source->getType();
2059 ASSERT(sourceType != TextureType::CubeMap);
2060 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2061 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2062
2063 const Texture *dest = context->getTexture(destId);
2064 if (dest == nullptr)
2065 {
2066 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidDestinationTexture);
2067 return false;
2068 }
2069
2070 if (!ValidateCopyTexture3DCommon(context, source, sourceLevel,
2071 sourceFormat.info->internalFormat, dest, destLevel,
2072 internalFormat, destTarget))
2073 {
2074 return false;
2075 }
2076
2077 if (!ValidMipLevel(context, source->getType(), sourceLevel))
2078 {
2079 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSourceTextureLevel);
2080 return false;
2081 }
2082
2083 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
2084 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
2085 if (sourceWidth == 0 || sourceHeight == 0)
2086 {
2087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSourceTextureSize);
2088 return false;
2089 }
2090
2091 if (dest->getImmutableFormat())
2092 {
2093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DestinationImmutable);
2094 return false;
2095 }
2096
2097 return true;
2098}
2099
2100bool ValidateCopySubTexture3DANGLE(Context *context,
2101 GLuint sourceId,
2102 GLint sourceLevel,
2103 TextureTarget destTarget,
2104 GLuint destId,
2105 GLint destLevel,
2106 GLint xoffset,
2107 GLint yoffset,
2108 GLint zoffset,
2109 GLint x,
2110 GLint y,
2111 GLint z,
2112 GLsizei width,
2113 GLsizei height,
2114 GLsizei depth,
2115 GLboolean unpackFlipY,
2116 GLboolean unpackPremultiplyAlpha,
2117 GLboolean unpackUnmultiplyAlpha)
2118{
2119 const Texture *source = context->getTexture(sourceId);
2120 if (source == nullptr)
2121 {
2122 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSourceTexture);
2123 return false;
2124 }
2125
2126 TextureType sourceType = source->getType();
2127 ASSERT(sourceType != TextureType::CubeMap);
2128 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2129 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2130
2131 const Texture *dest = context->getTexture(destId);
2132 if (dest == nullptr)
2133 {
2134 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidDestinationTexture);
2135 return false;
2136 }
2137
2138 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
2139
2140 if (!ValidateCopyTexture3DCommon(context, source, sourceLevel,
2141 sourceFormat.info->internalFormat, dest, destLevel,
2142 destFormat.internalFormat, destTarget))
2143 {
2144 return false;
2145 }
2146
2147 if (x < 0 || y < 0 || z < 0)
2148 {
2149 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeXYZ);
2150 return false;
2151 }
2152
2153 if (width < 0 || height < 0 || depth < 0)
2154 {
2155 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeHeightWidthDepth);
2156 return false;
2157 }
2158
2159 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
2160 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
2161 static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
2162 {
2163 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
2164 return false;
2165 }
2166
2167 if (TextureTargetToType(destTarget) != dest->getType())
2168 {
2169 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidDestinationTextureType);
2170 return false;
2171 }
2172
2173 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2174 {
2175 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2176 return false;
2177 }
2178
2179 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
2180 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
2181 static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
2182 {
2183 ANGLE_VALIDATION_ERR(context, InvalidValue(), DestinationTextureTooSmall);
2184 return false;
2185 }
2186
2187 return true;
2188}
2189
Jamie Madill73a84962016-02-12 09:27:23 -05002190bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002191 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002192 GLint level,
2193 GLint internalformat,
2194 GLsizei width,
2195 GLsizei height,
2196 GLsizei depth,
2197 GLint border,
2198 GLenum format,
2199 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002200 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002201{
Martin Radev1be913c2016-07-11 17:59:16 +03002202 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002203 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002205 return false;
2206 }
2207
2208 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04002209 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002210 pixels);
2211}
2212
Geoff Langc52f6f12016-10-14 10:18:00 -04002213bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002214 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04002215 GLint level,
2216 GLint internalformat,
2217 GLsizei width,
2218 GLsizei height,
2219 GLsizei depth,
2220 GLint border,
2221 GLenum format,
2222 GLenum type,
2223 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002224 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002225{
2226 if (context->getClientMajorVersion() < 3)
2227 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04002229 return false;
2230 }
2231
2232 if (!ValidateRobustEntryPoint(context, bufSize))
2233 {
2234 return false;
2235 }
2236
2237 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
2238 0, 0, width, height, depth, border, format, type,
2239 bufSize, pixels);
2240}
2241
Jamie Madill73a84962016-02-12 09:27:23 -05002242bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002243 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002244 GLint level,
2245 GLint xoffset,
2246 GLint yoffset,
2247 GLint zoffset,
2248 GLsizei width,
2249 GLsizei height,
2250 GLsizei depth,
2251 GLenum format,
2252 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002253 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002254{
Martin Radev1be913c2016-07-11 17:59:16 +03002255 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002256 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002258 return false;
2259 }
2260
2261 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2262 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04002263 -1, pixels);
2264}
2265
2266bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002267 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04002268 GLint level,
2269 GLint xoffset,
2270 GLint yoffset,
2271 GLint zoffset,
2272 GLsizei width,
2273 GLsizei height,
2274 GLsizei depth,
2275 GLenum format,
2276 GLenum type,
2277 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002278 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002279{
2280 if (context->getClientMajorVersion() < 3)
2281 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04002283 return false;
2284 }
2285
2286 if (!ValidateRobustEntryPoint(context, bufSize))
2287 {
2288 return false;
2289 }
2290
2291 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2292 yoffset, zoffset, width, height, depth, 0, format, type,
2293 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002294}
2295
2296bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002297 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002298 GLint level,
2299 GLint xoffset,
2300 GLint yoffset,
2301 GLint zoffset,
2302 GLsizei width,
2303 GLsizei height,
2304 GLsizei depth,
2305 GLenum format,
2306 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002307 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002308{
Martin Radev1be913c2016-07-11 17:59:16 +03002309 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002310 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002312 return false;
2313 }
2314
Geoff Langca271392017-04-05 12:30:00 -04002315 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002316 if (!formatInfo.compressed)
2317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002318 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002319 return false;
2320 }
2321
Jamie Madillca2ff382018-07-11 09:01:17 -04002322 GLuint blockSize = 0;
2323 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002324 {
Jamie Madillca2ff382018-07-11 09:01:17 -04002325 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madille2e406c2016-06-02 13:04:10 -04002326 return false;
2327 }
Jamie Madillca2ff382018-07-11 09:01:17 -04002328
2329 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill73a84962016-02-12 09:27:23 -05002330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002331 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002332 return false;
2333 }
2334
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002335 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2336 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2337 -1, data))
2338 {
2339 return false;
2340 }
2341
Jamie Madill73a84962016-02-12 09:27:23 -05002342 if (!data)
2343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002344 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002345 return false;
2346 }
2347
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002348 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002349}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002350
Corentin Wallezb2931602017-04-11 15:58:57 -04002351bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002352 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002353 GLint level,
2354 GLint xoffset,
2355 GLint yoffset,
2356 GLint zoffset,
2357 GLsizei width,
2358 GLsizei height,
2359 GLsizei depth,
2360 GLenum format,
2361 GLsizei imageSize,
2362 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002363 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002364{
2365 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2366 {
2367 return false;
2368 }
2369
2370 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2371 height, depth, format, imageSize, data);
2372}
Jamie Madill73a84962016-02-12 09:27:23 -05002373
Olli Etuaho41997e72016-03-10 13:38:39 +02002374bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2375{
2376 return ValidateGenOrDeleteES3(context, n);
2377}
2378
2379bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2380{
2381 return ValidateGenOrDeleteES3(context, n);
2382}
2383
2384bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2385{
2386 return ValidateGenOrDeleteCountES3(context, count);
2387}
2388
2389bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2390{
2391 return ValidateGenOrDeleteCountES3(context, count);
2392}
2393
2394bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2395{
2396 return ValidateGenOrDeleteES3(context, n);
2397}
2398
2399bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2400{
2401 if (!ValidateGenOrDeleteES3(context, n))
2402 {
2403 return false;
2404 }
2405 for (GLint i = 0; i < n; ++i)
2406 {
2407 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2408 if (transformFeedback != nullptr && transformFeedback->isActive())
2409 {
2410 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002411 context->handleError(InvalidOperation()
2412 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002413 return false;
2414 }
2415 }
2416 return true;
2417}
2418
2419bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2420{
2421 return ValidateGenOrDeleteES3(context, n);
2422}
2423
2424bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2425{
2426 return ValidateGenOrDeleteES3(context, n);
2427}
2428
Jamie Madill493f9572018-05-24 19:52:15 -04002429bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMode)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002430{
Martin Radev1be913c2016-07-11 17:59:16 +03002431 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002432 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002434 return false;
2435 }
2436 switch (primitiveMode)
2437 {
Jamie Madill493f9572018-05-24 19:52:15 -04002438 case PrimitiveMode::Triangles:
2439 case PrimitiveMode::Lines:
2440 case PrimitiveMode::Points:
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002441 break;
2442
2443 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002444 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002445 return false;
2446 }
2447
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002448 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002449 ASSERT(transformFeedback != nullptr);
2450
2451 if (transformFeedback->isActive())
2452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002453 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002454 return false;
2455 }
Geoff Lang79f71042017-08-14 16:43:43 -04002456
2457 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2458 {
2459 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2460 if (buffer.get() && buffer->isMapped())
2461 {
2462 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2463 return false;
2464 }
2465 }
2466
Jamie Madill44a6fbf2018-10-02 13:38:56 -04002467 Program *program = context->getGLState().getLinkedProgram();
Olli Etuaho02032bd2017-10-13 18:10:17 +03002468
2469 if (!program)
2470 {
2471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2472 return false;
2473 }
2474
2475 if (program->getTransformFeedbackVaryingCount() == 0)
2476 {
2477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2478 return false;
2479 }
2480
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002481 return true;
2482}
2483
Corentin Wallez336129f2017-10-17 15:55:40 -04002484bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002485{
Geoff Lang496c02d2016-10-20 11:38:11 -07002486 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2487}
2488
2489bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002490 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002491 GLenum pname,
2492 GLsizei bufSize,
2493 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002494 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002495{
2496 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002497 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002498 return false;
2499 }
2500
Brandon Jonesd1049182018-03-28 10:02:20 -07002501 GLsizei numParams = 0;
2502
2503 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002504 {
2505 return false;
2506 }
2507
Brandon Jonesd1049182018-03-28 10:02:20 -07002508 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002509 {
2510 return false;
2511 }
2512
Brandon Jonesd1049182018-03-28 10:02:20 -07002513 SetRobustLengthParam(length, numParams);
2514
Geoff Lang496c02d2016-10-20 11:38:11 -07002515 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002516}
2517
Corentin Wallez336129f2017-10-17 15:55:40 -04002518bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002519{
Martin Radev1be913c2016-07-11 17:59:16 +03002520 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002521 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002523 return false;
2524 }
2525
2526 return ValidateUnmapBufferBase(context, target);
2527}
2528
2529bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002530 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002531 GLintptr offset,
2532 GLsizeiptr length,
2533 GLbitfield access)
2534{
Martin Radev1be913c2016-07-11 17:59:16 +03002535 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002536 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002538 return false;
2539 }
2540
2541 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2542}
2543
2544bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002545 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002546 GLintptr offset,
2547 GLsizeiptr length)
2548{
Martin Radev1be913c2016-07-11 17:59:16 +03002549 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002550 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002552 return false;
2553 }
2554
2555 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2556}
2557
Jamie Madill5b772312018-03-08 20:28:32 -05002558bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002559{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002560 if (length)
2561 {
2562 *length = 0;
2563 }
2564
Martin Radev66fb8202016-07-28 11:45:20 +03002565 GLenum nativeType;
2566 unsigned int numParams;
2567 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002569 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002570 return false;
2571 }
2572
2573 const Caps &caps = context->getCaps();
2574 switch (pname)
2575 {
2576 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2577 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2578 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2579 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002581 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002582 return false;
2583 }
2584 break;
2585
2586 case GL_UNIFORM_BUFFER_START:
2587 case GL_UNIFORM_BUFFER_SIZE:
2588 case GL_UNIFORM_BUFFER_BINDING:
2589 if (index >= caps.maxUniformBufferBindings)
2590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002591 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002592 return false;
2593 }
2594 break;
Shao80957d92017-02-20 21:25:59 +08002595
Martin Radev66fb8202016-07-28 11:45:20 +03002596 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2597 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2598 if (index >= 3u)
2599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002600 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002601 return false;
2602 }
2603 break;
Shao80957d92017-02-20 21:25:59 +08002604
Jiajia Qin6eafb042016-12-27 17:04:07 +08002605 case GL_ATOMIC_COUNTER_BUFFER_START:
2606 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2607 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2608 if (context->getClientVersion() < ES_3_1)
2609 {
2610 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002611 InvalidEnum()
2612 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002613 return false;
2614 }
2615 if (index >= caps.maxAtomicCounterBufferBindings)
2616 {
2617 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002618 InvalidValue()
2619 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002620 return false;
2621 }
2622 break;
Shao80957d92017-02-20 21:25:59 +08002623
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002624 case GL_SHADER_STORAGE_BUFFER_START:
2625 case GL_SHADER_STORAGE_BUFFER_SIZE:
2626 case GL_SHADER_STORAGE_BUFFER_BINDING:
2627 if (context->getClientVersion() < ES_3_1)
2628 {
2629 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 InvalidEnum()
2631 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002632 return false;
2633 }
2634 if (index >= caps.maxShaderStorageBufferBindings)
2635 {
2636 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002637 InvalidValue()
2638 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002639 return false;
2640 }
2641 break;
2642
Shao80957d92017-02-20 21:25:59 +08002643 case GL_VERTEX_BINDING_BUFFER:
2644 case GL_VERTEX_BINDING_DIVISOR:
2645 case GL_VERTEX_BINDING_OFFSET:
2646 case GL_VERTEX_BINDING_STRIDE:
2647 if (context->getClientVersion() < ES_3_1)
2648 {
2649 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002650 InvalidEnum()
2651 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002652 return false;
2653 }
2654 if (index >= caps.maxVertexAttribBindings)
2655 {
2656 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002657 InvalidValue()
2658 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002659 return false;
2660 }
2661 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002662 case GL_SAMPLE_MASK_VALUE:
2663 if (context->getClientVersion() < ES_3_1)
2664 {
2665 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2666 return false;
2667 }
2668 if (index >= caps.maxSampleMaskWords)
2669 {
2670 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2671 return false;
2672 }
2673 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002674 case GL_IMAGE_BINDING_NAME:
2675 case GL_IMAGE_BINDING_LEVEL:
2676 case GL_IMAGE_BINDING_LAYERED:
2677 case GL_IMAGE_BINDING_LAYER:
2678 case GL_IMAGE_BINDING_ACCESS:
2679 case GL_IMAGE_BINDING_FORMAT:
2680 if (context->getClientVersion() < ES_3_1)
2681 {
2682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2683 return false;
2684 }
2685 if (index >= caps.maxImageUnits)
2686 {
2687 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2688 return false;
2689 }
2690 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002691 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002692 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002693 return false;
2694 }
2695
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002696 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002697 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002698 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002699 }
2700
2701 return true;
2702}
2703
Jamie Madill5b772312018-03-08 20:28:32 -05002704bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002705{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002706 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002707 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002709 return false;
2710 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002711 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002712}
2713
Jamie Madill5b772312018-03-08 20:28:32 -05002714bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002715 GLenum target,
2716 GLuint index,
2717 GLsizei bufSize,
2718 GLsizei *length,
2719 GLint *data)
2720{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002721 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002722 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002724 return false;
2725 }
2726
2727 if (!ValidateRobustEntryPoint(context, bufSize))
2728 {
2729 return false;
2730 }
2731
Brandon Jonesd1049182018-03-28 10:02:20 -07002732 GLsizei numParams = 0;
2733
2734 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002735 {
2736 return false;
2737 }
2738
Brandon Jonesd1049182018-03-28 10:02:20 -07002739 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002740 {
2741 return false;
2742 }
2743
Brandon Jonesd1049182018-03-28 10:02:20 -07002744 SetRobustLengthParam(length, numParams);
2745
Geoff Langcf255ea2016-10-20 11:39:09 -07002746 return true;
2747}
2748
Jamie Madill5b772312018-03-08 20:28:32 -05002749bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002750{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002751 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002752 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002754 return false;
2755 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002756 return ValidateIndexedStateQuery(context, target, index, nullptr);
2757}
2758
Jamie Madill5b772312018-03-08 20:28:32 -05002759bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002760 GLenum target,
2761 GLuint index,
2762 GLsizei bufSize,
2763 GLsizei *length,
2764 GLint64 *data)
2765{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002766 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002767 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002768 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002769 return false;
2770 }
2771
2772 if (!ValidateRobustEntryPoint(context, bufSize))
2773 {
2774 return false;
2775 }
2776
Brandon Jonesd1049182018-03-28 10:02:20 -07002777 GLsizei numParams = 0;
2778
2779 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002780 {
2781 return false;
2782 }
2783
Brandon Jonesd1049182018-03-28 10:02:20 -07002784 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002785 {
2786 return false;
2787 }
2788
Brandon Jonesd1049182018-03-28 10:02:20 -07002789 SetRobustLengthParam(length, numParams);
2790
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002791 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002792}
2793
Jamie Madill5b772312018-03-08 20:28:32 -05002794bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002795 BufferBinding readTarget,
2796 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002797 GLintptr readOffset,
2798 GLintptr writeOffset,
2799 GLsizeiptr size)
2800{
2801 if (context->getClientMajorVersion() < 3)
2802 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002804 return false;
2805 }
2806
Corentin Walleze4477002017-12-01 14:39:58 -05002807 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002809 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002810 return false;
2811 }
2812
2813 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2814 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2815
2816 if (!readBuffer || !writeBuffer)
2817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002818 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002819 return false;
2820 }
2821
2822 // Verify that readBuffer and writeBuffer are not currently mapped
2823 if (readBuffer->isMapped() || writeBuffer->isMapped())
2824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002825 context->handleError(InvalidOperation()
2826 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002827 return false;
2828 }
2829
James Darpiniane8a93c62018-01-04 18:02:24 -08002830 if (context->getExtensions().webglCompatibility &&
2831 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2832 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2833 {
2834 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2835 return false;
2836 }
2837
Jamie Madilld2f0c742016-11-02 10:34:41 -04002838 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2839 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2840 CheckedNumeric<GLintptr> checkedSize(size);
2841
2842 auto checkedReadSum = checkedReadOffset + checkedSize;
2843 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2844
2845 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2846 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2847 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002849 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002850 return false;
2851 }
2852
Jamie Madilld2f0c742016-11-02 10:34:41 -04002853 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002855 context->handleError(InvalidValue()
2856 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002857 return false;
2858 }
2859
Jamie Madilld2f0c742016-11-02 10:34:41 -04002860 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2861 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002863 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002864 return false;
2865 }
2866
2867 if (readBuffer == writeBuffer)
2868 {
2869 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2870 if (!checkedOffsetDiff.IsValid())
2871 {
2872 // This shold not be possible.
2873 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002874 context->handleError(InvalidValue()
2875 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002876 return false;
2877 }
2878
2879 if (checkedOffsetDiff.ValueOrDie() < size)
2880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002881 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002882 return false;
2883 }
2884 }
2885
Jamie Madillb0817d12016-11-01 15:48:31 -04002886 return true;
2887}
2888
Geoff Langc339c4e2016-11-29 10:37:36 -05002889bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2890{
2891 if (context->getClientMajorVersion() < 3)
2892 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002893 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002894 return false;
2895 }
2896
2897 switch (name)
2898 {
2899 case GL_EXTENSIONS:
2900 if (index >= context->getExtensionStringCount())
2901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002902 context->handleError(InvalidValue()
2903 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002904 return false;
2905 }
2906 break;
2907
2908 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2909 if (!context->getExtensions().requestExtension)
2910 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002912 return false;
2913 }
2914 if (index >= context->getRequestableExtensionStringCount())
2915 {
2916 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002917 InvalidValue()
2918 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002919 return false;
2920 }
2921 break;
2922
2923 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002925 return false;
2926 }
2927
2928 return true;
2929}
2930
Jamie Madill5b772312018-03-08 20:28:32 -05002931bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002932 GLenum target,
2933 GLsizei samples,
2934 GLenum internalformat,
2935 GLsizei width,
2936 GLsizei height)
2937{
2938 if (context->getClientMajorVersion() < 3)
2939 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002941 return false;
2942 }
2943
2944 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2945 height))
2946 {
2947 return false;
2948 }
2949
2950 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
Yunchao Hec0810202018-01-22 09:48:48 +08002951 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2952 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002953 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002954 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002955 {
Yunchao Hec0810202018-01-22 09:48:48 +08002956 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2957 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2958 {
2959 context->handleError(InvalidOperation());
2960 return false;
2961 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002962 }
2963
2964 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2965 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2966 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2967 {
2968 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002969 InvalidOperation()
2970 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002971 return false;
2972 }
2973
2974 return true;
2975}
2976
Jamie Madill5b772312018-03-08 20:28:32 -05002977bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002978 GLuint index,
2979 GLint size,
2980 GLenum type,
2981 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002982 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002983{
2984 if (context->getClientMajorVersion() < 3)
2985 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002987 return false;
2988 }
2989
Shao80957d92017-02-20 21:25:59 +08002990 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002991 {
Geoff Langaa086d62017-03-23 16:47:21 -04002992 return false;
2993 }
2994
Geoff Langaa086d62017-03-23 16:47:21 -04002995 if (stride < 0)
2996 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002997 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002998 return false;
2999 }
3000
Shao80957d92017-02-20 21:25:59 +08003001 const Caps &caps = context->getCaps();
3002 if (context->getClientVersion() >= ES_3_1)
3003 {
3004 if (stride > caps.maxVertexAttribStride)
3005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidValue()
3007 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08003008 return false;
3009 }
3010
3011 // [OpenGL ES 3.1] Section 10.3.1 page 245:
3012 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
3013 // validation should be inherited.
3014 if (index >= caps.maxVertexAttribBindings)
3015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003016 context->handleError(InvalidValue()
3017 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08003018 return false;
3019 }
3020 }
3021
Geoff Langaa086d62017-03-23 16:47:21 -04003022 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3023 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3024 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3025 // and the pointer argument is not NULL.
3026 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04003027 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04003028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003029 context
3030 ->handleError(InvalidOperation()
3031 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04003032 return false;
3033 }
3034
Geoff Lang2d62ab72017-03-23 16:54:40 -04003035 if (context->getExtensions().webglCompatibility)
3036 {
3037 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
3038 {
3039 return false;
3040 }
3041 }
3042
Geoff Langaa086d62017-03-23 16:47:21 -04003043 return true;
3044}
3045
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003046bool ValidateGetSynciv(Context *context,
3047 GLsync sync,
3048 GLenum pname,
3049 GLsizei bufSize,
3050 GLsizei *length,
3051 GLint *values)
3052{
3053 if (context->getClientMajorVersion() < 3)
3054 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003056 return false;
3057 }
3058
3059 if (bufSize < 0)
3060 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003061 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003062 return false;
3063 }
3064
Jamie Madill70b5bb02017-08-28 13:32:37 -04003065 Sync *syncObject = context->getSync(sync);
3066 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003068 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003069 return false;
3070 }
3071
3072 switch (pname)
3073 {
3074 case GL_OBJECT_TYPE:
3075 case GL_SYNC_CONDITION:
3076 case GL_SYNC_FLAGS:
3077 case GL_SYNC_STATUS:
3078 break;
3079
3080 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003082 return false;
3083 }
3084
3085 return true;
3086}
3087
Jamie Madill5b772312018-03-08 20:28:32 -05003088bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003089 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003090 GLsizei count,
3091 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003092 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003093 GLsizei instanceCount)
3094{
3095 if (context->getClientMajorVersion() < 3)
3096 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003098 return false;
3099 }
3100
3101 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
3102}
3103
Martin Radev137032d2017-07-13 10:11:12 +03003104bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
3105 GLenum target,
3106 GLenum attachment,
3107 GLuint texture,
3108 GLint level,
3109 GLint baseViewIndex,
3110 GLsizei numViews)
3111{
Martin Radev137032d2017-07-13 10:11:12 +03003112 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
3113 numViews))
3114 {
3115 return false;
3116 }
3117
Martin Radev137032d2017-07-13 10:11:12 +03003118 if (texture != 0)
3119 {
Martin Radev14b21262017-08-25 13:54:37 +03003120 if (baseViewIndex < 0)
3121 {
3122 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
3123 return false;
3124 }
3125
Martin Radev137032d2017-07-13 10:11:12 +03003126 Texture *tex = context->getTexture(texture);
3127 ASSERT(tex);
3128
Corentin Wallez99d492c2018-02-27 15:17:10 -05003129 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03003130 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05003131 case TextureType::_2DArray:
Olli Etuaho2c8f0842018-09-12 14:44:55 +03003132 case TextureType::_2DMultisampleArray:
Martin Radev137032d2017-07-13 10:11:12 +03003133 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +03003134 if (tex->getType() == TextureType::_2DMultisampleArray)
3135 {
3136 if (!context->getExtensions().multiviewMultisample)
3137 {
3138 context->handleError(InvalidOperation()
3139 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
3140 return false;
3141 }
3142 }
3143
Martin Radev137032d2017-07-13 10:11:12 +03003144 const Caps &caps = context->getCaps();
3145 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
3146 {
3147 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
3148 "greater than "
3149 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
3150 return false;
3151 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +03003152
3153 break;
Martin Radev137032d2017-07-13 10:11:12 +03003154 }
Martin Radev137032d2017-07-13 10:11:12 +03003155 default:
3156 context->handleError(InvalidOperation()
3157 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
3158 return false;
3159 }
3160
3161 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
3162 {
3163 return false;
3164 }
3165 }
3166
3167 return true;
3168}
3169
3170bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
3171 GLenum target,
3172 GLenum attachment,
3173 GLuint texture,
3174 GLint level,
3175 GLsizei numViews,
3176 const GLint *viewportOffsets)
3177{
3178 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
3179 numViews))
3180 {
3181 return false;
3182 }
3183
Martin Radev137032d2017-07-13 10:11:12 +03003184 if (texture != 0)
3185 {
Martin Radev14b21262017-08-25 13:54:37 +03003186 const GLsizei numViewportOffsetValues = numViews * 2;
3187 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
3188 {
3189 if (viewportOffsets[i] < 0)
3190 {
3191 context->handleError(InvalidValue()
3192 << "viewportOffsets cannot contain negative values.");
3193 return false;
3194 }
3195 }
3196
Martin Radev137032d2017-07-13 10:11:12 +03003197 Texture *tex = context->getTexture(texture);
3198 ASSERT(tex);
3199
Corentin Wallez99d492c2018-02-27 15:17:10 -05003200 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03003201 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05003202 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03003203 break;
3204 default:
3205 context->handleError(InvalidOperation()
3206 << "Texture's target must be GL_TEXTURE_2D.");
3207 return false;
3208 }
3209
3210 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
3211 {
3212 return false;
3213 }
3214 }
3215
3216 return true;
3217}
3218
Jamie Madillff325f12017-08-26 15:06:05 -04003219bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
3220{
3221 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
3222}
3223
3224bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
3225{
3226 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
3227}
3228
3229bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
3230{
3231 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
3232}
3233
3234bool ValidateUniform4ui(Context *context,
3235 GLint location,
3236 GLuint v0,
3237 GLuint v1,
3238 GLuint v2,
3239 GLuint v3)
3240{
3241 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
3242}
3243
3244bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3245{
3246 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
3247}
3248
3249bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3250{
3251 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
3252}
3253
3254bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3255{
3256 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
3257}
3258
3259bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3260{
3261 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
3262}
3263
Jamie Madillf0e04492017-08-26 15:28:42 -04003264bool ValidateIsQuery(Context *context, GLuint id)
3265{
3266 if (context->getClientMajorVersion() < 3)
3267 {
3268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3269 return false;
3270 }
3271
3272 return true;
3273}
3274
Jamie Madillc8c95812017-08-26 18:40:09 -04003275bool ValidateUniformMatrix2x3fv(Context *context,
3276 GLint location,
3277 GLsizei count,
3278 GLboolean transpose,
3279 const GLfloat *value)
3280{
3281 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
3282}
3283
3284bool ValidateUniformMatrix3x2fv(Context *context,
3285 GLint location,
3286 GLsizei count,
3287 GLboolean transpose,
3288 const GLfloat *value)
3289{
3290 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
3291}
3292
3293bool ValidateUniformMatrix2x4fv(Context *context,
3294 GLint location,
3295 GLsizei count,
3296 GLboolean transpose,
3297 const GLfloat *value)
3298{
3299 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
3300}
3301
3302bool ValidateUniformMatrix4x2fv(Context *context,
3303 GLint location,
3304 GLsizei count,
3305 GLboolean transpose,
3306 const GLfloat *value)
3307{
3308 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3309}
3310
3311bool ValidateUniformMatrix3x4fv(Context *context,
3312 GLint location,
3313 GLsizei count,
3314 GLboolean transpose,
3315 const GLfloat *value)
3316{
3317 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3318}
3319
3320bool ValidateUniformMatrix4x3fv(Context *context,
3321 GLint location,
3322 GLsizei count,
3323 GLboolean transpose,
3324 const GLfloat *value)
3325{
3326 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3327}
3328
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003329bool ValidateEndTransformFeedback(Context *context)
3330{
3331 if (context->getClientMajorVersion() < 3)
3332 {
3333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3334 return false;
3335 }
3336
3337 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3338 ASSERT(transformFeedback != nullptr);
3339
3340 if (!transformFeedback->isActive())
3341 {
3342 context->handleError(InvalidOperation());
3343 return false;
3344 }
3345
3346 return true;
3347}
3348
3349bool ValidateTransformFeedbackVaryings(Context *context,
3350 GLuint program,
3351 GLsizei count,
3352 const GLchar *const *varyings,
3353 GLenum bufferMode)
3354{
3355 if (context->getClientMajorVersion() < 3)
3356 {
3357 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3358 return false;
3359 }
3360
3361 if (count < 0)
3362 {
3363 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3364 return false;
3365 }
3366
3367 switch (bufferMode)
3368 {
3369 case GL_INTERLEAVED_ATTRIBS:
3370 break;
3371 case GL_SEPARATE_ATTRIBS:
3372 {
3373 const Caps &caps = context->getCaps();
3374 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3375 {
3376 context->handleError(InvalidValue());
3377 return false;
3378 }
3379 break;
3380 }
3381 default:
3382 context->handleError(InvalidEnum());
3383 return false;
3384 }
3385
3386 Program *programObject = GetValidProgram(context, program);
3387 if (!programObject)
3388 {
3389 return false;
3390 }
3391
3392 return true;
3393}
3394
3395bool ValidateGetTransformFeedbackVarying(Context *context,
3396 GLuint program,
3397 GLuint index,
3398 GLsizei bufSize,
3399 GLsizei *length,
3400 GLsizei *size,
3401 GLenum *type,
3402 GLchar *name)
3403{
3404 if (context->getClientMajorVersion() < 3)
3405 {
3406 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3407 return false;
3408 }
3409
3410 if (bufSize < 0)
3411 {
3412 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3413 return false;
3414 }
3415
3416 Program *programObject = GetValidProgram(context, program);
3417 if (!programObject)
3418 {
3419 return false;
3420 }
3421
3422 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3423 {
3424 context->handleError(InvalidValue());
3425 return false;
3426 }
3427
3428 return true;
3429}
3430
3431bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3432{
3433 if (context->getClientMajorVersion() < 3)
3434 {
3435 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3436 return false;
3437 }
3438
3439 switch (target)
3440 {
3441 case GL_TRANSFORM_FEEDBACK:
3442 {
3443 // Cannot bind a transform feedback object if the current one is started and not
3444 // paused (3.0.2 pg 85 section 2.14.1)
3445 TransformFeedback *curTransformFeedback =
3446 context->getGLState().getCurrentTransformFeedback();
3447 if (curTransformFeedback && curTransformFeedback->isActive() &&
3448 !curTransformFeedback->isPaused())
3449 {
3450 context->handleError(InvalidOperation());
3451 return false;
3452 }
3453
3454 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3455 // 2.14.1)
3456 if (!context->isTransformFeedbackGenerated(id))
3457 {
3458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3459 return false;
3460 }
3461 }
3462 break;
3463
3464 default:
3465 context->handleError(InvalidEnum());
3466 return false;
3467 }
3468
3469 return true;
3470}
3471
3472bool ValidateIsTransformFeedback(Context *context, GLuint id)
3473{
3474 if (context->getClientMajorVersion() < 3)
3475 {
3476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3477 return false;
3478 }
3479
3480 return true;
3481}
3482
3483bool ValidatePauseTransformFeedback(Context *context)
3484{
3485 if (context->getClientMajorVersion() < 3)
3486 {
3487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3488 return false;
3489 }
3490
3491 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3492 ASSERT(transformFeedback != nullptr);
3493
3494 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3495 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3496 {
3497 context->handleError(InvalidOperation());
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
3504bool ValidateResumeTransformFeedback(Context *context)
3505{
3506 if (context->getClientMajorVersion() < 3)
3507 {
3508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3509 return false;
3510 }
3511
3512 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3513 ASSERT(transformFeedback != nullptr);
3514
3515 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3516 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3517 {
3518 context->handleError(InvalidOperation());
3519 return false;
3520 }
3521
3522 return true;
3523}
3524
Jamie Madill12e957f2017-08-26 21:42:26 -04003525bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3526{
3527 if (context->getClientMajorVersion() < 3)
3528 {
3529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3530 return false;
3531 }
3532
3533 return ValidateVertexAttribIndex(context, index);
3534}
3535
3536bool ValidateVertexAttribI4ui(Context *context,
3537 GLuint index,
3538 GLuint x,
3539 GLuint y,
3540 GLuint z,
3541 GLuint w)
3542{
3543 if (context->getClientMajorVersion() < 3)
3544 {
3545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3546 return false;
3547 }
3548
3549 return ValidateVertexAttribIndex(context, index);
3550}
3551
3552bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3553{
3554 if (context->getClientMajorVersion() < 3)
3555 {
3556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3557 return false;
3558 }
3559
3560 return ValidateVertexAttribIndex(context, index);
3561}
3562
3563bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3564{
3565 if (context->getClientMajorVersion() < 3)
3566 {
3567 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3568 return false;
3569 }
3570
3571 return ValidateVertexAttribIndex(context, index);
3572}
3573
3574bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3575{
3576 if (context->getClientMajorVersion() < 3)
3577 {
3578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3579 return false;
3580 }
3581
3582 Program *programObject = GetValidProgram(context, program);
3583 if (!programObject)
3584 {
3585 return false;
3586 }
3587
3588 if (!programObject->isLinked())
3589 {
3590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3591 return false;
3592 }
3593
3594 return true;
3595}
3596
3597bool ValidateGetUniformIndices(Context *context,
3598 GLuint program,
3599 GLsizei uniformCount,
3600 const GLchar *const *uniformNames,
3601 GLuint *uniformIndices)
3602{
3603 if (context->getClientMajorVersion() < 3)
3604 {
3605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3606 return false;
3607 }
3608
3609 if (uniformCount < 0)
3610 {
3611 context->handleError(InvalidValue());
3612 return false;
3613 }
3614
3615 Program *programObject = GetValidProgram(context, program);
3616 if (!programObject)
3617 {
3618 return false;
3619 }
3620
3621 return true;
3622}
3623
3624bool ValidateGetActiveUniformsiv(Context *context,
3625 GLuint program,
3626 GLsizei uniformCount,
3627 const GLuint *uniformIndices,
3628 GLenum pname,
3629 GLint *params)
3630{
3631 if (context->getClientMajorVersion() < 3)
3632 {
3633 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3634 return false;
3635 }
3636
3637 if (uniformCount < 0)
3638 {
3639 context->handleError(InvalidValue());
3640 return false;
3641 }
3642
3643 Program *programObject = GetValidProgram(context, program);
3644 if (!programObject)
3645 {
3646 return false;
3647 }
3648
3649 switch (pname)
3650 {
3651 case GL_UNIFORM_TYPE:
3652 case GL_UNIFORM_SIZE:
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07003653 break;
Jamie Madill12e957f2017-08-26 21:42:26 -04003654 case GL_UNIFORM_NAME_LENGTH:
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07003655 if (context->getExtensions().webglCompatibility)
3656 {
3657 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3658 return false;
3659 }
3660 break;
Jamie Madill12e957f2017-08-26 21:42:26 -04003661 case GL_UNIFORM_BLOCK_INDEX:
3662 case GL_UNIFORM_OFFSET:
3663 case GL_UNIFORM_ARRAY_STRIDE:
3664 case GL_UNIFORM_MATRIX_STRIDE:
3665 case GL_UNIFORM_IS_ROW_MAJOR:
3666 break;
3667
3668 default:
3669 context->handleError(InvalidEnum());
3670 return false;
3671 }
3672
3673 if (uniformCount > programObject->getActiveUniformCount())
3674 {
3675 context->handleError(InvalidValue());
3676 return false;
3677 }
3678
3679 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3680 {
3681 const GLuint index = uniformIndices[uniformId];
3682
3683 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3684 {
3685 context->handleError(InvalidValue());
3686 return false;
3687 }
3688 }
3689
3690 return true;
3691}
3692
3693bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3694{
3695 if (context->getClientMajorVersion() < 3)
3696 {
3697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3698 return false;
3699 }
3700
3701 Program *programObject = GetValidProgram(context, program);
3702 if (!programObject)
3703 {
3704 return false;
3705 }
3706
3707 return true;
3708}
3709
3710bool ValidateGetActiveUniformBlockiv(Context *context,
3711 GLuint program,
3712 GLuint uniformBlockIndex,
3713 GLenum pname,
3714 GLint *params)
3715{
3716 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3717}
3718
3719bool ValidateGetActiveUniformBlockName(Context *context,
3720 GLuint program,
3721 GLuint uniformBlockIndex,
3722 GLsizei bufSize,
3723 GLsizei *length,
3724 GLchar *uniformBlockName)
3725{
3726 if (context->getClientMajorVersion() < 3)
3727 {
3728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3729 return false;
3730 }
3731
3732 Program *programObject = GetValidProgram(context, program);
3733 if (!programObject)
3734 {
3735 return false;
3736 }
3737
3738 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3739 {
3740 context->handleError(InvalidValue());
3741 return false;
3742 }
3743
3744 return true;
3745}
3746
3747bool ValidateUniformBlockBinding(Context *context,
3748 GLuint program,
3749 GLuint uniformBlockIndex,
3750 GLuint uniformBlockBinding)
3751{
3752 if (context->getClientMajorVersion() < 3)
3753 {
3754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3755 return false;
3756 }
3757
3758 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3759 {
3760 context->handleError(InvalidValue());
3761 return false;
3762 }
3763
3764 Program *programObject = GetValidProgram(context, program);
3765 if (!programObject)
3766 {
3767 return false;
3768 }
3769
3770 // if never linked, there won't be any uniform blocks
3771 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3772 {
3773 context->handleError(InvalidValue());
3774 return false;
3775 }
3776
3777 return true;
3778}
3779
3780bool ValidateDrawArraysInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003781 PrimitiveMode mode,
Jamie Madill12e957f2017-08-26 21:42:26 -04003782 GLint first,
3783 GLsizei count,
3784 GLsizei primcount)
3785{
3786 if (context->getClientMajorVersion() < 3)
3787 {
3788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3789 return false;
3790 }
3791
3792 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3793}
3794
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003795bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3796{
3797 if (context->getClientMajorVersion() < 3)
3798 {
3799 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3800 return false;
3801 }
3802
3803 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3804 {
3805 context->handleError(InvalidEnum());
3806 return false;
3807 }
3808
3809 if (flags != 0)
3810 {
3811 context->handleError(InvalidValue());
3812 return false;
3813 }
3814
3815 return true;
3816}
3817
3818bool ValidateIsSync(Context *context, GLsync sync)
3819{
3820 if (context->getClientMajorVersion() < 3)
3821 {
3822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3823 return false;
3824 }
3825
3826 return true;
3827}
3828
3829bool ValidateDeleteSync(Context *context, GLsync sync)
3830{
3831 if (context->getClientMajorVersion() < 3)
3832 {
3833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3834 return false;
3835 }
3836
Jamie Madill70b5bb02017-08-28 13:32:37 -04003837 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003838 {
3839 context->handleError(InvalidValue());
3840 return false;
3841 }
3842
3843 return true;
3844}
3845
3846bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3847{
3848 if (context->getClientMajorVersion() < 3)
3849 {
3850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3851 return false;
3852 }
3853
3854 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3855 {
3856 context->handleError(InvalidValue());
3857 return false;
3858 }
3859
Jamie Madill70b5bb02017-08-28 13:32:37 -04003860 Sync *clientWaitSync = context->getSync(sync);
3861 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003862 {
3863 context->handleError(InvalidValue());
3864 return false;
3865 }
3866
3867 return true;
3868}
3869
3870bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3871{
3872 if (context->getClientMajorVersion() < 3)
3873 {
3874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3875 return false;
3876 }
3877
3878 if (flags != 0)
3879 {
3880 context->handleError(InvalidValue());
3881 return false;
3882 }
3883
3884 if (timeout != GL_TIMEOUT_IGNORED)
3885 {
3886 context->handleError(InvalidValue());
3887 return false;
3888 }
3889
Jamie Madill70b5bb02017-08-28 13:32:37 -04003890 Sync *waitSync = context->getSync(sync);
3891 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003892 {
3893 context->handleError(InvalidValue());
3894 return false;
3895 }
3896
3897 return true;
3898}
3899
3900bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3901{
3902 if (context->getClientMajorVersion() < 3)
3903 {
3904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3905 return false;
3906 }
3907
3908 GLenum nativeType = GL_NONE;
3909 unsigned int numParams = 0;
3910 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3911 {
3912 return false;
3913 }
3914
3915 return true;
3916}
3917
Jamie Madill3ef140a2017-08-26 23:11:21 -04003918bool ValidateIsSampler(Context *context, GLuint sampler)
3919{
3920 if (context->getClientMajorVersion() < 3)
3921 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003923 return false;
3924 }
3925
3926 return true;
3927}
3928
3929bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3930{
3931 if (context->getClientMajorVersion() < 3)
3932 {
3933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3934 return false;
3935 }
3936
3937 if (sampler != 0 && !context->isSampler(sampler))
3938 {
3939 context->handleError(InvalidOperation());
3940 return false;
3941 }
3942
3943 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3944 {
3945 context->handleError(InvalidValue());
3946 return false;
3947 }
3948
3949 return true;
3950}
3951
3952bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3953{
3954 if (context->getClientMajorVersion() < 3)
3955 {
3956 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3957 return false;
3958 }
3959
3960 return ValidateVertexAttribIndex(context, index);
3961}
3962
3963bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003964 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003965 GLsizei levels,
3966 GLenum internalformat,
3967 GLsizei width,
3968 GLsizei height)
3969{
3970 if (context->getClientMajorVersion() < 3)
3971 {
3972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3973 return false;
3974 }
3975
3976 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3977 1))
3978 {
3979 return false;
3980 }
3981
3982 return true;
3983}
3984
3985bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003986 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04003987 GLsizei levels,
3988 GLenum internalformat,
3989 GLsizei width,
3990 GLsizei height,
3991 GLsizei depth)
3992{
3993 if (context->getClientMajorVersion() < 3)
3994 {
3995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3996 return false;
3997 }
3998
3999 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
4000 depth))
4001 {
4002 return false;
4003 }
4004
4005 return true;
4006}
4007
Jamie Madill5b772312018-03-08 20:28:32 -05004008bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004009 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04004010 GLenum pname,
4011 GLint64 *params)
4012{
4013 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4014}
4015
4016bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4017{
4018 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4019}
4020
4021bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4022{
4023 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4024}
4025
4026bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4027{
4028 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4029}
4030
4031bool ValidateSamplerParameterfv(Context *context,
4032 GLuint sampler,
4033 GLenum pname,
4034 const GLfloat *params)
4035{
4036 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4037}
4038
4039bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4040{
4041 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4042}
4043
4044bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4045{
4046 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4047}
4048
4049bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4050{
4051 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4052}
4053
4054bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4055{
4056 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4057}
4058
4059bool ValidateGetInternalformativ(Context *context,
4060 GLenum target,
4061 GLenum internalformat,
4062 GLenum pname,
4063 GLsizei bufSize,
4064 GLint *params)
4065{
4066 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4067 nullptr);
4068}
4069
Olli Etuaho0ca09752018-09-24 11:00:50 +03004070bool ValidateBindFragDataLocationIndexedEXT(Context *context,
4071 GLuint program,
4072 GLuint colorNumber,
4073 GLuint index,
4074 const char *name)
4075{
4076 if (!context->getExtensions().blendFuncExtended)
4077 {
4078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4079 return false;
4080 }
4081 if (context->getClientMajorVersion() < 3)
4082 {
4083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4084 return false;
4085 }
4086 if (index < 0 || index > 1)
4087 {
4088 // This error is not explicitly specified but the spec does say that "<index> may be zero or
4089 // one to specify that the color be used as either the first or second color input to the
4090 // blend equation, respectively"
4091 ANGLE_VALIDATION_ERR(context, InvalidValue(), FragDataBindingIndexOutOfRange);
4092 return false;
4093 }
4094 if (index == 1)
4095 {
4096 if (colorNumber >= context->getExtensions().maxDualSourceDrawBuffers)
4097 {
4098 ANGLE_VALIDATION_ERR(context, InvalidValue(),
4099 ColorNumberGreaterThanMaxDualSourceDrawBuffers);
4100 return false;
4101 }
4102 }
4103 else
4104 {
4105 if (colorNumber >= context->getCaps().maxDrawBuffers)
4106 {
4107 ANGLE_VALIDATION_ERR(context, InvalidValue(), ColorNumberGreaterThanMaxDrawBuffers);
4108 return false;
4109 }
4110 }
4111 Program *programObject = GetValidProgram(context, program);
4112 if (!programObject)
4113 {
4114 return false;
4115 }
4116 return true;
4117}
4118
4119bool ValidateBindFragDataLocationEXT(Context *context,
4120 GLuint program,
4121 GLuint colorNumber,
4122 const char *name)
4123{
4124 return ValidateBindFragDataLocationIndexedEXT(context, program, colorNumber, 0u, name);
4125}
4126
4127bool ValidateGetFragDataIndexEXT(Context *context, GLuint program, const char *name)
4128{
4129 if (!context->getExtensions().blendFuncExtended)
4130 {
4131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4132 return false;
4133 }
4134 if (context->getClientMajorVersion() < 3)
4135 {
4136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4137 return false;
4138 }
4139 Program *programObject = GetValidProgram(context, program);
4140 if (!programObject)
4141 {
4142 return false;
4143 }
4144 if (!programObject->isLinked())
4145 {
4146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4147 return false;
4148 }
4149 return true;
4150}
4151
Jamie Madillc29968b2016-01-20 11:17:23 -05004152} // namespace gl