blob: 913d2388962a0e8b4799ef99e0ca61e12f254c83 [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
Jamie Madillc8c95812017-08-26 18:40:09 -040096bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101{
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110}
111
Jamie Madillff325f12017-08-26 15:06:05 -0400112} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300113
He Yunchaoced53ae2016-11-29 15:00:51 +0800114static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -0400115 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800116 GLenum internalFormat,
117 GLenum format,
118 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400119{
Geoff Lang5d601382014-07-22 15:14:06 -0400120
121 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400122 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400123 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400125 return false;
126 }
127
128 if (!ValidES3Type(type))
129 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400131 return false;
132 }
133
134 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
135 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
136 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
137 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
138 if (!ValidES3InternalFormat(internalFormat))
139 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700140 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400141 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400142 }
143
Geoff Langca271392017-04-05 12:30:00 -0400144 // From the ES 3.0 spec section 3.8.3:
145 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
146 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
147 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
148 // INVALID_OPERATION error.
149 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500151 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
152 "GL_DEPTH_STENCIL if target is "
153 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400154 return false;
155 }
156
Geoff Lang5d601382014-07-22 15:14:06 -0400157 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400158 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500160 context->handleError(InvalidOperation()
161 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400162 return false;
163 }
164
165 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
166 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500168 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400169 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400170 }
171
172 return true;
173}
174
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500175bool ValidateES3TexImageParametersBase(Context *context,
176 GLenum target,
177 GLint level,
178 GLenum internalformat,
179 bool isCompressed,
180 bool isSubImage,
181 GLint xoffset,
182 GLint yoffset,
183 GLint zoffset,
184 GLsizei width,
185 GLsizei height,
186 GLsizei depth,
187 GLint border,
188 GLenum format,
189 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400190 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400191 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400192{
193 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700194 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500196 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 }
199
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400200 // Verify zero border
201 if (border != 0)
202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500203 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400205 }
206
Jamie Madill6f38f822014-06-06 17:12:20 -0400207 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
208 std::numeric_limits<GLsizei>::max() - xoffset < width ||
209 std::numeric_limits<GLsizei>::max() - yoffset < height ||
210 std::numeric_limits<GLsizei>::max() - zoffset < depth)
211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500212 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400213 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400214 }
215
Geoff Langaae65a42014-05-26 12:43:44 -0400216 const gl::Caps &caps = context->getCaps();
217
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400218 switch (target)
219 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800220 case GL_TEXTURE_2D:
221 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
222 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500224 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800225 return false;
226 }
227 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400228
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400229 case GL_TEXTURE_RECTANGLE_ANGLE:
230 ASSERT(level == 0);
231 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
232 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
233 {
234 context->handleError(InvalidValue());
235 return false;
236 }
237 if (isCompressed)
238 {
239 context->handleError(InvalidEnum()
240 << "Rectangle texture cannot have a compressed format.");
241 return false;
242 }
243 break;
244
He Yunchaoced53ae2016-11-29 15:00:51 +0800245 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
246 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
247 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
248 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
249 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
250 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
251 if (!isSubImage && width != height)
252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500253 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800254 return false;
255 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400256
He Yunchaoced53ae2016-11-29 15:00:51 +0800257 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500259 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800260 return false;
261 }
262 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400263
He Yunchaoced53ae2016-11-29 15:00:51 +0800264 case GL_TEXTURE_3D:
265 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
266 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
267 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500269 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 return false;
271 }
272 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400273
He Yunchaoced53ae2016-11-29 15:00:51 +0800274 case GL_TEXTURE_2D_ARRAY:
275 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
276 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
277 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500279 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800280 return false;
281 }
282 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400283
He Yunchaoced53ae2016-11-29 15:00:51 +0800284 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500285 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800286 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400287 }
288
He Yunchaoced53ae2016-11-29 15:00:51 +0800289 gl::Texture *texture =
290 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400291 if (!texture)
292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500293 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400294 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295 }
296
Geoff Lang69cce582015-09-17 13:20:36 -0400297 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500299 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400301 }
302
303 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400304 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400305 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500306 if (isSubImage && actualInternalFormat == GL_NONE)
307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500308 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500309 return false;
310 }
311
Geoff Langc4e93662017-05-01 10:45:59 -0400312 const gl::InternalFormat &actualFormatInfo = isSubImage
313 ? *texture->getFormat(target, level).info
314 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 if (isCompressed)
316 {
tmartino7c102692015-10-02 16:43:40 -0400317 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500319 context->handleError(
320 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400322 }
323
Geoff Lang966c9402017-04-18 12:38:27 -0400324 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Geoff Lang966c9402017-04-18 12:38:27 -0400326 if (!ValidCompressedSubImageSize(
327 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
328 texture->getWidth(target, level), texture->getHeight(target, level)))
329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500330 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400331 return false;
332 }
333
334 if (format != actualInternalFormat)
335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500336 context->handleError(InvalidOperation()
337 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400338 return false;
339 }
340 }
341 else
342 {
343 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500345 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400346 return false;
347 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348 }
349
Geoff Langeb66a6e2016-10-31 13:06:12 -0400350 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500352 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400353 return false;
354 }
355
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 if (target == GL_TEXTURE_3D)
357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500358 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400360 }
361 }
362 else
363 {
Geoff Langca271392017-04-05 12:30:00 -0400364 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400365 {
Geoff Lang5d601382014-07-22 15:14:06 -0400366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 }
369
370 // Validate sub image parameters
371 if (isSubImage)
372 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500373 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500375 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400376 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377 }
378
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
380 {
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 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
386 std::numeric_limits<GLsizei>::max() - yoffset < height ||
387 std::numeric_limits<GLsizei>::max() - zoffset < depth)
388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500389 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392
Geoff Langa9be0dc2014-12-17 12:34:40 -0500393 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
394 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
395 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500397 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 }
400 }
401
Geoff Langdbcced82017-06-06 15:55:54 -0400402 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
403 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
404 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400405 {
406 return false;
407 }
408
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400409 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700410 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400411 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400412 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800413 // ...data is not evenly divisible into the number of bytes needed to store in memory a
414 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400415 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400416 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400417 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400418 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400419 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
420
Geoff Langff5b2d52016-09-07 11:32:23 -0400421 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500423 context->handleError(InvalidOperation()
424 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400425 return false;
426 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400427 }
428
Jamie Madill7a5f7382014-03-05 15:01:24 -0500429 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700430 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500432 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400433 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500434 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400435 }
436
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400437 return true;
438}
439
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500440bool ValidateES3TexImage2DParameters(Context *context,
441 GLenum target,
442 GLint level,
443 GLenum internalformat,
444 bool isCompressed,
445 bool isSubImage,
446 GLint xoffset,
447 GLint yoffset,
448 GLint zoffset,
449 GLsizei width,
450 GLsizei height,
451 GLsizei depth,
452 GLint border,
453 GLenum format,
454 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400455 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400456 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500457{
458 if (!ValidTexture2DDestinationTarget(context, target))
459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500460 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500461 return false;
462 }
463
464 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
465 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400466 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500467}
468
469bool ValidateES3TexImage3DParameters(Context *context,
470 GLenum target,
471 GLint level,
472 GLenum internalformat,
473 bool isCompressed,
474 bool isSubImage,
475 GLint xoffset,
476 GLint yoffset,
477 GLint zoffset,
478 GLsizei width,
479 GLsizei height,
480 GLsizei depth,
481 GLint border,
482 GLenum format,
483 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400484 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400485 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500486{
487 if (!ValidTexture3DDestinationTarget(context, target))
488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500489 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500490 return false;
491 }
492
493 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
494 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400495 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500496}
497
Geoff Lang5d601382014-07-22 15:14:06 -0400498struct EffectiveInternalFormatInfo
499{
Jamie Madill76648fe2016-10-05 17:01:41 -0400500 GLenum effectiveFormat;
501 GLenum destFormat;
502 GLuint minRedBits;
503 GLuint maxRedBits;
504 GLuint minGreenBits;
505 GLuint maxGreenBits;
506 GLuint minBlueBits;
507 GLuint maxBlueBits;
508 GLuint minAlphaBits;
509 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400510};
511
Jamie Madill76648fe2016-10-05 17:01:41 -0400512static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
513 GLenum targetFormat,
514 const EffectiveInternalFormatInfo *list,
515 size_t size,
516 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400517{
Jamie Madill76648fe2016-10-05 17:01:41 -0400518 for (size_t curFormat = 0; curFormat < size; ++curFormat)
519 {
520 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
521 if ((formatInfo.destFormat == targetFormat) &&
522 (formatInfo.minRedBits <= srcFormat.redBits &&
523 formatInfo.maxRedBits >= srcFormat.redBits) &&
524 (formatInfo.minGreenBits <= srcFormat.greenBits &&
525 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
526 (formatInfo.minBlueBits <= srcFormat.blueBits &&
527 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
528 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
529 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
530 {
531 *outEffectiveFormat = formatInfo.effectiveFormat;
532 return true;
533 }
534 }
Geoff Lang5d601382014-07-22 15:14:06 -0400535
Jamie Madill76648fe2016-10-05 17:01:41 -0400536 *outEffectiveFormat = GL_NONE;
537 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400538}
539
Jamie Madill76648fe2016-10-05 17:01:41 -0400540bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
541 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400542{
Jamie Madill76648fe2016-10-05 17:01:41 -0400543 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
544 // Effective internal format coresponding to destination internal format and linear source
545 // buffer component sizes.
546 // | Source channel min/max sizes |
547 // Effective Internal Format | N/A | R | G | B | A |
548 // clang-format off
549 constexpr EffectiveInternalFormatInfo list[] = {
550 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
551 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
552 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
553 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
554 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
555 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
556 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
557 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
558 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
559 };
560 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400561
Jamie Madill76648fe2016-10-05 17:01:41 -0400562 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
563}
Geoff Lang5d601382014-07-22 15:14:06 -0400564
Jamie Madill76648fe2016-10-05 17:01:41 -0400565bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
566 const InternalFormat &destFormat,
567 GLenum *outEffectiveFormat)
568{
569 constexpr GLuint umax = UINT_MAX;
570
571 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
572 // Effective internal format coresponding to destination internal format andlinear source buffer
573 // component sizes.
574 // | Source channel min/max sizes |
575 // Effective Internal Format | Dest Format | R | G | B | A |
576 // clang-format off
577 constexpr EffectiveInternalFormatInfo list[] = {
578 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
579 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
580 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
581 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
582 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
583 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
584 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
585 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
586 };
587 // clang-format on
588
589 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
590 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400591}
592
He Yunchaoced53ae2016-11-29 15:00:51 +0800593static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
594 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400595 GLenum *outEffectiveFormat)
596{
Geoff Langca271392017-04-05 12:30:00 -0400597 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400598 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400599 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400600 }
601 else
602 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400603 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400604 }
Geoff Lang5d601382014-07-22 15:14:06 -0400605}
606
Corentin Wallez76287682016-04-25 09:23:38 -0400607static bool EqualOrFirstZero(GLuint first, GLuint second)
608{
609 return first == 0 || first == second;
610}
611
Geoff Langca271392017-04-05 12:30:00 -0400612static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
613 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400614 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400615{
Jamie Madill21b786b2016-11-01 17:41:31 -0400616 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400617 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400618 return false;
619 }
Geoff Lang5d601382014-07-22 15:14:06 -0400620
Jamie Madill21b786b2016-11-01 17:41:31 -0400621 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
622 // must both be signed, unsigned, or fixed point and both source and destinations
623 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
624 // conversion between fixed and floating point.
625
626 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
627 (framebufferFormatInfo.colorEncoding == GL_SRGB))
628 {
629 return false;
630 }
631
632 if (((textureFormatInfo.componentType == GL_INT) !=
633 (framebufferFormatInfo.componentType == GL_INT)) ||
634 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
635 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
636 {
637 return false;
638 }
639
640 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
641 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
642 textureFormatInfo.componentType == GL_FLOAT) &&
643 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
644 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
645 framebufferFormatInfo.componentType == GL_FLOAT))
646 {
647 return false;
648 }
649
650 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
651 // The effective internal format of the source buffer is determined with the following rules
652 // applied in order:
653 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
654 // format then the effective internal format is the source buffer's sized internal format.
655 // * If the source buffer is a texture that was created with an unsized base internal format,
656 // then the effective internal format is the source image array's effective internal
657 // format, as specified by table 3.12, which is determined from the <format> and <type>
658 // that were used when the source image array was specified by TexImage*.
659 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
660 // where Destination Internal Format matches internalformat and where the [source channel
661 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
662 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
663 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800664 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400665 if (readBufferHandle != 0)
666 {
667 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
668 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400669 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400670 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400671 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400672 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400673 else
Geoff Lang5d601382014-07-22 15:14:06 -0400674 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400675 // Renderbuffers cannot be created with an unsized internal format, so this must be an
676 // unsized-format texture. We can use the same table we use when creating textures to
677 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400678 sourceEffectiveFormat =
679 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400680 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400681 }
682 else
683 {
684 // The effective internal format must be derived from the source framebuffer's channel
685 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
686 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400687 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400688 GLenum effectiveFormat;
689 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
690 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400691 {
Geoff Langca271392017-04-05 12:30:00 -0400692 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400693 }
694 else
695 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400696 return false;
697 }
698 }
699 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
700 {
701 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400702 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400703 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
704 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
705 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
706 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
707 {
Geoff Langca271392017-04-05 12:30:00 -0400708 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400709 }
710 else
711 {
712 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400713 }
714 }
715 else
716 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400717 UNREACHABLE();
718 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400719 }
Geoff Lang5d601382014-07-22 15:14:06 -0400720 }
721
Geoff Langca271392017-04-05 12:30:00 -0400722 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400723 {
724 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
725 // sized, component sizes of the source and destination formats must exactly match if the
726 // destination format exists.
727 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
728 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
729 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
730 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
731 {
732 return false;
733 }
734 }
735
736 return true; // A conversion function exists, and no rule in the specification has precluded
737 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400738}
739
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500740bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
741 GLenum target,
742 GLint level,
743 GLenum internalformat,
744 bool isSubImage,
745 GLint xoffset,
746 GLint yoffset,
747 GLint zoffset,
748 GLint x,
749 GLint y,
750 GLsizei width,
751 GLsizei height,
752 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400754 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400755 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400756 xoffset, yoffset, zoffset, x, y, width, height, border,
757 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400758 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400761 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400762
Jamie Madill51f40ec2016-06-15 14:06:00 -0400763 const auto &state = context->getGLState();
764 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
765 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400766
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400767 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500769 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400770 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400771 }
772
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400773 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500775 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400776 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400777 }
778
Jamie Madill0c8abca2016-07-22 20:21:26 -0400779 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780
781 if (isSubImage)
782 {
Geoff Langca271392017-04-05 12:30:00 -0400783 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500784 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500786 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400787 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 }
789 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400790 else
791 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400792 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400793 const InternalFormat &framebufferFormat = *source->getFormat().info;
794 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400795 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500797 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400798 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400799 }
800 }
801
Geoff Lang784a8fd2013-09-24 12:33:16 -0400802 // If width or height is zero, it is a no-op. Return false without setting an error.
803 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804}
805
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500806bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
807 GLenum target,
808 GLint level,
809 GLenum internalformat,
810 bool isSubImage,
811 GLint xoffset,
812 GLint yoffset,
813 GLint zoffset,
814 GLint x,
815 GLint y,
816 GLsizei width,
817 GLsizei height,
818 GLint border)
819{
820 if (!ValidTexture2DDestinationTarget(context, target))
821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500822 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500823 return false;
824 }
825
826 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
827 xoffset, yoffset, zoffset, x, y, width, height,
828 border);
829}
830
831bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
832 GLenum target,
833 GLint level,
834 GLenum internalformat,
835 bool isSubImage,
836 GLint xoffset,
837 GLint yoffset,
838 GLint zoffset,
839 GLint x,
840 GLint y,
841 GLsizei width,
842 GLsizei height,
843 GLint border)
844{
845 if (!ValidTexture3DDestinationTarget(context, target))
846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500847 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500848 return false;
849 }
850
851 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
852 xoffset, yoffset, zoffset, x, y, width, height,
853 border);
854}
855
856bool ValidateES3TexStorageParametersBase(Context *context,
857 GLenum target,
858 GLsizei levels,
859 GLenum internalformat,
860 GLsizei width,
861 GLsizei height,
862 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863{
864 if (width < 1 || height < 1 || depth < 1 || levels < 1)
865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500866 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400867 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868 }
869
Geoff Langb92c1332015-09-04 12:54:55 -0400870 GLsizei maxDim = std::max(width, height);
871 if (target != GL_TEXTURE_2D_ARRAY)
872 {
873 maxDim = std::max(maxDim, depth);
874 }
875
876 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400879 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400880 }
881
Geoff Langaae65a42014-05-26 12:43:44 -0400882 const gl::Caps &caps = context->getCaps();
883
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400884 switch (target)
885 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800886 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400887 {
Geoff Langaae65a42014-05-26 12:43:44 -0400888 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
889 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400892 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 }
894 }
895 break;
896
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400897 case GL_TEXTURE_RECTANGLE_ANGLE:
898 {
899 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
900 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
901 {
902 context->handleError(InvalidValue());
903 return false;
904 }
905 }
906 break;
907
He Yunchaoced53ae2016-11-29 15:00:51 +0800908 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 if (width != height)
911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500912 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400913 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 }
915
Geoff Langaae65a42014-05-26 12:43:44 -0400916 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500918 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400919 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 }
921 }
922 break;
923
He Yunchaoced53ae2016-11-29 15:00:51 +0800924 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 {
Geoff Langaae65a42014-05-26 12:43:44 -0400926 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
927 static_cast<GLuint>(height) > caps.max3DTextureSize ||
928 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500930 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 }
933 }
934 break;
935
He Yunchaoced53ae2016-11-29 15:00:51 +0800936 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 {
Geoff Langaae65a42014-05-26 12:43:44 -0400938 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
939 static_cast<GLuint>(height) > caps.max2DTextureSize ||
940 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500942 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945 }
946 break;
947
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 default:
949 UNREACHABLE();
950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952
Geoff Lang691e58c2014-12-19 17:03:25 -0500953 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 if (!texture || texture->id() == 0)
955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959
Geoff Lang69cce582015-09-17 13:20:36 -0400960 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965
Geoff Langca271392017-04-05 12:30:00 -0400966 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400967 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500969 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400970 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 }
972
Geoff Langca271392017-04-05 12:30:00 -0400973 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500975 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400976 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400977 }
978
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400979 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
980 {
981 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
982 return false;
983 }
984
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985 return true;
986}
987
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500988bool ValidateES3TexStorage2DParameters(Context *context,
989 GLenum target,
990 GLsizei levels,
991 GLenum internalformat,
992 GLsizei width,
993 GLsizei height,
994 GLsizei depth)
995{
996 if (!ValidTexture2DTarget(context, target))
997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500998 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500999 return false;
1000 }
1001
1002 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1003 height, depth);
1004}
1005
1006bool ValidateES3TexStorage3DParameters(Context *context,
1007 GLenum target,
1008 GLsizei levels,
1009 GLenum internalformat,
1010 GLsizei width,
1011 GLsizei height,
1012 GLsizei depth)
1013{
1014 if (!ValidTexture3DTarget(context, target))
1015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001016 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001017 return false;
1018 }
1019
1020 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1021 height, depth);
1022}
1023
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001024bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1025{
Martin Radev1be913c2016-07-11 17:59:16 +03001026 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001028 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001029 return false;
1030 }
1031
1032 return ValidateBeginQueryBase(context, target, id);
1033}
1034
1035bool ValidateEndQuery(gl::Context *context, GLenum target)
1036{
Martin Radev1be913c2016-07-11 17:59:16 +03001037 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001039 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001040 return false;
1041 }
1042
1043 return ValidateEndQueryBase(context, target);
1044}
1045
1046bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1047{
Martin Radev1be913c2016-07-11 17:59:16 +03001048 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001050 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001051 return false;
1052 }
1053
Geoff Lang2186c382016-10-14 10:54:54 -04001054 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001055}
1056
1057bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1058{
Martin Radev1be913c2016-07-11 17:59:16 +03001059 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001061 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001062 return false;
1063 }
1064
Geoff Lang2186c382016-10-14 10:54:54 -04001065 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001066}
1067
He Yunchaoced53ae2016-11-29 15:00:51 +08001068bool ValidateFramebufferTextureLayer(Context *context,
1069 GLenum target,
1070 GLenum attachment,
1071 GLuint texture,
1072 GLint level,
1073 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001074{
Martin Radev1be913c2016-07-11 17:59:16 +03001075 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001077 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001079 }
1080
Jamie Madill55ec3b12014-07-03 10:38:57 -04001081 if (layer < 0)
1082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001083 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001085 }
1086
1087 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1088 {
1089 return false;
1090 }
1091
1092 const gl::Caps &caps = context->getCaps();
1093 if (texture != 0)
1094 {
1095 gl::Texture *tex = context->getTexture(texture);
1096 ASSERT(tex);
1097
1098 switch (tex->getTarget())
1099 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001101 {
1102 if (level > gl::log2(caps.max2DTextureSize))
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.maxArrayTextureLayers)
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 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001117 {
1118 if (level > gl::log2(caps.max3DTextureSize))
1119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001120 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001121 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001122 }
1123
1124 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001126 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001127 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001128 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001129 }
1130 break;
1131
He Yunchaoced53ae2016-11-29 15:00:51 +08001132 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001133 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001135 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001136
Jamie Madilla3944d42016-07-22 22:13:26 -04001137 const auto &format = tex->getFormat(tex->getTarget(), level);
1138 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001140 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001141 return false;
1142 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001143 }
1144
1145 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001146}
1147
He Yunchaoced53ae2016-11-29 15:00:51 +08001148bool ValidateInvalidateFramebuffer(Context *context,
1149 GLenum target,
1150 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001151 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001152{
Martin Radev1be913c2016-07-11 17:59:16 +03001153 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001154 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001156 return false;
1157 }
1158
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001159 bool defaultFramebuffer = false;
1160
1161 switch (target)
1162 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 case GL_DRAW_FRAMEBUFFER:
1164 case GL_FRAMEBUFFER:
1165 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1166 break;
1167 case GL_READ_FRAMEBUFFER:
1168 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1169 break;
1170 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
He Yunchaoced53ae2016-11-29 15:00:51 +08001175 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1176 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001177}
1178
Jamie Madillc29968b2016-01-20 11:17:23 -05001179bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001180{
Martin Radev1be913c2016-07-11 17:59:16 +03001181 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001183 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001184 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001185 }
1186
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001187 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001189 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001190 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001191 }
1192
1193 return true;
1194}
1195
Olli Etuaho71dfb362016-03-10 14:04:27 +02001196bool ValidateDrawRangeElements(Context *context,
1197 GLenum mode,
1198 GLuint start,
1199 GLuint end,
1200 GLsizei count,
1201 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001202 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001203{
Martin Radev1be913c2016-07-11 17:59:16 +03001204 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001205 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001207 return false;
1208 }
1209
1210 if (end < start)
1211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001212 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001213 return false;
1214 }
1215
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001216 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001217 {
1218 return false;
1219 }
1220
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001221 // Use the parameter buffer to retrieve and cache the index range.
1222 const auto &params = context->getParams<HasIndexRange>();
1223 const auto &indexRangeOpt = params.getIndexRange();
1224 if (!indexRangeOpt.valid())
1225 {
1226 // Unexpected error.
1227 return false;
1228 }
1229
1230 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001231 {
1232 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001234 return false;
1235 }
1236 return true;
1237}
1238
He Yunchaoced53ae2016-11-29 15:00:51 +08001239bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001240{
Martin Radev1be913c2016-07-11 17:59:16 +03001241 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001245 }
1246
Jamie Madill78f41802014-08-25 15:47:55 -04001247 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001248}
1249
Jamie Madillb885e572015-02-03 16:16:04 -05001250bool ValidateReadBuffer(Context *context, GLenum src)
1251{
Martin Radev1be913c2016-07-11 17:59:16 +03001252 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001255 return false;
1256 }
1257
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001258 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001259
1260 if (readFBO == nullptr)
1261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001262 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001263 return false;
1264 }
1265
1266 if (src == GL_NONE)
1267 {
1268 return true;
1269 }
1270
Olli Etuaho84c9f592016-03-09 14:37:25 +02001271 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001273 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001274 return false;
1275 }
1276
1277 if (readFBO->id() == 0)
1278 {
1279 if (src != GL_BACK)
1280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001281 context->handleError(
1282 InvalidOperation()
1283 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001284 return false;
1285 }
1286 }
1287 else
1288 {
1289 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1290
1291 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001293 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001294 return false;
1295 }
1296 }
1297
1298 return true;
1299}
1300
Jamie Madill86af3d22015-07-21 15:14:07 -04001301bool ValidateCompressedTexImage3D(Context *context,
1302 GLenum target,
1303 GLint level,
1304 GLenum internalformat,
1305 GLsizei width,
1306 GLsizei height,
1307 GLsizei depth,
1308 GLint border,
1309 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001310 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001311{
Martin Radev1be913c2016-07-11 17:59:16 +03001312 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001314 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001315 return false;
1316 }
1317
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001318 if (!ValidTextureTarget(context, target))
1319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001321 return false;
1322 }
1323
Jamie Madille2e406c2016-06-02 13:04:10 -04001324 // Validate image size
1325 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001328 return false;
1329 }
1330
Geoff Langca271392017-04-05 12:30:00 -04001331 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001332 if (!formatInfo.compressed)
1333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001334 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001335 return false;
1336 }
1337
Jamie Madill513558d2016-06-02 13:04:11 -04001338 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001339 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001340 if (blockSizeOrErr.isError())
1341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001343 return false;
1344 }
1345 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001347 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001348 return false;
1349 }
1350
1351 // 3D texture target validation
1352 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001354 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001355 return false;
1356 }
1357
1358 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001359 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001360 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1361 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001362 {
1363 return false;
1364 }
1365
1366 return true;
1367}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001368
Corentin Wallezb2931602017-04-11 15:58:57 -04001369bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1370 GLenum target,
1371 GLint level,
1372 GLenum internalformat,
1373 GLsizei width,
1374 GLsizei height,
1375 GLsizei depth,
1376 GLint border,
1377 GLsizei imageSize,
1378 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001379 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001380{
1381 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1382 {
1383 return false;
1384 }
1385
1386 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1387 depth, border, imageSize, data);
1388}
1389
Austin Kinrossbc781f32015-10-26 09:27:38 -07001390bool ValidateBindVertexArray(Context *context, GLuint array)
1391{
Martin Radev1be913c2016-07-11 17:59:16 +03001392 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001395 return false;
1396 }
1397
1398 return ValidateBindVertexArrayBase(context, array);
1399}
1400
Jamie Madilld7576732017-08-26 18:49:50 -04001401bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001402{
Martin Radev1be913c2016-07-11 17:59:16 +03001403 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001404 {
Jamie Madilld7576732017-08-26 18:49:50 -04001405 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001406 return false;
1407 }
1408
1409 return true;
1410}
Geoff Langc5629752015-12-07 16:29:04 -05001411
Jiajia Qin6eafb042016-12-27 17:04:07 +08001412static bool ValidateBindBufferCommon(Context *context,
1413 GLenum target,
1414 GLuint index,
1415 GLuint buffer,
1416 GLintptr offset,
1417 GLsizeiptr size)
1418{
1419 if (context->getClientMajorVersion() < 3)
1420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001422 return false;
1423 }
1424
1425 if (buffer != 0 && offset < 0)
1426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001428 return false;
1429 }
1430
1431 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1432 !context->isBufferGenerated(buffer))
1433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001435 return false;
1436 }
1437
1438 const Caps &caps = context->getCaps();
1439 switch (target)
1440 {
1441 case GL_TRANSFORM_FEEDBACK_BUFFER:
1442 {
1443 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidValue() << "index is greater than or equal to the "
1446 "number of TRANSFORM_FEEDBACK_BUFFER "
1447 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001448 return false;
1449 }
1450 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001453 return false;
1454 }
1455
1456 TransformFeedback *curTransformFeedback =
1457 context->getGLState().getCurrentTransformFeedback();
1458 if (curTransformFeedback && curTransformFeedback->isActive())
1459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001460 context->handleError(InvalidOperation()
1461 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1462 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001463 return false;
1464 }
1465 break;
1466 }
1467 case GL_UNIFORM_BUFFER:
1468 {
1469 if (index >= caps.maxUniformBufferBindings)
1470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001471 context->handleError(InvalidValue() << "index is greater than or equal to the "
1472 "number of UNIFORM_BUFFER indexed "
1473 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001474 return false;
1475 }
1476
1477 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1478 {
1479 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001480 InvalidValue()
1481 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001482 return false;
1483 }
1484 break;
1485 }
1486 case GL_ATOMIC_COUNTER_BUFFER:
1487 {
1488 if (context->getClientVersion() < ES_3_1)
1489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001490 context->handleError(InvalidEnum()
1491 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001492 return false;
1493 }
1494 if (index >= caps.maxAtomicCounterBufferBindings)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(InvalidValue() << "index is greater than or equal to the "
1497 "number of ATOMIC_COUNTER_BUFFER "
1498 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001499 return false;
1500 }
1501 if (buffer != 0 && (offset % 4) != 0)
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 return false;
1505 }
1506 break;
1507 }
1508 case GL_SHADER_STORAGE_BUFFER:
1509 {
1510 if (context->getClientVersion() < ES_3_1)
1511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001512 context->handleError(InvalidEnum()
1513 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001514 return false;
1515 }
1516 if (index >= caps.maxShaderStorageBufferBindings)
1517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001518 context->handleError(InvalidValue() << "index is greater than or equal to the "
1519 "number of SHADER_STORAGE_BUFFER "
1520 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001521 return false;
1522 }
1523 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001525 context->handleError(InvalidValue() << "offset must be multiple of value of "
1526 "SHADER_STORAGE_BUFFER_OFFSET_"
1527 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001528 return false;
1529 }
1530 break;
1531 }
1532 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001534 return false;
1535 }
1536
1537 return true;
1538}
1539
1540bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1541{
1542 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1543}
1544
1545bool ValidateBindBufferRange(Context *context,
1546 GLenum target,
1547 GLuint index,
1548 GLuint buffer,
1549 GLintptr offset,
1550 GLsizeiptr size)
1551{
1552 if (buffer != 0 && size <= 0)
1553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001554 context->handleError(InvalidValue()
1555 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001556 return false;
1557 }
1558 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1559}
1560
Geoff Langc5629752015-12-07 16:29:04 -05001561bool ValidateProgramBinary(Context *context,
1562 GLuint program,
1563 GLenum binaryFormat,
1564 const void *binary,
1565 GLint length)
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 ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1574}
1575
1576bool ValidateGetProgramBinary(Context *context,
1577 GLuint program,
1578 GLsizei bufSize,
1579 GLsizei *length,
1580 GLenum *binaryFormat,
1581 void *binary)
1582{
Martin Radev1be913c2016-07-11 17:59:16 +03001583 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001585 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001586 return false;
1587 }
1588
1589 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1590}
1591
Olli Etuahof0fee072016-03-30 15:11:58 +03001592bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001593{
Martin Radev1be913c2016-07-11 17:59:16 +03001594 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001597 return false;
1598 }
1599
1600 if (GetValidProgram(context, program) == nullptr)
1601 {
1602 return false;
1603 }
1604
1605 switch (pname)
1606 {
1607 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001608 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);
Olli Etuahof0fee072016-03-30 15:11:58 +03001612 return false;
1613 }
Geoff Langc5629752015-12-07 16:29:04 -05001614 break;
1615
Yunchao He61afff12017-03-14 15:34:03 +08001616 case GL_PROGRAM_SEPARABLE:
1617 if (context->getClientVersion() < ES_3_1)
1618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001619 context->handleError(InvalidEnum()
1620 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001621 return false;
1622 }
1623
1624 if (value != GL_FALSE && value != GL_TRUE)
1625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001626 context->handleError(InvalidValue()
1627 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001628 return false;
1629 }
1630 break;
1631
Geoff Langc5629752015-12-07 16:29:04 -05001632 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidEnum()
1634 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001635 return false;
1636 }
1637
1638 return true;
1639}
Jamie Madillc29968b2016-01-20 11:17:23 -05001640
1641bool ValidateBlitFramebuffer(Context *context,
1642 GLint srcX0,
1643 GLint srcY0,
1644 GLint srcX1,
1645 GLint srcY1,
1646 GLint dstX0,
1647 GLint dstY0,
1648 GLint dstX1,
1649 GLint dstY1,
1650 GLbitfield mask,
1651 GLenum filter)
1652{
Martin Radev1be913c2016-07-11 17:59:16 +03001653 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001656 return false;
1657 }
1658
1659 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1660 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661}
Jamie Madillc29968b2016-01-20 11:17:23 -05001662
1663bool ValidateClearBufferiv(ValidationContext *context,
1664 GLenum buffer,
1665 GLint drawbuffer,
1666 const GLint *value)
1667{
1668 switch (buffer)
1669 {
1670 case GL_COLOR:
1671 if (drawbuffer < 0 ||
1672 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001674 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001675 return false;
1676 }
Geoff Lang76e65652017-03-27 14:58:02 -04001677 if (context->getExtensions().webglCompatibility)
1678 {
1679 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001680 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001681 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1682 {
1683 return false;
1684 }
1685 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001686 break;
1687
1688 case GL_STENCIL:
1689 if (drawbuffer != 0)
1690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001692 return false;
1693 }
1694 break;
1695
1696 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001697 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001698 return false;
1699 }
1700
1701 return ValidateClearBuffer(context);
1702}
1703
1704bool ValidateClearBufferuiv(ValidationContext *context,
1705 GLenum buffer,
1706 GLint drawbuffer,
1707 const GLuint *value)
1708{
1709 switch (buffer)
1710 {
1711 case GL_COLOR:
1712 if (drawbuffer < 0 ||
1713 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001716 return false;
1717 }
Geoff Lang76e65652017-03-27 14:58:02 -04001718 if (context->getExtensions().webglCompatibility)
1719 {
1720 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001721 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001722 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1723 {
1724 return false;
1725 }
1726 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001727 break;
1728
1729 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001731 return false;
1732 }
1733
1734 return ValidateClearBuffer(context);
1735}
1736
1737bool ValidateClearBufferfv(ValidationContext *context,
1738 GLenum buffer,
1739 GLint drawbuffer,
1740 const GLfloat *value)
1741{
1742 switch (buffer)
1743 {
1744 case GL_COLOR:
1745 if (drawbuffer < 0 ||
1746 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001749 return false;
1750 }
Geoff Lang76e65652017-03-27 14:58:02 -04001751 if (context->getExtensions().webglCompatibility)
1752 {
1753 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1754 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001755 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001756 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1757 {
1758 return false;
1759 }
1760 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 break;
1762
1763 case GL_DEPTH:
1764 if (drawbuffer != 0)
1765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001767 return false;
1768 }
1769 break;
1770
1771 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001772 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 return false;
1774 }
1775
1776 return ValidateClearBuffer(context);
1777}
1778
1779bool ValidateClearBufferfi(ValidationContext *context,
1780 GLenum buffer,
1781 GLint drawbuffer,
1782 GLfloat depth,
1783 GLint stencil)
1784{
1785 switch (buffer)
1786 {
1787 case GL_DEPTH_STENCIL:
1788 if (drawbuffer != 0)
1789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001790 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001791 return false;
1792 }
1793 break;
1794
1795 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001796 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001797 return false;
1798 }
1799
1800 return ValidateClearBuffer(context);
1801}
1802
1803bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1804{
Martin Radev1be913c2016-07-11 17:59:16 +03001805 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001808 return false;
1809 }
1810
1811 return ValidateDrawBuffersBase(context, n, bufs);
1812}
1813
1814bool ValidateCopyTexSubImage3D(Context *context,
1815 GLenum target,
1816 GLint level,
1817 GLint xoffset,
1818 GLint yoffset,
1819 GLint zoffset,
1820 GLint x,
1821 GLint y,
1822 GLsizei width,
1823 GLsizei height)
1824{
Martin Radev1be913c2016-07-11 17:59:16 +03001825 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001827 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 return false;
1829 }
1830
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001831 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1832 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001833}
1834
Jamie Madill73a84962016-02-12 09:27:23 -05001835bool ValidateTexImage3D(Context *context,
1836 GLenum target,
1837 GLint level,
1838 GLint internalformat,
1839 GLsizei width,
1840 GLsizei height,
1841 GLsizei depth,
1842 GLint border,
1843 GLenum format,
1844 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001845 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001846{
Martin Radev1be913c2016-07-11 17:59:16 +03001847 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001849 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001850 return false;
1851 }
1852
1853 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001854 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001855 pixels);
1856}
1857
Geoff Langc52f6f12016-10-14 10:18:00 -04001858bool ValidateTexImage3DRobustANGLE(Context *context,
1859 GLenum target,
1860 GLint level,
1861 GLint internalformat,
1862 GLsizei width,
1863 GLsizei height,
1864 GLsizei depth,
1865 GLint border,
1866 GLenum format,
1867 GLenum type,
1868 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001869 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001870{
1871 if (context->getClientMajorVersion() < 3)
1872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001873 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001874 return false;
1875 }
1876
1877 if (!ValidateRobustEntryPoint(context, bufSize))
1878 {
1879 return false;
1880 }
1881
1882 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1883 0, 0, width, height, depth, border, format, type,
1884 bufSize, pixels);
1885}
1886
Jamie Madill73a84962016-02-12 09:27:23 -05001887bool ValidateTexSubImage3D(Context *context,
1888 GLenum target,
1889 GLint level,
1890 GLint xoffset,
1891 GLint yoffset,
1892 GLint zoffset,
1893 GLsizei width,
1894 GLsizei height,
1895 GLsizei depth,
1896 GLenum format,
1897 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001898 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001899{
Martin Radev1be913c2016-07-11 17:59:16 +03001900 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001902 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001903 return false;
1904 }
1905
1906 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1907 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001908 -1, pixels);
1909}
1910
1911bool ValidateTexSubImage3DRobustANGLE(Context *context,
1912 GLenum target,
1913 GLint level,
1914 GLint xoffset,
1915 GLint yoffset,
1916 GLint zoffset,
1917 GLsizei width,
1918 GLsizei height,
1919 GLsizei depth,
1920 GLenum format,
1921 GLenum type,
1922 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001923 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001924{
1925 if (context->getClientMajorVersion() < 3)
1926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001927 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001928 return false;
1929 }
1930
1931 if (!ValidateRobustEntryPoint(context, bufSize))
1932 {
1933 return false;
1934 }
1935
1936 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1937 yoffset, zoffset, width, height, depth, 0, format, type,
1938 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001939}
1940
1941bool ValidateCompressedTexSubImage3D(Context *context,
1942 GLenum target,
1943 GLint level,
1944 GLint xoffset,
1945 GLint yoffset,
1946 GLint zoffset,
1947 GLsizei width,
1948 GLsizei height,
1949 GLsizei depth,
1950 GLenum format,
1951 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001952 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001953{
Martin Radev1be913c2016-07-11 17:59:16 +03001954 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001956 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001957 return false;
1958 }
1959
Geoff Langca271392017-04-05 12:30:00 -04001960 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001961 if (!formatInfo.compressed)
1962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001963 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001964 return false;
1965 }
1966
Jamie Madill513558d2016-06-02 13:04:11 -04001967 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001968 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001969 if (blockSizeOrErr.isError())
1970 {
1971 context->handleError(blockSizeOrErr.getError());
1972 return false;
1973 }
1974 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001976 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001977 return false;
1978 }
1979
1980 if (!data)
1981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001982 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001983 return false;
1984 }
1985
1986 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001987 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001988}
Corentin Wallezb2931602017-04-11 15:58:57 -04001989bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1990 GLenum target,
1991 GLint level,
1992 GLint xoffset,
1993 GLint yoffset,
1994 GLint zoffset,
1995 GLsizei width,
1996 GLsizei height,
1997 GLsizei depth,
1998 GLenum format,
1999 GLsizei imageSize,
2000 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002001 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002002{
2003 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2004 {
2005 return false;
2006 }
2007
2008 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2009 height, depth, format, imageSize, data);
2010}
Jamie Madill73a84962016-02-12 09:27:23 -05002011
Olli Etuaho41997e72016-03-10 13:38:39 +02002012bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2013{
2014 return ValidateGenOrDeleteES3(context, n);
2015}
2016
2017bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2018{
2019 return ValidateGenOrDeleteES3(context, n);
2020}
2021
2022bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2023{
2024 return ValidateGenOrDeleteCountES3(context, count);
2025}
2026
2027bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2028{
2029 return ValidateGenOrDeleteCountES3(context, count);
2030}
2031
2032bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2033{
2034 return ValidateGenOrDeleteES3(context, n);
2035}
2036
2037bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2038{
2039 if (!ValidateGenOrDeleteES3(context, n))
2040 {
2041 return false;
2042 }
2043 for (GLint i = 0; i < n; ++i)
2044 {
2045 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2046 if (transformFeedback != nullptr && transformFeedback->isActive())
2047 {
2048 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002049 context->handleError(InvalidOperation()
2050 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002051 return false;
2052 }
2053 }
2054 return true;
2055}
2056
2057bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2058{
2059 return ValidateGenOrDeleteES3(context, n);
2060}
2061
2062bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2063{
2064 return ValidateGenOrDeleteES3(context, n);
2065}
2066
2067bool ValidateGenOrDeleteES3(Context *context, GLint n)
2068{
Martin Radev1be913c2016-07-11 17:59:16 +03002069 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002071 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002072 return false;
2073 }
2074 return ValidateGenOrDelete(context, n);
2075}
2076
2077bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2078{
Martin Radev1be913c2016-07-11 17:59:16 +03002079 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002080 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho41997e72016-03-10 13:38:39 +02002082 return false;
2083 }
2084 if (count < 0)
2085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002086 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02002087 return false;
2088 }
2089 return true;
2090}
2091
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002092bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2093{
Martin Radev1be913c2016-07-11 17:59:16 +03002094 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002095 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002097 return false;
2098 }
2099 switch (primitiveMode)
2100 {
2101 case GL_TRIANGLES:
2102 case GL_LINES:
2103 case GL_POINTS:
2104 break;
2105
2106 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002107 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002108 return false;
2109 }
2110
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002111 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002112 ASSERT(transformFeedback != nullptr);
2113
2114 if (transformFeedback->isActive())
2115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002116 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002117 return false;
2118 }
Geoff Lang79f71042017-08-14 16:43:43 -04002119
2120 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2121 {
2122 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2123 if (buffer.get() && buffer->isMapped())
2124 {
2125 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2126 return false;
2127 }
2128 }
2129
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002130 return true;
2131}
2132
Jamie Madill876429b2017-04-20 15:46:24 -04002133bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002134{
Geoff Lang496c02d2016-10-20 11:38:11 -07002135 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2136}
2137
2138bool ValidateGetBufferPointervRobustANGLE(Context *context,
2139 GLenum target,
2140 GLenum pname,
2141 GLsizei bufSize,
2142 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002143 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002144{
2145 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002146 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002147 return false;
2148 }
2149
Geoff Lang496c02d2016-10-20 11:38:11 -07002150 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2151 {
2152 return false;
2153 }
2154
2155 if (!ValidateRobustBufferSize(context, bufSize, *length))
2156 {
2157 return false;
2158 }
2159
2160 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002161}
2162
2163bool ValidateUnmapBuffer(Context *context, GLenum target)
2164{
Martin Radev1be913c2016-07-11 17:59:16 +03002165 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002167 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002168 return false;
2169 }
2170
2171 return ValidateUnmapBufferBase(context, target);
2172}
2173
2174bool ValidateMapBufferRange(Context *context,
2175 GLenum target,
2176 GLintptr offset,
2177 GLsizeiptr length,
2178 GLbitfield access)
2179{
Martin Radev1be913c2016-07-11 17:59:16 +03002180 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002181 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002183 return false;
2184 }
2185
2186 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2187}
2188
2189bool ValidateFlushMappedBufferRange(Context *context,
2190 GLenum target,
2191 GLintptr offset,
2192 GLsizeiptr length)
2193{
Martin Radev1be913c2016-07-11 17:59:16 +03002194 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002195 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002197 return false;
2198 }
2199
2200 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2201}
2202
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002203bool ValidateIndexedStateQuery(ValidationContext *context,
2204 GLenum pname,
2205 GLuint index,
2206 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002207{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002208 if (length)
2209 {
2210 *length = 0;
2211 }
2212
Martin Radev66fb8202016-07-28 11:45:20 +03002213 GLenum nativeType;
2214 unsigned int numParams;
2215 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002217 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002218 return false;
2219 }
2220
2221 const Caps &caps = context->getCaps();
2222 switch (pname)
2223 {
2224 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2225 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2226 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2227 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002229 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002230 return false;
2231 }
2232 break;
2233
2234 case GL_UNIFORM_BUFFER_START:
2235 case GL_UNIFORM_BUFFER_SIZE:
2236 case GL_UNIFORM_BUFFER_BINDING:
2237 if (index >= caps.maxUniformBufferBindings)
2238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002239 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002240 return false;
2241 }
2242 break;
Shao80957d92017-02-20 21:25:59 +08002243
Martin Radev66fb8202016-07-28 11:45:20 +03002244 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2245 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2246 if (index >= 3u)
2247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002248 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002249 return false;
2250 }
2251 break;
Shao80957d92017-02-20 21:25:59 +08002252
Jiajia Qin6eafb042016-12-27 17:04:07 +08002253 case GL_ATOMIC_COUNTER_BUFFER_START:
2254 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2255 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2256 if (context->getClientVersion() < ES_3_1)
2257 {
2258 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002259 InvalidEnum()
2260 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002261 return false;
2262 }
2263 if (index >= caps.maxAtomicCounterBufferBindings)
2264 {
2265 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002266 InvalidValue()
2267 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002268 return false;
2269 }
2270 break;
Shao80957d92017-02-20 21:25:59 +08002271
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002272 case GL_SHADER_STORAGE_BUFFER_START:
2273 case GL_SHADER_STORAGE_BUFFER_SIZE:
2274 case GL_SHADER_STORAGE_BUFFER_BINDING:
2275 if (context->getClientVersion() < ES_3_1)
2276 {
2277 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002278 InvalidEnum()
2279 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002280 return false;
2281 }
2282 if (index >= caps.maxShaderStorageBufferBindings)
2283 {
2284 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002285 InvalidValue()
2286 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002287 return false;
2288 }
2289 break;
2290
Shao80957d92017-02-20 21:25:59 +08002291 case GL_VERTEX_BINDING_BUFFER:
2292 case GL_VERTEX_BINDING_DIVISOR:
2293 case GL_VERTEX_BINDING_OFFSET:
2294 case GL_VERTEX_BINDING_STRIDE:
2295 if (context->getClientVersion() < ES_3_1)
2296 {
2297 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002298 InvalidEnum()
2299 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002300 return false;
2301 }
2302 if (index >= caps.maxVertexAttribBindings)
2303 {
2304 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002305 InvalidValue()
2306 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002307 return false;
2308 }
2309 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002310 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002311 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002312 return false;
2313 }
2314
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002315 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002316 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002317 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002318 }
2319
2320 return true;
2321}
2322
2323bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2324{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002325 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002326 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002327 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002328 return false;
2329 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002330 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002331}
2332
Geoff Langcf255ea2016-10-20 11:39:09 -07002333bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2334 GLenum target,
2335 GLuint index,
2336 GLsizei bufSize,
2337 GLsizei *length,
2338 GLint *data)
2339{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002340 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002341 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002343 return false;
2344 }
2345
2346 if (!ValidateRobustEntryPoint(context, bufSize))
2347 {
2348 return false;
2349 }
2350
2351 if (!ValidateIndexedStateQuery(context, target, index, length))
2352 {
2353 return false;
2354 }
2355
2356 if (!ValidateRobustBufferSize(context, bufSize, *length))
2357 {
2358 return false;
2359 }
2360
2361 return true;
2362}
2363
Martin Radev66fb8202016-07-28 11:45:20 +03002364bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2365{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002366 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002367 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002369 return false;
2370 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002371 return ValidateIndexedStateQuery(context, target, index, nullptr);
2372}
2373
2374bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2375 GLenum target,
2376 GLuint index,
2377 GLsizei bufSize,
2378 GLsizei *length,
2379 GLint64 *data)
2380{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002381 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002382 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002383 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002384 return false;
2385 }
2386
2387 if (!ValidateRobustEntryPoint(context, bufSize))
2388 {
2389 return false;
2390 }
2391
2392 if (!ValidateIndexedStateQuery(context, target, index, length))
2393 {
2394 return false;
2395 }
2396
2397 if (!ValidateRobustBufferSize(context, bufSize, *length))
2398 {
2399 return false;
2400 }
2401
2402 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002403}
2404
Jamie Madillb0817d12016-11-01 15:48:31 -04002405bool ValidateCopyBufferSubData(ValidationContext *context,
2406 GLenum readTarget,
2407 GLenum writeTarget,
2408 GLintptr readOffset,
2409 GLintptr writeOffset,
2410 GLsizeiptr size)
2411{
2412 if (context->getClientMajorVersion() < 3)
2413 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002415 return false;
2416 }
2417
2418 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002420 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002421 return false;
2422 }
2423
2424 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2425 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2426
2427 if (!readBuffer || !writeBuffer)
2428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002429 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002430 return false;
2431 }
2432
2433 // Verify that readBuffer and writeBuffer are not currently mapped
2434 if (readBuffer->isMapped() || writeBuffer->isMapped())
2435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002436 context->handleError(InvalidOperation()
2437 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002438 return false;
2439 }
2440
Jamie Madilld2f0c742016-11-02 10:34:41 -04002441 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2442 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2443 CheckedNumeric<GLintptr> checkedSize(size);
2444
2445 auto checkedReadSum = checkedReadOffset + checkedSize;
2446 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2447
2448 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2449 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2450 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002452 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002453 return false;
2454 }
2455
Jamie Madilld2f0c742016-11-02 10:34:41 -04002456 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002458 context->handleError(InvalidValue()
2459 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002460 return false;
2461 }
2462
Jamie Madilld2f0c742016-11-02 10:34:41 -04002463 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2464 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002466 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002467 return false;
2468 }
2469
2470 if (readBuffer == writeBuffer)
2471 {
2472 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2473 if (!checkedOffsetDiff.IsValid())
2474 {
2475 // This shold not be possible.
2476 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002477 context->handleError(InvalidValue()
2478 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002479 return false;
2480 }
2481
2482 if (checkedOffsetDiff.ValueOrDie() < size)
2483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002484 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002485 return false;
2486 }
2487 }
2488
Jamie Madillb0817d12016-11-01 15:48:31 -04002489 return true;
2490}
2491
Geoff Langc339c4e2016-11-29 10:37:36 -05002492bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2493{
2494 if (context->getClientMajorVersion() < 3)
2495 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002497 return false;
2498 }
2499
2500 switch (name)
2501 {
2502 case GL_EXTENSIONS:
2503 if (index >= context->getExtensionStringCount())
2504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002505 context->handleError(InvalidValue()
2506 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002507 return false;
2508 }
2509 break;
2510
2511 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2512 if (!context->getExtensions().requestExtension)
2513 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002515 return false;
2516 }
2517 if (index >= context->getRequestableExtensionStringCount())
2518 {
2519 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002520 InvalidValue()
2521 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002522 return false;
2523 }
2524 break;
2525
2526 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002527 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002528 return false;
2529 }
2530
2531 return true;
2532}
2533
Jamie Madille8fb6402017-02-14 17:56:40 -05002534bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2535 GLenum target,
2536 GLsizei samples,
2537 GLenum internalformat,
2538 GLsizei width,
2539 GLsizei height)
2540{
2541 if (context->getClientMajorVersion() < 3)
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 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2548 height))
2549 {
2550 return false;
2551 }
2552
2553 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2554 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002555 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002556 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2557 samples > 0)
2558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002560 return false;
2561 }
2562
2563 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2564 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2565 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2566 {
2567 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 InvalidOperation()
2569 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002570 return false;
2571 }
2572
2573 return true;
2574}
2575
Geoff Langaa086d62017-03-23 16:47:21 -04002576bool ValidateVertexAttribIPointer(ValidationContext *context,
2577 GLuint index,
2578 GLint size,
2579 GLenum type,
2580 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002581 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002582{
2583 if (context->getClientMajorVersion() < 3)
2584 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002585 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002586 return false;
2587 }
2588
Shao80957d92017-02-20 21:25:59 +08002589 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002590 {
Geoff Langaa086d62017-03-23 16:47:21 -04002591 return false;
2592 }
2593
Geoff Langaa086d62017-03-23 16:47:21 -04002594 if (stride < 0)
2595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002596 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002597 return false;
2598 }
2599
Shao80957d92017-02-20 21:25:59 +08002600 const Caps &caps = context->getCaps();
2601 if (context->getClientVersion() >= ES_3_1)
2602 {
2603 if (stride > caps.maxVertexAttribStride)
2604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002605 context->handleError(InvalidValue()
2606 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002607 return false;
2608 }
2609
2610 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2611 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2612 // validation should be inherited.
2613 if (index >= caps.maxVertexAttribBindings)
2614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002615 context->handleError(InvalidValue()
2616 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002617 return false;
2618 }
2619 }
2620
Geoff Langaa086d62017-03-23 16:47:21 -04002621 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2622 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2623 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2624 // and the pointer argument is not NULL.
2625 if (context->getGLState().getVertexArrayId() != 0 &&
2626 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002628 context
2629 ->handleError(InvalidOperation()
2630 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002631 return false;
2632 }
2633
Geoff Lang2d62ab72017-03-23 16:54:40 -04002634 if (context->getExtensions().webglCompatibility)
2635 {
2636 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2637 {
2638 return false;
2639 }
2640 }
2641
Geoff Langaa086d62017-03-23 16:47:21 -04002642 return true;
2643}
2644
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002645bool ValidateGetSynciv(Context *context,
2646 GLsync sync,
2647 GLenum pname,
2648 GLsizei bufSize,
2649 GLsizei *length,
2650 GLint *values)
2651{
2652 if (context->getClientMajorVersion() < 3)
2653 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002655 return false;
2656 }
2657
2658 if (bufSize < 0)
2659 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002660 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002661 return false;
2662 }
2663
2664 FenceSync *fenceSync = context->getFenceSync(sync);
2665 if (!fenceSync)
2666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002667 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002668 return false;
2669 }
2670
2671 switch (pname)
2672 {
2673 case GL_OBJECT_TYPE:
2674 case GL_SYNC_CONDITION:
2675 case GL_SYNC_FLAGS:
2676 case GL_SYNC_STATUS:
2677 break;
2678
2679 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002681 return false;
2682 }
2683
2684 return true;
2685}
2686
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002687bool ValidateDrawElementsInstanced(ValidationContext *context,
2688 GLenum mode,
2689 GLsizei count,
2690 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002691 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002692 GLsizei instanceCount)
2693{
2694 if (context->getClientMajorVersion() < 3)
2695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002696 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002697 return false;
2698 }
2699
2700 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2701}
2702
Martin Radev137032d2017-07-13 10:11:12 +03002703bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2704 GLenum target,
2705 GLenum attachment,
2706 GLuint texture,
2707 GLint level,
2708 GLint baseViewIndex,
2709 GLsizei numViews)
2710{
2711
2712 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2713 numViews))
2714 {
2715 return false;
2716 }
2717
2718 if (baseViewIndex < 0)
2719 {
2720 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2721 return false;
2722 }
2723
2724 if (texture != 0)
2725 {
2726 Texture *tex = context->getTexture(texture);
2727 ASSERT(tex);
2728
2729 switch (tex->getTarget())
2730 {
2731 case GL_TEXTURE_2D_ARRAY:
2732 {
2733 const Caps &caps = context->getCaps();
2734 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2735 {
2736 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2737 "greater than "
2738 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2739 return false;
2740 }
2741 }
2742 break;
2743 default:
2744 context->handleError(InvalidOperation()
2745 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2746 return false;
2747 }
2748
2749 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2750 {
2751 return false;
2752 }
2753 }
2754
2755 return true;
2756}
2757
2758bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2759 GLenum target,
2760 GLenum attachment,
2761 GLuint texture,
2762 GLint level,
2763 GLsizei numViews,
2764 const GLint *viewportOffsets)
2765{
2766 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2767 numViews))
2768 {
2769 return false;
2770 }
2771
2772 const GLsizei numViewportOffsetValues = numViews * 2;
2773 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2774 {
2775 if (viewportOffsets[i] < 0)
2776 {
2777 context->handleError(InvalidValue()
2778 << "viewportOffsets cannot contain negative values.");
2779 return false;
2780 }
2781 }
2782
2783 if (texture != 0)
2784 {
2785 Texture *tex = context->getTexture(texture);
2786 ASSERT(tex);
2787
2788 switch (tex->getTarget())
2789 {
2790 case GL_TEXTURE_2D:
2791 break;
2792 default:
2793 context->handleError(InvalidOperation()
2794 << "Texture's target must be GL_TEXTURE_2D.");
2795 return false;
2796 }
2797
2798 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2799 {
2800 return false;
2801 }
2802 }
2803
2804 return true;
2805}
2806
Jamie Madillff325f12017-08-26 15:06:05 -04002807bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2808{
2809 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2810}
2811
2812bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2813{
2814 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2815}
2816
2817bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2818{
2819 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2820}
2821
2822bool ValidateUniform4ui(Context *context,
2823 GLint location,
2824 GLuint v0,
2825 GLuint v1,
2826 GLuint v2,
2827 GLuint v3)
2828{
2829 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2830}
2831
2832bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2833{
2834 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2835}
2836
2837bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2838{
2839 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2840}
2841
2842bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2843{
2844 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2845}
2846
2847bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2848{
2849 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2850}
2851
Jamie Madillf0e04492017-08-26 15:28:42 -04002852bool ValidateIsQuery(Context *context, GLuint id)
2853{
2854 if (context->getClientMajorVersion() < 3)
2855 {
2856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2857 return false;
2858 }
2859
2860 return true;
2861}
2862
Jamie Madillc8c95812017-08-26 18:40:09 -04002863bool ValidateUniformMatrix2x3fv(Context *context,
2864 GLint location,
2865 GLsizei count,
2866 GLboolean transpose,
2867 const GLfloat *value)
2868{
2869 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2870}
2871
2872bool ValidateUniformMatrix3x2fv(Context *context,
2873 GLint location,
2874 GLsizei count,
2875 GLboolean transpose,
2876 const GLfloat *value)
2877{
2878 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2879}
2880
2881bool ValidateUniformMatrix2x4fv(Context *context,
2882 GLint location,
2883 GLsizei count,
2884 GLboolean transpose,
2885 const GLfloat *value)
2886{
2887 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2888}
2889
2890bool ValidateUniformMatrix4x2fv(Context *context,
2891 GLint location,
2892 GLsizei count,
2893 GLboolean transpose,
2894 const GLfloat *value)
2895{
2896 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2897}
2898
2899bool ValidateUniformMatrix3x4fv(Context *context,
2900 GLint location,
2901 GLsizei count,
2902 GLboolean transpose,
2903 const GLfloat *value)
2904{
2905 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2906}
2907
2908bool ValidateUniformMatrix4x3fv(Context *context,
2909 GLint location,
2910 GLsizei count,
2911 GLboolean transpose,
2912 const GLfloat *value)
2913{
2914 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2915}
2916
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002917bool ValidateEndTransformFeedback(Context *context)
2918{
2919 if (context->getClientMajorVersion() < 3)
2920 {
2921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2922 return false;
2923 }
2924
2925 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2926 ASSERT(transformFeedback != nullptr);
2927
2928 if (!transformFeedback->isActive())
2929 {
2930 context->handleError(InvalidOperation());
2931 return false;
2932 }
2933
2934 return true;
2935}
2936
2937bool ValidateTransformFeedbackVaryings(Context *context,
2938 GLuint program,
2939 GLsizei count,
2940 const GLchar *const *varyings,
2941 GLenum bufferMode)
2942{
2943 if (context->getClientMajorVersion() < 3)
2944 {
2945 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2946 return false;
2947 }
2948
2949 if (count < 0)
2950 {
2951 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2952 return false;
2953 }
2954
2955 switch (bufferMode)
2956 {
2957 case GL_INTERLEAVED_ATTRIBS:
2958 break;
2959 case GL_SEPARATE_ATTRIBS:
2960 {
2961 const Caps &caps = context->getCaps();
2962 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
2963 {
2964 context->handleError(InvalidValue());
2965 return false;
2966 }
2967 break;
2968 }
2969 default:
2970 context->handleError(InvalidEnum());
2971 return false;
2972 }
2973
2974 Program *programObject = GetValidProgram(context, program);
2975 if (!programObject)
2976 {
2977 return false;
2978 }
2979
2980 return true;
2981}
2982
2983bool ValidateGetTransformFeedbackVarying(Context *context,
2984 GLuint program,
2985 GLuint index,
2986 GLsizei bufSize,
2987 GLsizei *length,
2988 GLsizei *size,
2989 GLenum *type,
2990 GLchar *name)
2991{
2992 if (context->getClientMajorVersion() < 3)
2993 {
2994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2995 return false;
2996 }
2997
2998 if (bufSize < 0)
2999 {
3000 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3001 return false;
3002 }
3003
3004 Program *programObject = GetValidProgram(context, program);
3005 if (!programObject)
3006 {
3007 return false;
3008 }
3009
3010 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3011 {
3012 context->handleError(InvalidValue());
3013 return false;
3014 }
3015
3016 return true;
3017}
3018
3019bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3020{
3021 if (context->getClientMajorVersion() < 3)
3022 {
3023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3024 return false;
3025 }
3026
3027 switch (target)
3028 {
3029 case GL_TRANSFORM_FEEDBACK:
3030 {
3031 // Cannot bind a transform feedback object if the current one is started and not
3032 // paused (3.0.2 pg 85 section 2.14.1)
3033 TransformFeedback *curTransformFeedback =
3034 context->getGLState().getCurrentTransformFeedback();
3035 if (curTransformFeedback && curTransformFeedback->isActive() &&
3036 !curTransformFeedback->isPaused())
3037 {
3038 context->handleError(InvalidOperation());
3039 return false;
3040 }
3041
3042 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3043 // 2.14.1)
3044 if (!context->isTransformFeedbackGenerated(id))
3045 {
3046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3047 return false;
3048 }
3049 }
3050 break;
3051
3052 default:
3053 context->handleError(InvalidEnum());
3054 return false;
3055 }
3056
3057 return true;
3058}
3059
3060bool ValidateIsTransformFeedback(Context *context, GLuint id)
3061{
3062 if (context->getClientMajorVersion() < 3)
3063 {
3064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3065 return false;
3066 }
3067
3068 return true;
3069}
3070
3071bool ValidatePauseTransformFeedback(Context *context)
3072{
3073 if (context->getClientMajorVersion() < 3)
3074 {
3075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3076 return false;
3077 }
3078
3079 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3080 ASSERT(transformFeedback != nullptr);
3081
3082 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3083 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3084 {
3085 context->handleError(InvalidOperation());
3086 return false;
3087 }
3088
3089 return true;
3090}
3091
3092bool ValidateResumeTransformFeedback(Context *context)
3093{
3094 if (context->getClientMajorVersion() < 3)
3095 {
3096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3097 return false;
3098 }
3099
3100 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3101 ASSERT(transformFeedback != nullptr);
3102
3103 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3104 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3105 {
3106 context->handleError(InvalidOperation());
3107 return false;
3108 }
3109
3110 return true;
3111}
3112
Jamie Madill12e957f2017-08-26 21:42:26 -04003113bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3114{
3115 if (context->getClientMajorVersion() < 3)
3116 {
3117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3118 return false;
3119 }
3120
3121 return ValidateVertexAttribIndex(context, index);
3122}
3123
3124bool ValidateVertexAttribI4ui(Context *context,
3125 GLuint index,
3126 GLuint x,
3127 GLuint y,
3128 GLuint z,
3129 GLuint w)
3130{
3131 if (context->getClientMajorVersion() < 3)
3132 {
3133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3134 return false;
3135 }
3136
3137 return ValidateVertexAttribIndex(context, index);
3138}
3139
3140bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3141{
3142 if (context->getClientMajorVersion() < 3)
3143 {
3144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3145 return false;
3146 }
3147
3148 return ValidateVertexAttribIndex(context, index);
3149}
3150
3151bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3152{
3153 if (context->getClientMajorVersion() < 3)
3154 {
3155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3156 return false;
3157 }
3158
3159 return ValidateVertexAttribIndex(context, index);
3160}
3161
3162bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3163{
3164 if (context->getClientMajorVersion() < 3)
3165 {
3166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3167 return false;
3168 }
3169
3170 Program *programObject = GetValidProgram(context, program);
3171 if (!programObject)
3172 {
3173 return false;
3174 }
3175
3176 if (!programObject->isLinked())
3177 {
3178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3179 return false;
3180 }
3181
3182 return true;
3183}
3184
3185bool ValidateGetUniformIndices(Context *context,
3186 GLuint program,
3187 GLsizei uniformCount,
3188 const GLchar *const *uniformNames,
3189 GLuint *uniformIndices)
3190{
3191 if (context->getClientMajorVersion() < 3)
3192 {
3193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3194 return false;
3195 }
3196
3197 if (uniformCount < 0)
3198 {
3199 context->handleError(InvalidValue());
3200 return false;
3201 }
3202
3203 Program *programObject = GetValidProgram(context, program);
3204 if (!programObject)
3205 {
3206 return false;
3207 }
3208
3209 return true;
3210}
3211
3212bool ValidateGetActiveUniformsiv(Context *context,
3213 GLuint program,
3214 GLsizei uniformCount,
3215 const GLuint *uniformIndices,
3216 GLenum pname,
3217 GLint *params)
3218{
3219 if (context->getClientMajorVersion() < 3)
3220 {
3221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3222 return false;
3223 }
3224
3225 if (uniformCount < 0)
3226 {
3227 context->handleError(InvalidValue());
3228 return false;
3229 }
3230
3231 Program *programObject = GetValidProgram(context, program);
3232 if (!programObject)
3233 {
3234 return false;
3235 }
3236
3237 switch (pname)
3238 {
3239 case GL_UNIFORM_TYPE:
3240 case GL_UNIFORM_SIZE:
3241 case GL_UNIFORM_NAME_LENGTH:
3242 case GL_UNIFORM_BLOCK_INDEX:
3243 case GL_UNIFORM_OFFSET:
3244 case GL_UNIFORM_ARRAY_STRIDE:
3245 case GL_UNIFORM_MATRIX_STRIDE:
3246 case GL_UNIFORM_IS_ROW_MAJOR:
3247 break;
3248
3249 default:
3250 context->handleError(InvalidEnum());
3251 return false;
3252 }
3253
3254 if (uniformCount > programObject->getActiveUniformCount())
3255 {
3256 context->handleError(InvalidValue());
3257 return false;
3258 }
3259
3260 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3261 {
3262 const GLuint index = uniformIndices[uniformId];
3263
3264 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3265 {
3266 context->handleError(InvalidValue());
3267 return false;
3268 }
3269 }
3270
3271 return true;
3272}
3273
3274bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3275{
3276 if (context->getClientMajorVersion() < 3)
3277 {
3278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3279 return false;
3280 }
3281
3282 Program *programObject = GetValidProgram(context, program);
3283 if (!programObject)
3284 {
3285 return false;
3286 }
3287
3288 return true;
3289}
3290
3291bool ValidateGetActiveUniformBlockiv(Context *context,
3292 GLuint program,
3293 GLuint uniformBlockIndex,
3294 GLenum pname,
3295 GLint *params)
3296{
3297 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3298}
3299
3300bool ValidateGetActiveUniformBlockName(Context *context,
3301 GLuint program,
3302 GLuint uniformBlockIndex,
3303 GLsizei bufSize,
3304 GLsizei *length,
3305 GLchar *uniformBlockName)
3306{
3307 if (context->getClientMajorVersion() < 3)
3308 {
3309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3310 return false;
3311 }
3312
3313 Program *programObject = GetValidProgram(context, program);
3314 if (!programObject)
3315 {
3316 return false;
3317 }
3318
3319 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3320 {
3321 context->handleError(InvalidValue());
3322 return false;
3323 }
3324
3325 return true;
3326}
3327
3328bool ValidateUniformBlockBinding(Context *context,
3329 GLuint program,
3330 GLuint uniformBlockIndex,
3331 GLuint uniformBlockBinding)
3332{
3333 if (context->getClientMajorVersion() < 3)
3334 {
3335 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3336 return false;
3337 }
3338
3339 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3340 {
3341 context->handleError(InvalidValue());
3342 return false;
3343 }
3344
3345 Program *programObject = GetValidProgram(context, program);
3346 if (!programObject)
3347 {
3348 return false;
3349 }
3350
3351 // if never linked, there won't be any uniform blocks
3352 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3353 {
3354 context->handleError(InvalidValue());
3355 return false;
3356 }
3357
3358 return true;
3359}
3360
3361bool ValidateDrawArraysInstanced(Context *context,
3362 GLenum mode,
3363 GLint first,
3364 GLsizei count,
3365 GLsizei primcount)
3366{
3367 if (context->getClientMajorVersion() < 3)
3368 {
3369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3370 return false;
3371 }
3372
3373 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3374}
3375
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003376bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3377{
3378 if (context->getClientMajorVersion() < 3)
3379 {
3380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3381 return false;
3382 }
3383
3384 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3385 {
3386 context->handleError(InvalidEnum());
3387 return false;
3388 }
3389
3390 if (flags != 0)
3391 {
3392 context->handleError(InvalidValue());
3393 return false;
3394 }
3395
3396 return true;
3397}
3398
3399bool ValidateIsSync(Context *context, GLsync sync)
3400{
3401 if (context->getClientMajorVersion() < 3)
3402 {
3403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3404 return false;
3405 }
3406
3407 return true;
3408}
3409
3410bool ValidateDeleteSync(Context *context, GLsync sync)
3411{
3412 if (context->getClientMajorVersion() < 3)
3413 {
3414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3415 return false;
3416 }
3417
3418 if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
3419 {
3420 context->handleError(InvalidValue());
3421 return false;
3422 }
3423
3424 return true;
3425}
3426
3427bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3428{
3429 if (context->getClientMajorVersion() < 3)
3430 {
3431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3432 return false;
3433 }
3434
3435 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3436 {
3437 context->handleError(InvalidValue());
3438 return false;
3439 }
3440
3441 FenceSync *fenceSync = context->getFenceSync(sync);
3442
3443 if (!fenceSync)
3444 {
3445 context->handleError(InvalidValue());
3446 return false;
3447 }
3448
3449 return true;
3450}
3451
3452bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3453{
3454 if (context->getClientMajorVersion() < 3)
3455 {
3456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3457 return false;
3458 }
3459
3460 if (flags != 0)
3461 {
3462 context->handleError(InvalidValue());
3463 return false;
3464 }
3465
3466 if (timeout != GL_TIMEOUT_IGNORED)
3467 {
3468 context->handleError(InvalidValue());
3469 return false;
3470 }
3471
3472 FenceSync *fenceSync = context->getFenceSync(sync);
3473 if (!fenceSync)
3474 {
3475 context->handleError(InvalidValue());
3476 return false;
3477 }
3478
3479 return true;
3480}
3481
3482bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3483{
3484 if (context->getClientMajorVersion() < 3)
3485 {
3486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3487 return false;
3488 }
3489
3490 GLenum nativeType = GL_NONE;
3491 unsigned int numParams = 0;
3492 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3493 {
3494 return false;
3495 }
3496
3497 return true;
3498}
3499
Jamie Madillc29968b2016-01-20 11:17:23 -05003500} // namespace gl