blob: 86e28aac470ef892a157522089271ba4fcb8caed [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
48 if (numViews < 1)
49 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
Jamie Madillff325f12017-08-26 15:06:05 -040085bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86{
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94}
95
96} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +030097
He Yunchaoced53ae2016-11-29 15:00:51 +080098static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -040099 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800100 GLenum internalFormat,
101 GLenum format,
102 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400103{
Geoff Lang5d601382014-07-22 15:14:06 -0400104
105 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400106 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400107 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700108 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400109 return false;
110 }
111
112 if (!ValidES3Type(type))
113 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400115 return false;
116 }
117
118 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
119 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
120 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
121 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
122 if (!ValidES3InternalFormat(internalFormat))
123 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700124 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400125 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400126 }
127
Geoff Langca271392017-04-05 12:30:00 -0400128 // From the ES 3.0 spec section 3.8.3:
129 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
130 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
131 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
132 // INVALID_OPERATION error.
133 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500135 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
136 "GL_DEPTH_STENCIL if target is "
137 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400138 return false;
139 }
140
Geoff Lang5d601382014-07-22 15:14:06 -0400141 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400142 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500144 context->handleError(InvalidOperation()
145 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400146 return false;
147 }
148
149 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
150 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500152 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400153 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400154 }
155
156 return true;
157}
158
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500159bool ValidateES3TexImageParametersBase(Context *context,
160 GLenum target,
161 GLint level,
162 GLenum internalformat,
163 bool isCompressed,
164 bool isSubImage,
165 GLint xoffset,
166 GLint yoffset,
167 GLint zoffset,
168 GLsizei width,
169 GLsizei height,
170 GLsizei depth,
171 GLint border,
172 GLenum format,
173 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400174 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400175 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400176{
177 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700178 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500180 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 }
183
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400184 // Verify zero border
185 if (border != 0)
186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500187 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400189 }
190
Jamie Madill6f38f822014-06-06 17:12:20 -0400191 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
192 std::numeric_limits<GLsizei>::max() - xoffset < width ||
193 std::numeric_limits<GLsizei>::max() - yoffset < height ||
194 std::numeric_limits<GLsizei>::max() - zoffset < depth)
195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500196 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400197 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400198 }
199
Geoff Langaae65a42014-05-26 12:43:44 -0400200 const gl::Caps &caps = context->getCaps();
201
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400202 switch (target)
203 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800204 case GL_TEXTURE_2D:
205 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
206 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500208 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800209 return false;
210 }
211 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400212
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400213 case GL_TEXTURE_RECTANGLE_ANGLE:
214 ASSERT(level == 0);
215 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
216 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
217 {
218 context->handleError(InvalidValue());
219 return false;
220 }
221 if (isCompressed)
222 {
223 context->handleError(InvalidEnum()
224 << "Rectangle texture cannot have a compressed format.");
225 return false;
226 }
227 break;
228
He Yunchaoced53ae2016-11-29 15:00:51 +0800229 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
230 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
231 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
232 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
233 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
234 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
235 if (!isSubImage && width != height)
236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500237 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800238 return false;
239 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400240
He Yunchaoced53ae2016-11-29 15:00:51 +0800241 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500243 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800244 return false;
245 }
246 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400247
He Yunchaoced53ae2016-11-29 15:00:51 +0800248 case GL_TEXTURE_3D:
249 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
250 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
251 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500253 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800254 return false;
255 }
256 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400257
He Yunchaoced53ae2016-11-29 15:00:51 +0800258 case GL_TEXTURE_2D_ARRAY:
259 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
260 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
261 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500263 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800264 return false;
265 }
266 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400267
He Yunchaoced53ae2016-11-29 15:00:51 +0800268 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500269 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400271 }
272
He Yunchaoced53ae2016-11-29 15:00:51 +0800273 gl::Texture *texture =
274 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400275 if (!texture)
276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500277 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400278 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400279 }
280
Geoff Lang69cce582015-09-17 13:20:36 -0400281 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500283 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400284 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285 }
286
287 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400288 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400289 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500290 if (isSubImage && actualInternalFormat == GL_NONE)
291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500292 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500293 return false;
294 }
295
Geoff Langc4e93662017-05-01 10:45:59 -0400296 const gl::InternalFormat &actualFormatInfo = isSubImage
297 ? *texture->getFormat(target, level).info
298 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400299 if (isCompressed)
300 {
tmartino7c102692015-10-02 16:43:40 -0400301 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500303 context->handleError(
304 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400305 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400306 }
307
Geoff Lang966c9402017-04-18 12:38:27 -0400308 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 {
Geoff Lang966c9402017-04-18 12:38:27 -0400310 if (!ValidCompressedSubImageSize(
311 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
312 texture->getWidth(target, level), texture->getHeight(target, level)))
313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400315 return false;
316 }
317
318 if (format != actualInternalFormat)
319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidOperation()
321 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400322 return false;
323 }
324 }
325 else
326 {
327 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400330 return false;
331 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 }
333
Geoff Langeb66a6e2016-10-31 13:06:12 -0400334 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500336 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400337 return false;
338 }
339
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 if (target == GL_TEXTURE_3D)
341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500342 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 }
345 }
346 else
347 {
Geoff Langca271392017-04-05 12:30:00 -0400348 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400349 {
Geoff Lang5d601382014-07-22 15:14:06 -0400350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400352 }
353
354 // Validate sub image parameters
355 if (isSubImage)
356 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500357 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400361 }
362
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500365 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
368
369 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
370 std::numeric_limits<GLsizei>::max() - yoffset < height ||
371 std::numeric_limits<GLsizei>::max() - zoffset < depth)
372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500373 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 }
376
Geoff Langa9be0dc2014-12-17 12:34:40 -0500377 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
378 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
379 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500381 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 }
384 }
385
Geoff Langdbcced82017-06-06 15:55:54 -0400386 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
387 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
388 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400389 {
390 return false;
391 }
392
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400393 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700394 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400395 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400396 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800397 // ...data is not evenly divisible into the number of bytes needed to store in memory a
398 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400399 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400400 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400401 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400402 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400403 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
404
Geoff Langff5b2d52016-09-07 11:32:23 -0400405 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500407 context->handleError(InvalidOperation()
408 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400409 return false;
410 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400411 }
412
Jamie Madill7a5f7382014-03-05 15:01:24 -0500413 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700414 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500416 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400417 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500418 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400419 }
420
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400421 return true;
422}
423
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500424bool ValidateES3TexImage2DParameters(Context *context,
425 GLenum target,
426 GLint level,
427 GLenum internalformat,
428 bool isCompressed,
429 bool isSubImage,
430 GLint xoffset,
431 GLint yoffset,
432 GLint zoffset,
433 GLsizei width,
434 GLsizei height,
435 GLsizei depth,
436 GLint border,
437 GLenum format,
438 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400439 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400440 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500441{
442 if (!ValidTexture2DDestinationTarget(context, target))
443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500444 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500445 return false;
446 }
447
448 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
449 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400450 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500451}
452
453bool ValidateES3TexImage3DParameters(Context *context,
454 GLenum target,
455 GLint level,
456 GLenum internalformat,
457 bool isCompressed,
458 bool isSubImage,
459 GLint xoffset,
460 GLint yoffset,
461 GLint zoffset,
462 GLsizei width,
463 GLsizei height,
464 GLsizei depth,
465 GLint border,
466 GLenum format,
467 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400468 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400469 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500470{
471 if (!ValidTexture3DDestinationTarget(context, target))
472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500473 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500474 return false;
475 }
476
477 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
478 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400479 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500480}
481
Geoff Lang5d601382014-07-22 15:14:06 -0400482struct EffectiveInternalFormatInfo
483{
Jamie Madill76648fe2016-10-05 17:01:41 -0400484 GLenum effectiveFormat;
485 GLenum destFormat;
486 GLuint minRedBits;
487 GLuint maxRedBits;
488 GLuint minGreenBits;
489 GLuint maxGreenBits;
490 GLuint minBlueBits;
491 GLuint maxBlueBits;
492 GLuint minAlphaBits;
493 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400494};
495
Jamie Madill76648fe2016-10-05 17:01:41 -0400496static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
497 GLenum targetFormat,
498 const EffectiveInternalFormatInfo *list,
499 size_t size,
500 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400501{
Jamie Madill76648fe2016-10-05 17:01:41 -0400502 for (size_t curFormat = 0; curFormat < size; ++curFormat)
503 {
504 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
505 if ((formatInfo.destFormat == targetFormat) &&
506 (formatInfo.minRedBits <= srcFormat.redBits &&
507 formatInfo.maxRedBits >= srcFormat.redBits) &&
508 (formatInfo.minGreenBits <= srcFormat.greenBits &&
509 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
510 (formatInfo.minBlueBits <= srcFormat.blueBits &&
511 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
512 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
513 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
514 {
515 *outEffectiveFormat = formatInfo.effectiveFormat;
516 return true;
517 }
518 }
Geoff Lang5d601382014-07-22 15:14:06 -0400519
Jamie Madill76648fe2016-10-05 17:01:41 -0400520 *outEffectiveFormat = GL_NONE;
521 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400522}
523
Jamie Madill76648fe2016-10-05 17:01:41 -0400524bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
525 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400526{
Jamie Madill76648fe2016-10-05 17:01:41 -0400527 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
528 // Effective internal format coresponding to destination internal format and linear source
529 // buffer component sizes.
530 // | Source channel min/max sizes |
531 // Effective Internal Format | N/A | R | G | B | A |
532 // clang-format off
533 constexpr EffectiveInternalFormatInfo list[] = {
534 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
535 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
536 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
537 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
538 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
539 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
540 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
541 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
542 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
543 };
544 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400545
Jamie Madill76648fe2016-10-05 17:01:41 -0400546 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
547}
Geoff Lang5d601382014-07-22 15:14:06 -0400548
Jamie Madill76648fe2016-10-05 17:01:41 -0400549bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
550 const InternalFormat &destFormat,
551 GLenum *outEffectiveFormat)
552{
553 constexpr GLuint umax = UINT_MAX;
554
555 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
556 // Effective internal format coresponding to destination internal format andlinear source buffer
557 // component sizes.
558 // | Source channel min/max sizes |
559 // Effective Internal Format | Dest Format | R | G | B | A |
560 // clang-format off
561 constexpr EffectiveInternalFormatInfo list[] = {
562 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
563 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
564 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
565 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
566 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
567 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
568 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
569 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
570 };
571 // clang-format on
572
573 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
574 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400575}
576
He Yunchaoced53ae2016-11-29 15:00:51 +0800577static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
578 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400579 GLenum *outEffectiveFormat)
580{
Geoff Langca271392017-04-05 12:30:00 -0400581 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400582 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400583 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400584 }
585 else
586 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400587 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400588 }
Geoff Lang5d601382014-07-22 15:14:06 -0400589}
590
Corentin Wallez76287682016-04-25 09:23:38 -0400591static bool EqualOrFirstZero(GLuint first, GLuint second)
592{
593 return first == 0 || first == second;
594}
595
Geoff Langca271392017-04-05 12:30:00 -0400596static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
597 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400598 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400599{
Jamie Madill21b786b2016-11-01 17:41:31 -0400600 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400601 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400602 return false;
603 }
Geoff Lang5d601382014-07-22 15:14:06 -0400604
Jamie Madill21b786b2016-11-01 17:41:31 -0400605 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
606 // must both be signed, unsigned, or fixed point and both source and destinations
607 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
608 // conversion between fixed and floating point.
609
610 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
611 (framebufferFormatInfo.colorEncoding == GL_SRGB))
612 {
613 return false;
614 }
615
616 if (((textureFormatInfo.componentType == GL_INT) !=
617 (framebufferFormatInfo.componentType == GL_INT)) ||
618 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
619 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
620 {
621 return false;
622 }
623
624 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
625 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
626 textureFormatInfo.componentType == GL_FLOAT) &&
627 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
628 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
629 framebufferFormatInfo.componentType == GL_FLOAT))
630 {
631 return false;
632 }
633
634 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
635 // The effective internal format of the source buffer is determined with the following rules
636 // applied in order:
637 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
638 // format then the effective internal format is the source buffer's sized internal format.
639 // * If the source buffer is a texture that was created with an unsized base internal format,
640 // then the effective internal format is the source image array's effective internal
641 // format, as specified by table 3.12, which is determined from the <format> and <type>
642 // that were used when the source image array was specified by TexImage*.
643 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
644 // where Destination Internal Format matches internalformat and where the [source channel
645 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
646 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
647 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800648 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400649 if (readBufferHandle != 0)
650 {
651 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
652 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400653 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400654 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400655 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400656 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400657 else
Geoff Lang5d601382014-07-22 15:14:06 -0400658 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400659 // Renderbuffers cannot be created with an unsized internal format, so this must be an
660 // unsized-format texture. We can use the same table we use when creating textures to
661 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400662 sourceEffectiveFormat =
663 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400664 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400665 }
666 else
667 {
668 // The effective internal format must be derived from the source framebuffer's channel
669 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
670 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400671 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400672 GLenum effectiveFormat;
673 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
674 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400675 {
Geoff Langca271392017-04-05 12:30:00 -0400676 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400677 }
678 else
679 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400680 return false;
681 }
682 }
683 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
684 {
685 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400686 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400687 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
688 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
689 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
690 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
691 {
Geoff Langca271392017-04-05 12:30:00 -0400692 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400693 }
694 else
695 {
696 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400697 }
698 }
699 else
700 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400701 UNREACHABLE();
702 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400703 }
Geoff Lang5d601382014-07-22 15:14:06 -0400704 }
705
Geoff Langca271392017-04-05 12:30:00 -0400706 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400707 {
708 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
709 // sized, component sizes of the source and destination formats must exactly match if the
710 // destination format exists.
711 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
712 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
713 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
714 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
715 {
716 return false;
717 }
718 }
719
720 return true; // A conversion function exists, and no rule in the specification has precluded
721 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400722}
723
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500724bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
725 GLenum target,
726 GLint level,
727 GLenum internalformat,
728 bool isSubImage,
729 GLint xoffset,
730 GLint yoffset,
731 GLint zoffset,
732 GLint x,
733 GLint y,
734 GLsizei width,
735 GLsizei height,
736 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400737{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400738 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400739 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400740 xoffset, yoffset, zoffset, x, y, width, height, border,
741 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400742 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400743 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400744 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400745 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746
Jamie Madill51f40ec2016-06-15 14:06:00 -0400747 const auto &state = context->getGLState();
748 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
749 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400750
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400751 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500753 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400754 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400755 }
756
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400757 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500759 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400760 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400761 }
762
Jamie Madill0c8abca2016-07-22 20:21:26 -0400763 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764
765 if (isSubImage)
766 {
Geoff Langca271392017-04-05 12:30:00 -0400767 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500768 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500770 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400771 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 }
773 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400774 else
775 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400776 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400777 const InternalFormat &framebufferFormat = *source->getFormat().info;
778 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400779 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500781 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400782 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400783 }
784 }
785
Geoff Lang784a8fd2013-09-24 12:33:16 -0400786 // If width or height is zero, it is a no-op. Return false without setting an error.
787 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788}
789
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500790bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
791 GLenum target,
792 GLint level,
793 GLenum internalformat,
794 bool isSubImage,
795 GLint xoffset,
796 GLint yoffset,
797 GLint zoffset,
798 GLint x,
799 GLint y,
800 GLsizei width,
801 GLsizei height,
802 GLint border)
803{
804 if (!ValidTexture2DDestinationTarget(context, target))
805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500806 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500807 return false;
808 }
809
810 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
811 xoffset, yoffset, zoffset, x, y, width, height,
812 border);
813}
814
815bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
816 GLenum target,
817 GLint level,
818 GLenum internalformat,
819 bool isSubImage,
820 GLint xoffset,
821 GLint yoffset,
822 GLint zoffset,
823 GLint x,
824 GLint y,
825 GLsizei width,
826 GLsizei height,
827 GLint border)
828{
829 if (!ValidTexture3DDestinationTarget(context, target))
830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500831 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500832 return false;
833 }
834
835 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
836 xoffset, yoffset, zoffset, x, y, width, height,
837 border);
838}
839
840bool ValidateES3TexStorageParametersBase(Context *context,
841 GLenum target,
842 GLsizei levels,
843 GLenum internalformat,
844 GLsizei width,
845 GLsizei height,
846 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847{
848 if (width < 1 || height < 1 || depth < 1 || levels < 1)
849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500850 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400851 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400852 }
853
Geoff Langb92c1332015-09-04 12:54:55 -0400854 GLsizei maxDim = std::max(width, height);
855 if (target != GL_TEXTURE_2D_ARRAY)
856 {
857 maxDim = std::max(maxDim, depth);
858 }
859
860 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500862 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400863 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400864 }
865
Geoff Langaae65a42014-05-26 12:43:44 -0400866 const gl::Caps &caps = context->getCaps();
867
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868 switch (target)
869 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800870 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 {
Geoff Langaae65a42014-05-26 12:43:44 -0400872 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
873 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500875 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400876 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 }
878 }
879 break;
880
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400881 case GL_TEXTURE_RECTANGLE_ANGLE:
882 {
883 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
884 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
885 {
886 context->handleError(InvalidValue());
887 return false;
888 }
889 }
890 break;
891
He Yunchaoced53ae2016-11-29 15:00:51 +0800892 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894 if (width != height)
895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400897 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898 }
899
Geoff Langaae65a42014-05-26 12:43:44 -0400900 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500902 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400903 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400904 }
905 }
906 break;
907
He Yunchaoced53ae2016-11-29 15:00:51 +0800908 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 {
Geoff Langaae65a42014-05-26 12:43:44 -0400910 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
911 static_cast<GLuint>(height) > caps.max3DTextureSize ||
912 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500914 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400915 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916 }
917 }
918 break;
919
He Yunchaoced53ae2016-11-29 15:00:51 +0800920 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 {
Geoff Langaae65a42014-05-26 12:43:44 -0400922 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
923 static_cast<GLuint>(height) > caps.max2DTextureSize ||
924 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500926 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400927 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 }
929 }
930 break;
931
He Yunchaoced53ae2016-11-29 15:00:51 +0800932 default:
933 UNREACHABLE();
934 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 }
936
Geoff Lang691e58c2014-12-19 17:03:25 -0500937 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400938 if (!texture || texture->id() == 0)
939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500940 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400941 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 }
943
Geoff Lang69cce582015-09-17 13:20:36 -0400944 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500946 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400947 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 }
949
Geoff Langca271392017-04-05 12:30:00 -0400950 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400951 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500953 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400954 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400955 }
956
Geoff Langca271392017-04-05 12:30:00 -0400957 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500959 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400960 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 }
962
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400963 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
964 {
965 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
966 return false;
967 }
968
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 return true;
970}
971
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500972bool ValidateES3TexStorage2DParameters(Context *context,
973 GLenum target,
974 GLsizei levels,
975 GLenum internalformat,
976 GLsizei width,
977 GLsizei height,
978 GLsizei depth)
979{
980 if (!ValidTexture2DTarget(context, target))
981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500982 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500983 return false;
984 }
985
986 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
987 height, depth);
988}
989
990bool ValidateES3TexStorage3DParameters(Context *context,
991 GLenum target,
992 GLsizei levels,
993 GLenum internalformat,
994 GLsizei width,
995 GLsizei height,
996 GLsizei depth)
997{
998 if (!ValidTexture3DTarget(context, target))
999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001001 return false;
1002 }
1003
1004 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1005 height, depth);
1006}
1007
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001008bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1009{
Martin Radev1be913c2016-07-11 17:59:16 +03001010 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001013 return false;
1014 }
1015
1016 return ValidateBeginQueryBase(context, target, id);
1017}
1018
1019bool ValidateEndQuery(gl::Context *context, GLenum target)
1020{
Martin Radev1be913c2016-07-11 17:59:16 +03001021 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001024 return false;
1025 }
1026
1027 return ValidateEndQueryBase(context, target);
1028}
1029
1030bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1031{
Martin Radev1be913c2016-07-11 17:59:16 +03001032 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001034 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001035 return false;
1036 }
1037
Geoff Lang2186c382016-10-14 10:54:54 -04001038 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001039}
1040
1041bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1042{
Martin Radev1be913c2016-07-11 17:59:16 +03001043 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001045 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001046 return false;
1047 }
1048
Geoff Lang2186c382016-10-14 10:54:54 -04001049 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001050}
1051
He Yunchaoced53ae2016-11-29 15:00:51 +08001052bool ValidateFramebufferTextureLayer(Context *context,
1053 GLenum target,
1054 GLenum attachment,
1055 GLuint texture,
1056 GLint level,
1057 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001058{
Martin Radev1be913c2016-07-11 17:59:16 +03001059 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001061 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001062 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001063 }
1064
Jamie Madill55ec3b12014-07-03 10:38:57 -04001065 if (layer < 0)
1066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001067 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001068 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001069 }
1070
1071 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1072 {
1073 return false;
1074 }
1075
1076 const gl::Caps &caps = context->getCaps();
1077 if (texture != 0)
1078 {
1079 gl::Texture *tex = context->getTexture(texture);
1080 ASSERT(tex);
1081
1082 switch (tex->getTarget())
1083 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001084 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001085 {
1086 if (level > gl::log2(caps.max2DTextureSize))
1087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001088 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001090 }
1091
1092 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001094 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001095 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001096 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001097 }
1098 break;
1099
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001101 {
1102 if (level > gl::log2(caps.max3DTextureSize))
1103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001104 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001105 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001106 }
1107
1108 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001110 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001111 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001112 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001113 }
1114 break;
1115
He Yunchaoced53ae2016-11-29 15:00:51 +08001116 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001117 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001119 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001120
Jamie Madilla3944d42016-07-22 22:13:26 -04001121 const auto &format = tex->getFormat(tex->getTarget(), level);
1122 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001124 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001125 return false;
1126 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001127 }
1128
1129 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001130}
1131
He Yunchaoced53ae2016-11-29 15:00:51 +08001132bool ValidateInvalidateFramebuffer(Context *context,
1133 GLenum target,
1134 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001135 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136{
Martin Radev1be913c2016-07-11 17:59:16 +03001137 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001138 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001140 return false;
1141 }
1142
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 bool defaultFramebuffer = false;
1144
1145 switch (target)
1146 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001147 case GL_DRAW_FRAMEBUFFER:
1148 case GL_FRAMEBUFFER:
1149 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1150 break;
1151 case GL_READ_FRAMEBUFFER:
1152 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1153 break;
1154 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
He Yunchaoced53ae2016-11-29 15:00:51 +08001159 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1160 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001161}
1162
Jamie Madillc29968b2016-01-20 11:17:23 -05001163bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001164{
Martin Radev1be913c2016-07-11 17:59:16 +03001165 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001167 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001168 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001169 }
1170
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001171 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001173 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001174 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001175 }
1176
1177 return true;
1178}
1179
Olli Etuaho71dfb362016-03-10 14:04:27 +02001180bool ValidateDrawRangeElements(Context *context,
1181 GLenum mode,
1182 GLuint start,
1183 GLuint end,
1184 GLsizei count,
1185 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001186 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001187{
Martin Radev1be913c2016-07-11 17:59:16 +03001188 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001189 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001191 return false;
1192 }
1193
1194 if (end < start)
1195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001196 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001197 return false;
1198 }
1199
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001200 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001201 {
1202 return false;
1203 }
1204
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001205 // Use the parameter buffer to retrieve and cache the index range.
1206 const auto &params = context->getParams<HasIndexRange>();
1207 const auto &indexRangeOpt = params.getIndexRange();
1208 if (!indexRangeOpt.valid())
1209 {
1210 // Unexpected error.
1211 return false;
1212 }
1213
1214 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001215 {
1216 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001218 return false;
1219 }
1220 return true;
1221}
1222
He Yunchaoced53ae2016-11-29 15:00:51 +08001223bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001224{
Martin Radev1be913c2016-07-11 17:59:16 +03001225 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001227 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001229 }
1230
Jamie Madill78f41802014-08-25 15:47:55 -04001231 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001232}
1233
Jamie Madillb885e572015-02-03 16:16:04 -05001234bool ValidateReadBuffer(Context *context, GLenum src)
1235{
Martin Radev1be913c2016-07-11 17:59:16 +03001236 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001238 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001239 return false;
1240 }
1241
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001242 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001243
1244 if (readFBO == nullptr)
1245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001247 return false;
1248 }
1249
1250 if (src == GL_NONE)
1251 {
1252 return true;
1253 }
1254
Olli Etuaho84c9f592016-03-09 14:37:25 +02001255 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001257 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001258 return false;
1259 }
1260
1261 if (readFBO->id() == 0)
1262 {
1263 if (src != GL_BACK)
1264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001265 context->handleError(
1266 InvalidOperation()
1267 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001268 return false;
1269 }
1270 }
1271 else
1272 {
1273 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1274
1275 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001277 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001278 return false;
1279 }
1280 }
1281
1282 return true;
1283}
1284
Jamie Madill86af3d22015-07-21 15:14:07 -04001285bool ValidateCompressedTexImage3D(Context *context,
1286 GLenum target,
1287 GLint level,
1288 GLenum internalformat,
1289 GLsizei width,
1290 GLsizei height,
1291 GLsizei depth,
1292 GLint border,
1293 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001294 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001295{
Martin Radev1be913c2016-07-11 17:59:16 +03001296 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001298 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001299 return false;
1300 }
1301
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001302 if (!ValidTextureTarget(context, target))
1303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001304 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001305 return false;
1306 }
1307
Jamie Madille2e406c2016-06-02 13:04:10 -04001308 // Validate image size
1309 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001311 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001312 return false;
1313 }
1314
Geoff Langca271392017-04-05 12:30:00 -04001315 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001316 if (!formatInfo.compressed)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001319 return false;
1320 }
1321
Jamie Madill513558d2016-06-02 13:04:11 -04001322 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001323 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001324 if (blockSizeOrErr.isError())
1325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001326 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001327 return false;
1328 }
1329 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001332 return false;
1333 }
1334
1335 // 3D texture target validation
1336 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001338 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001339 return false;
1340 }
1341
1342 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001343 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001344 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1345 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001346 {
1347 return false;
1348 }
1349
1350 return true;
1351}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001352
Corentin Wallezb2931602017-04-11 15:58:57 -04001353bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1354 GLenum target,
1355 GLint level,
1356 GLenum internalformat,
1357 GLsizei width,
1358 GLsizei height,
1359 GLsizei depth,
1360 GLint border,
1361 GLsizei imageSize,
1362 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001363 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001364{
1365 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1366 {
1367 return false;
1368 }
1369
1370 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1371 depth, border, imageSize, data);
1372}
1373
Austin Kinrossbc781f32015-10-26 09:27:38 -07001374bool ValidateBindVertexArray(Context *context, GLuint array)
1375{
Martin Radev1be913c2016-07-11 17:59:16 +03001376 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001379 return false;
1380 }
1381
1382 return ValidateBindVertexArrayBase(context, array);
1383}
1384
Austin Kinrossbc781f32015-10-26 09:27:38 -07001385bool ValidateIsVertexArray(Context *context)
1386{
Martin Radev1be913c2016-07-11 17:59:16 +03001387 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001389 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001390 return false;
1391 }
1392
1393 return true;
1394}
Geoff Langc5629752015-12-07 16:29:04 -05001395
Jiajia Qin6eafb042016-12-27 17:04:07 +08001396static bool ValidateBindBufferCommon(Context *context,
1397 GLenum target,
1398 GLuint index,
1399 GLuint buffer,
1400 GLintptr offset,
1401 GLsizeiptr size)
1402{
1403 if (context->getClientMajorVersion() < 3)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001406 return false;
1407 }
1408
1409 if (buffer != 0 && offset < 0)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001412 return false;
1413 }
1414
1415 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1416 !context->isBufferGenerated(buffer))
1417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001418 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001419 return false;
1420 }
1421
1422 const Caps &caps = context->getCaps();
1423 switch (target)
1424 {
1425 case GL_TRANSFORM_FEEDBACK_BUFFER:
1426 {
1427 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001429 context->handleError(InvalidValue() << "index is greater than or equal to the "
1430 "number of TRANSFORM_FEEDBACK_BUFFER "
1431 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001432 return false;
1433 }
1434 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001437 return false;
1438 }
1439
1440 TransformFeedback *curTransformFeedback =
1441 context->getGLState().getCurrentTransformFeedback();
1442 if (curTransformFeedback && curTransformFeedback->isActive())
1443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidOperation()
1445 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1446 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001447 return false;
1448 }
1449 break;
1450 }
1451 case GL_UNIFORM_BUFFER:
1452 {
1453 if (index >= caps.maxUniformBufferBindings)
1454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001455 context->handleError(InvalidValue() << "index is greater than or equal to the "
1456 "number of UNIFORM_BUFFER indexed "
1457 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001458 return false;
1459 }
1460
1461 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1462 {
1463 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001464 InvalidValue()
1465 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001466 return false;
1467 }
1468 break;
1469 }
1470 case GL_ATOMIC_COUNTER_BUFFER:
1471 {
1472 if (context->getClientVersion() < ES_3_1)
1473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001474 context->handleError(InvalidEnum()
1475 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001476 return false;
1477 }
1478 if (index >= caps.maxAtomicCounterBufferBindings)
1479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001480 context->handleError(InvalidValue() << "index is greater than or equal to the "
1481 "number of ATOMIC_COUNTER_BUFFER "
1482 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001483 return false;
1484 }
1485 if (buffer != 0 && (offset % 4) != 0)
1486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001487 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001488 return false;
1489 }
1490 break;
1491 }
1492 case GL_SHADER_STORAGE_BUFFER:
1493 {
1494 if (context->getClientVersion() < ES_3_1)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(InvalidEnum()
1497 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001498 return false;
1499 }
1500 if (index >= caps.maxShaderStorageBufferBindings)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidValue() << "index is greater than or equal to the "
1503 "number of SHADER_STORAGE_BUFFER "
1504 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001505 return false;
1506 }
1507 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidValue() << "offset must be multiple of value of "
1510 "SHADER_STORAGE_BUFFER_OFFSET_"
1511 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001512 return false;
1513 }
1514 break;
1515 }
1516 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001518 return false;
1519 }
1520
1521 return true;
1522}
1523
1524bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1525{
1526 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1527}
1528
1529bool ValidateBindBufferRange(Context *context,
1530 GLenum target,
1531 GLuint index,
1532 GLuint buffer,
1533 GLintptr offset,
1534 GLsizeiptr size)
1535{
1536 if (buffer != 0 && size <= 0)
1537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidValue()
1539 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001540 return false;
1541 }
1542 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1543}
1544
Geoff Langc5629752015-12-07 16:29:04 -05001545bool ValidateProgramBinary(Context *context,
1546 GLuint program,
1547 GLenum binaryFormat,
1548 const void *binary,
1549 GLint length)
1550{
Martin Radev1be913c2016-07-11 17:59:16 +03001551 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001554 return false;
1555 }
1556
1557 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1558}
1559
1560bool ValidateGetProgramBinary(Context *context,
1561 GLuint program,
1562 GLsizei bufSize,
1563 GLsizei *length,
1564 GLenum *binaryFormat,
1565 void *binary)
1566{
Martin Radev1be913c2016-07-11 17:59:16 +03001567 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001569 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001570 return false;
1571 }
1572
1573 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1574}
1575
Olli Etuahof0fee072016-03-30 15:11:58 +03001576bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001577{
Martin Radev1be913c2016-07-11 17:59:16 +03001578 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001581 return false;
1582 }
1583
1584 if (GetValidProgram(context, program) == nullptr)
1585 {
1586 return false;
1587 }
1588
1589 switch (pname)
1590 {
1591 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001592 if (value != GL_FALSE && value != GL_TRUE)
1593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidValue()
1595 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001596 return false;
1597 }
Geoff Langc5629752015-12-07 16:29:04 -05001598 break;
1599
Yunchao He61afff12017-03-14 15:34:03 +08001600 case GL_PROGRAM_SEPARABLE:
1601 if (context->getClientVersion() < ES_3_1)
1602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001603 context->handleError(InvalidEnum()
1604 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001605 return false;
1606 }
1607
1608 if (value != GL_FALSE && value != GL_TRUE)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidValue()
1611 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001612 return false;
1613 }
1614 break;
1615
Geoff Langc5629752015-12-07 16:29:04 -05001616 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidEnum()
1618 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001619 return false;
1620 }
1621
1622 return true;
1623}
Jamie Madillc29968b2016-01-20 11:17:23 -05001624
1625bool ValidateBlitFramebuffer(Context *context,
1626 GLint srcX0,
1627 GLint srcY0,
1628 GLint srcX1,
1629 GLint srcY1,
1630 GLint dstX0,
1631 GLint dstY0,
1632 GLint dstX1,
1633 GLint dstY1,
1634 GLbitfield mask,
1635 GLenum filter)
1636{
Martin Radev1be913c2016-07-11 17:59:16 +03001637 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001639 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001640 return false;
1641 }
1642
1643 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1644 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001645}
Jamie Madillc29968b2016-01-20 11:17:23 -05001646
1647bool ValidateClearBufferiv(ValidationContext *context,
1648 GLenum buffer,
1649 GLint drawbuffer,
1650 const GLint *value)
1651{
1652 switch (buffer)
1653 {
1654 case GL_COLOR:
1655 if (drawbuffer < 0 ||
1656 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001658 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001659 return false;
1660 }
Geoff Lang76e65652017-03-27 14:58:02 -04001661 if (context->getExtensions().webglCompatibility)
1662 {
1663 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001664 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001665 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1666 {
1667 return false;
1668 }
1669 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001670 break;
1671
1672 case GL_STENCIL:
1673 if (drawbuffer != 0)
1674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001675 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001676 return false;
1677 }
1678 break;
1679
1680 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001681 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001682 return false;
1683 }
1684
1685 return ValidateClearBuffer(context);
1686}
1687
1688bool ValidateClearBufferuiv(ValidationContext *context,
1689 GLenum buffer,
1690 GLint drawbuffer,
1691 const GLuint *value)
1692{
1693 switch (buffer)
1694 {
1695 case GL_COLOR:
1696 if (drawbuffer < 0 ||
1697 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001700 return false;
1701 }
Geoff Lang76e65652017-03-27 14:58:02 -04001702 if (context->getExtensions().webglCompatibility)
1703 {
1704 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001705 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001706 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1707 {
1708 return false;
1709 }
1710 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001711 break;
1712
1713 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001715 return false;
1716 }
1717
1718 return ValidateClearBuffer(context);
1719}
1720
1721bool ValidateClearBufferfv(ValidationContext *context,
1722 GLenum buffer,
1723 GLint drawbuffer,
1724 const GLfloat *value)
1725{
1726 switch (buffer)
1727 {
1728 case GL_COLOR:
1729 if (drawbuffer < 0 ||
1730 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001732 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001733 return false;
1734 }
Geoff Lang76e65652017-03-27 14:58:02 -04001735 if (context->getExtensions().webglCompatibility)
1736 {
1737 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1738 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001739 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001740 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1741 {
1742 return false;
1743 }
1744 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001745 break;
1746
1747 case GL_DEPTH:
1748 if (drawbuffer != 0)
1749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001750 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001751 return false;
1752 }
1753 break;
1754
1755 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001756 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001757 return false;
1758 }
1759
1760 return ValidateClearBuffer(context);
1761}
1762
1763bool ValidateClearBufferfi(ValidationContext *context,
1764 GLenum buffer,
1765 GLint drawbuffer,
1766 GLfloat depth,
1767 GLint stencil)
1768{
1769 switch (buffer)
1770 {
1771 case GL_DEPTH_STENCIL:
1772 if (drawbuffer != 0)
1773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001774 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001775 return false;
1776 }
1777 break;
1778
1779 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 return ValidateClearBuffer(context);
1785}
1786
1787bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1788{
Martin Radev1be913c2016-07-11 17:59:16 +03001789 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001790 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001792 return false;
1793 }
1794
1795 return ValidateDrawBuffersBase(context, n, bufs);
1796}
1797
1798bool ValidateCopyTexSubImage3D(Context *context,
1799 GLenum target,
1800 GLint level,
1801 GLint xoffset,
1802 GLint yoffset,
1803 GLint zoffset,
1804 GLint x,
1805 GLint y,
1806 GLsizei width,
1807 GLsizei height)
1808{
Martin Radev1be913c2016-07-11 17:59:16 +03001809 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001811 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
1814
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001815 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1816 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001817}
1818
Jamie Madill73a84962016-02-12 09:27:23 -05001819bool ValidateTexImage3D(Context *context,
1820 GLenum target,
1821 GLint level,
1822 GLint internalformat,
1823 GLsizei width,
1824 GLsizei height,
1825 GLsizei depth,
1826 GLint border,
1827 GLenum format,
1828 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001829 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001830{
Martin Radev1be913c2016-07-11 17:59:16 +03001831 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001834 return false;
1835 }
1836
1837 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001838 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001839 pixels);
1840}
1841
Geoff Langc52f6f12016-10-14 10:18:00 -04001842bool ValidateTexImage3DRobustANGLE(Context *context,
1843 GLenum target,
1844 GLint level,
1845 GLint internalformat,
1846 GLsizei width,
1847 GLsizei height,
1848 GLsizei depth,
1849 GLint border,
1850 GLenum format,
1851 GLenum type,
1852 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001853 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001854{
1855 if (context->getClientMajorVersion() < 3)
1856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001857 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001858 return false;
1859 }
1860
1861 if (!ValidateRobustEntryPoint(context, bufSize))
1862 {
1863 return false;
1864 }
1865
1866 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1867 0, 0, width, height, depth, border, format, type,
1868 bufSize, pixels);
1869}
1870
Jamie Madill73a84962016-02-12 09:27:23 -05001871bool ValidateTexSubImage3D(Context *context,
1872 GLenum target,
1873 GLint level,
1874 GLint xoffset,
1875 GLint yoffset,
1876 GLint zoffset,
1877 GLsizei width,
1878 GLsizei height,
1879 GLsizei depth,
1880 GLenum format,
1881 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001882 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001883{
Martin Radev1be913c2016-07-11 17:59:16 +03001884 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001886 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001887 return false;
1888 }
1889
1890 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1891 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001892 -1, pixels);
1893}
1894
1895bool ValidateTexSubImage3DRobustANGLE(Context *context,
1896 GLenum target,
1897 GLint level,
1898 GLint xoffset,
1899 GLint yoffset,
1900 GLint zoffset,
1901 GLsizei width,
1902 GLsizei height,
1903 GLsizei depth,
1904 GLenum format,
1905 GLenum type,
1906 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001907 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001908{
1909 if (context->getClientMajorVersion() < 3)
1910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001911 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001912 return false;
1913 }
1914
1915 if (!ValidateRobustEntryPoint(context, bufSize))
1916 {
1917 return false;
1918 }
1919
1920 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1921 yoffset, zoffset, width, height, depth, 0, format, type,
1922 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001923}
1924
1925bool ValidateCompressedTexSubImage3D(Context *context,
1926 GLenum target,
1927 GLint level,
1928 GLint xoffset,
1929 GLint yoffset,
1930 GLint zoffset,
1931 GLsizei width,
1932 GLsizei height,
1933 GLsizei depth,
1934 GLenum format,
1935 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001936 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001937{
Martin Radev1be913c2016-07-11 17:59:16 +03001938 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001940 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001941 return false;
1942 }
1943
Geoff Langca271392017-04-05 12:30:00 -04001944 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001945 if (!formatInfo.compressed)
1946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001947 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001948 return false;
1949 }
1950
Jamie Madill513558d2016-06-02 13:04:11 -04001951 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001952 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001953 if (blockSizeOrErr.isError())
1954 {
1955 context->handleError(blockSizeOrErr.getError());
1956 return false;
1957 }
1958 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001960 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001961 return false;
1962 }
1963
1964 if (!data)
1965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001966 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001967 return false;
1968 }
1969
1970 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001971 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001972}
Corentin Wallezb2931602017-04-11 15:58:57 -04001973bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1974 GLenum target,
1975 GLint level,
1976 GLint xoffset,
1977 GLint yoffset,
1978 GLint zoffset,
1979 GLsizei width,
1980 GLsizei height,
1981 GLsizei depth,
1982 GLenum format,
1983 GLsizei imageSize,
1984 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001985 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001986{
1987 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1988 {
1989 return false;
1990 }
1991
1992 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1993 height, depth, format, imageSize, data);
1994}
Jamie Madill73a84962016-02-12 09:27:23 -05001995
Olli Etuaho41997e72016-03-10 13:38:39 +02001996bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1997{
1998 return ValidateGenOrDeleteES3(context, n);
1999}
2000
2001bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2002{
2003 return ValidateGenOrDeleteES3(context, n);
2004}
2005
2006bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2007{
2008 return ValidateGenOrDeleteCountES3(context, count);
2009}
2010
2011bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2012{
2013 return ValidateGenOrDeleteCountES3(context, count);
2014}
2015
2016bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2017{
2018 return ValidateGenOrDeleteES3(context, n);
2019}
2020
2021bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2022{
2023 if (!ValidateGenOrDeleteES3(context, n))
2024 {
2025 return false;
2026 }
2027 for (GLint i = 0; i < n; ++i)
2028 {
2029 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2030 if (transformFeedback != nullptr && transformFeedback->isActive())
2031 {
2032 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002033 context->handleError(InvalidOperation()
2034 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002035 return false;
2036 }
2037 }
2038 return true;
2039}
2040
2041bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2042{
2043 return ValidateGenOrDeleteES3(context, n);
2044}
2045
2046bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2047{
2048 return ValidateGenOrDeleteES3(context, n);
2049}
2050
2051bool ValidateGenOrDeleteES3(Context *context, GLint n)
2052{
Martin Radev1be913c2016-07-11 17:59:16 +03002053 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002055 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002056 return false;
2057 }
2058 return ValidateGenOrDelete(context, n);
2059}
2060
2061bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2062{
Martin Radev1be913c2016-07-11 17:59:16 +03002063 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002064 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho41997e72016-03-10 13:38:39 +02002066 return false;
2067 }
2068 if (count < 0)
2069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002070 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02002071 return false;
2072 }
2073 return true;
2074}
2075
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002076bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2077{
Martin Radev1be913c2016-07-11 17:59:16 +03002078 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002079 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002081 return false;
2082 }
2083 switch (primitiveMode)
2084 {
2085 case GL_TRIANGLES:
2086 case GL_LINES:
2087 case GL_POINTS:
2088 break;
2089
2090 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002091 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002092 return false;
2093 }
2094
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002095 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002096 ASSERT(transformFeedback != nullptr);
2097
2098 if (transformFeedback->isActive())
2099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002100 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002101 return false;
2102 }
Geoff Lang79f71042017-08-14 16:43:43 -04002103
2104 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2105 {
2106 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2107 if (buffer.get() && buffer->isMapped())
2108 {
2109 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2110 return false;
2111 }
2112 }
2113
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002114 return true;
2115}
2116
Jamie Madill876429b2017-04-20 15:46:24 -04002117bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002118{
Geoff Lang496c02d2016-10-20 11:38:11 -07002119 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2120}
2121
2122bool ValidateGetBufferPointervRobustANGLE(Context *context,
2123 GLenum target,
2124 GLenum pname,
2125 GLsizei bufSize,
2126 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002127 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002128{
2129 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002130 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002131 return false;
2132 }
2133
Geoff Lang496c02d2016-10-20 11:38:11 -07002134 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2135 {
2136 return false;
2137 }
2138
2139 if (!ValidateRobustBufferSize(context, bufSize, *length))
2140 {
2141 return false;
2142 }
2143
2144 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002145}
2146
2147bool ValidateUnmapBuffer(Context *context, GLenum target)
2148{
Martin Radev1be913c2016-07-11 17:59:16 +03002149 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002151 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002152 return false;
2153 }
2154
2155 return ValidateUnmapBufferBase(context, target);
2156}
2157
2158bool ValidateMapBufferRange(Context *context,
2159 GLenum target,
2160 GLintptr offset,
2161 GLsizeiptr length,
2162 GLbitfield access)
2163{
Martin Radev1be913c2016-07-11 17:59:16 +03002164 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002167 return false;
2168 }
2169
2170 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2171}
2172
2173bool ValidateFlushMappedBufferRange(Context *context,
2174 GLenum target,
2175 GLintptr offset,
2176 GLsizeiptr length)
2177{
Martin Radev1be913c2016-07-11 17:59:16 +03002178 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002179 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002181 return false;
2182 }
2183
2184 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2185}
2186
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002187bool ValidateIndexedStateQuery(ValidationContext *context,
2188 GLenum pname,
2189 GLuint index,
2190 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002191{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002192 if (length)
2193 {
2194 *length = 0;
2195 }
2196
Martin Radev66fb8202016-07-28 11:45:20 +03002197 GLenum nativeType;
2198 unsigned int numParams;
2199 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002201 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002202 return false;
2203 }
2204
2205 const Caps &caps = context->getCaps();
2206 switch (pname)
2207 {
2208 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2209 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2210 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2211 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002213 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002214 return false;
2215 }
2216 break;
2217
2218 case GL_UNIFORM_BUFFER_START:
2219 case GL_UNIFORM_BUFFER_SIZE:
2220 case GL_UNIFORM_BUFFER_BINDING:
2221 if (index >= caps.maxUniformBufferBindings)
2222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002223 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002224 return false;
2225 }
2226 break;
Shao80957d92017-02-20 21:25:59 +08002227
Martin Radev66fb8202016-07-28 11:45:20 +03002228 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2229 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2230 if (index >= 3u)
2231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002232 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002233 return false;
2234 }
2235 break;
Shao80957d92017-02-20 21:25:59 +08002236
Jiajia Qin6eafb042016-12-27 17:04:07 +08002237 case GL_ATOMIC_COUNTER_BUFFER_START:
2238 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2239 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2240 if (context->getClientVersion() < ES_3_1)
2241 {
2242 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 InvalidEnum()
2244 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002245 return false;
2246 }
2247 if (index >= caps.maxAtomicCounterBufferBindings)
2248 {
2249 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002250 InvalidValue()
2251 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002252 return false;
2253 }
2254 break;
Shao80957d92017-02-20 21:25:59 +08002255
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002256 case GL_SHADER_STORAGE_BUFFER_START:
2257 case GL_SHADER_STORAGE_BUFFER_SIZE:
2258 case GL_SHADER_STORAGE_BUFFER_BINDING:
2259 if (context->getClientVersion() < ES_3_1)
2260 {
2261 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002262 InvalidEnum()
2263 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002264 return false;
2265 }
2266 if (index >= caps.maxShaderStorageBufferBindings)
2267 {
2268 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002269 InvalidValue()
2270 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002271 return false;
2272 }
2273 break;
2274
Shao80957d92017-02-20 21:25:59 +08002275 case GL_VERTEX_BINDING_BUFFER:
2276 case GL_VERTEX_BINDING_DIVISOR:
2277 case GL_VERTEX_BINDING_OFFSET:
2278 case GL_VERTEX_BINDING_STRIDE:
2279 if (context->getClientVersion() < ES_3_1)
2280 {
2281 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002282 InvalidEnum()
2283 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002284 return false;
2285 }
2286 if (index >= caps.maxVertexAttribBindings)
2287 {
2288 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002289 InvalidValue()
2290 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002291 return false;
2292 }
2293 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002294 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002295 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002296 return false;
2297 }
2298
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002299 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002300 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002301 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002302 }
2303
2304 return true;
2305}
2306
2307bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2308{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002309 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002310 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002312 return false;
2313 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002314 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002315}
2316
Geoff Langcf255ea2016-10-20 11:39:09 -07002317bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2318 GLenum target,
2319 GLuint index,
2320 GLsizei bufSize,
2321 GLsizei *length,
2322 GLint *data)
2323{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002324 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002325 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002327 return false;
2328 }
2329
2330 if (!ValidateRobustEntryPoint(context, bufSize))
2331 {
2332 return false;
2333 }
2334
2335 if (!ValidateIndexedStateQuery(context, target, index, length))
2336 {
2337 return false;
2338 }
2339
2340 if (!ValidateRobustBufferSize(context, bufSize, *length))
2341 {
2342 return false;
2343 }
2344
2345 return true;
2346}
2347
Martin Radev66fb8202016-07-28 11:45:20 +03002348bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2349{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002350 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002351 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002352 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002353 return false;
2354 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002355 return ValidateIndexedStateQuery(context, target, index, nullptr);
2356}
2357
2358bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2359 GLenum target,
2360 GLuint index,
2361 GLsizei bufSize,
2362 GLsizei *length,
2363 GLint64 *data)
2364{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002365 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002366 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002367 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002368 return false;
2369 }
2370
2371 if (!ValidateRobustEntryPoint(context, bufSize))
2372 {
2373 return false;
2374 }
2375
2376 if (!ValidateIndexedStateQuery(context, target, index, length))
2377 {
2378 return false;
2379 }
2380
2381 if (!ValidateRobustBufferSize(context, bufSize, *length))
2382 {
2383 return false;
2384 }
2385
2386 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002387}
2388
Jamie Madillb0817d12016-11-01 15:48:31 -04002389bool ValidateCopyBufferSubData(ValidationContext *context,
2390 GLenum readTarget,
2391 GLenum writeTarget,
2392 GLintptr readOffset,
2393 GLintptr writeOffset,
2394 GLsizeiptr size)
2395{
2396 if (context->getClientMajorVersion() < 3)
2397 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002398 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002399 return false;
2400 }
2401
2402 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002404 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002405 return false;
2406 }
2407
2408 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2409 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2410
2411 if (!readBuffer || !writeBuffer)
2412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002413 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002414 return false;
2415 }
2416
2417 // Verify that readBuffer and writeBuffer are not currently mapped
2418 if (readBuffer->isMapped() || writeBuffer->isMapped())
2419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002420 context->handleError(InvalidOperation()
2421 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002422 return false;
2423 }
2424
Jamie Madilld2f0c742016-11-02 10:34:41 -04002425 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2426 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2427 CheckedNumeric<GLintptr> checkedSize(size);
2428
2429 auto checkedReadSum = checkedReadOffset + checkedSize;
2430 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2431
2432 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2433 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2434 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002436 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002437 return false;
2438 }
2439
Jamie Madilld2f0c742016-11-02 10:34:41 -04002440 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002442 context->handleError(InvalidValue()
2443 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002444 return false;
2445 }
2446
Jamie Madilld2f0c742016-11-02 10:34:41 -04002447 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2448 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002450 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002451 return false;
2452 }
2453
2454 if (readBuffer == writeBuffer)
2455 {
2456 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2457 if (!checkedOffsetDiff.IsValid())
2458 {
2459 // This shold not be possible.
2460 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002461 context->handleError(InvalidValue()
2462 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002463 return false;
2464 }
2465
2466 if (checkedOffsetDiff.ValueOrDie() < size)
2467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002468 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002469 return false;
2470 }
2471 }
2472
Jamie Madillb0817d12016-11-01 15:48:31 -04002473 return true;
2474}
2475
Geoff Langc339c4e2016-11-29 10:37:36 -05002476bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2477{
2478 if (context->getClientMajorVersion() < 3)
2479 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002480 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002481 return false;
2482 }
2483
2484 switch (name)
2485 {
2486 case GL_EXTENSIONS:
2487 if (index >= context->getExtensionStringCount())
2488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002489 context->handleError(InvalidValue()
2490 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002491 return false;
2492 }
2493 break;
2494
2495 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2496 if (!context->getExtensions().requestExtension)
2497 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002498 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002499 return false;
2500 }
2501 if (index >= context->getRequestableExtensionStringCount())
2502 {
2503 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 InvalidValue()
2505 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002506 return false;
2507 }
2508 break;
2509
2510 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002511 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002512 return false;
2513 }
2514
2515 return true;
2516}
2517
Jamie Madille8fb6402017-02-14 17:56:40 -05002518bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2519 GLenum target,
2520 GLsizei samples,
2521 GLenum internalformat,
2522 GLsizei width,
2523 GLsizei height)
2524{
2525 if (context->getClientMajorVersion() < 3)
2526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002527 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002528 return false;
2529 }
2530
2531 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2532 height))
2533 {
2534 return false;
2535 }
2536
2537 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2538 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002539 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002540 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2541 samples > 0)
2542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002543 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002544 return false;
2545 }
2546
2547 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2548 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2549 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2550 {
2551 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002552 InvalidOperation()
2553 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002554 return false;
2555 }
2556
2557 return true;
2558}
2559
Geoff Langaa086d62017-03-23 16:47:21 -04002560bool ValidateVertexAttribIPointer(ValidationContext *context,
2561 GLuint index,
2562 GLint size,
2563 GLenum type,
2564 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002565 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002566{
2567 if (context->getClientMajorVersion() < 3)
2568 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002569 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002570 return false;
2571 }
2572
Shao80957d92017-02-20 21:25:59 +08002573 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002574 {
Geoff Langaa086d62017-03-23 16:47:21 -04002575 return false;
2576 }
2577
Geoff Langaa086d62017-03-23 16:47:21 -04002578 if (stride < 0)
2579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002580 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002581 return false;
2582 }
2583
Shao80957d92017-02-20 21:25:59 +08002584 const Caps &caps = context->getCaps();
2585 if (context->getClientVersion() >= ES_3_1)
2586 {
2587 if (stride > caps.maxVertexAttribStride)
2588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002589 context->handleError(InvalidValue()
2590 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002591 return false;
2592 }
2593
2594 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2595 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2596 // validation should be inherited.
2597 if (index >= caps.maxVertexAttribBindings)
2598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002599 context->handleError(InvalidValue()
2600 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002601 return false;
2602 }
2603 }
2604
Geoff Langaa086d62017-03-23 16:47:21 -04002605 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2606 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2607 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2608 // and the pointer argument is not NULL.
2609 if (context->getGLState().getVertexArrayId() != 0 &&
2610 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002612 context
2613 ->handleError(InvalidOperation()
2614 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002615 return false;
2616 }
2617
Geoff Lang2d62ab72017-03-23 16:54:40 -04002618 if (context->getExtensions().webglCompatibility)
2619 {
2620 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2621 {
2622 return false;
2623 }
2624 }
2625
Geoff Langaa086d62017-03-23 16:47:21 -04002626 return true;
2627}
2628
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002629bool ValidateGetSynciv(Context *context,
2630 GLsync sync,
2631 GLenum pname,
2632 GLsizei bufSize,
2633 GLsizei *length,
2634 GLint *values)
2635{
2636 if (context->getClientMajorVersion() < 3)
2637 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002639 return false;
2640 }
2641
2642 if (bufSize < 0)
2643 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002644 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002645 return false;
2646 }
2647
2648 FenceSync *fenceSync = context->getFenceSync(sync);
2649 if (!fenceSync)
2650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002651 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002652 return false;
2653 }
2654
2655 switch (pname)
2656 {
2657 case GL_OBJECT_TYPE:
2658 case GL_SYNC_CONDITION:
2659 case GL_SYNC_FLAGS:
2660 case GL_SYNC_STATUS:
2661 break;
2662
2663 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002665 return false;
2666 }
2667
2668 return true;
2669}
2670
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002671bool ValidateDrawElementsInstanced(ValidationContext *context,
2672 GLenum mode,
2673 GLsizei count,
2674 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002675 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002676 GLsizei instanceCount)
2677{
2678 if (context->getClientMajorVersion() < 3)
2679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002680 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002681 return false;
2682 }
2683
2684 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2685}
2686
Martin Radev137032d2017-07-13 10:11:12 +03002687bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2688 GLenum target,
2689 GLenum attachment,
2690 GLuint texture,
2691 GLint level,
2692 GLint baseViewIndex,
2693 GLsizei numViews)
2694{
2695
2696 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2697 numViews))
2698 {
2699 return false;
2700 }
2701
2702 if (baseViewIndex < 0)
2703 {
2704 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2705 return false;
2706 }
2707
2708 if (texture != 0)
2709 {
2710 Texture *tex = context->getTexture(texture);
2711 ASSERT(tex);
2712
2713 switch (tex->getTarget())
2714 {
2715 case GL_TEXTURE_2D_ARRAY:
2716 {
2717 const Caps &caps = context->getCaps();
2718 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2719 {
2720 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2721 "greater than "
2722 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2723 return false;
2724 }
2725 }
2726 break;
2727 default:
2728 context->handleError(InvalidOperation()
2729 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2730 return false;
2731 }
2732
2733 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2734 {
2735 return false;
2736 }
2737 }
2738
2739 return true;
2740}
2741
2742bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2743 GLenum target,
2744 GLenum attachment,
2745 GLuint texture,
2746 GLint level,
2747 GLsizei numViews,
2748 const GLint *viewportOffsets)
2749{
2750 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2751 numViews))
2752 {
2753 return false;
2754 }
2755
2756 const GLsizei numViewportOffsetValues = numViews * 2;
2757 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2758 {
2759 if (viewportOffsets[i] < 0)
2760 {
2761 context->handleError(InvalidValue()
2762 << "viewportOffsets cannot contain negative values.");
2763 return false;
2764 }
2765 }
2766
2767 if (texture != 0)
2768 {
2769 Texture *tex = context->getTexture(texture);
2770 ASSERT(tex);
2771
2772 switch (tex->getTarget())
2773 {
2774 case GL_TEXTURE_2D:
2775 break;
2776 default:
2777 context->handleError(InvalidOperation()
2778 << "Texture's target must be GL_TEXTURE_2D.");
2779 return false;
2780 }
2781
2782 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2783 {
2784 return false;
2785 }
2786 }
2787
2788 return true;
2789}
2790
Jamie Madillff325f12017-08-26 15:06:05 -04002791bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2792{
2793 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2794}
2795
2796bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2797{
2798 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2799}
2800
2801bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2802{
2803 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2804}
2805
2806bool ValidateUniform4ui(Context *context,
2807 GLint location,
2808 GLuint v0,
2809 GLuint v1,
2810 GLuint v2,
2811 GLuint v3)
2812{
2813 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2814}
2815
2816bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2817{
2818 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2819}
2820
2821bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2822{
2823 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2824}
2825
2826bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2827{
2828 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2829}
2830
2831bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2832{
2833 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2834}
2835
Jamie Madillf0e04492017-08-26 15:28:42 -04002836bool ValidateIsQuery(Context *context, GLuint id)
2837{
2838 if (context->getClientMajorVersion() < 3)
2839 {
2840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2841 return false;
2842 }
2843
2844 return true;
2845}
2846
Jamie Madillc29968b2016-01-20 11:17:23 -05002847} // namespace gl