blob: 4890d32eaea5fcb839394c4c653ab6784989fb18 [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 Madill3ef140a2017-08-26 23:11:21 -04001179bool ValidateInvalidateSubFramebuffer(Context *context,
1180 GLenum target,
1181 GLsizei numAttachments,
1182 const GLenum *attachments,
1183 GLint x,
1184 GLint y,
1185 GLsizei width,
1186 GLsizei height)
1187{
1188 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1189}
1190
Jamie Madillc29968b2016-01-20 11:17:23 -05001191bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001192{
Martin Radev1be913c2016-07-11 17:59:16 +03001193 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001195 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001196 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001197 }
1198
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001199 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001201 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001203 }
1204
1205 return true;
1206}
1207
Olli Etuaho71dfb362016-03-10 14:04:27 +02001208bool ValidateDrawRangeElements(Context *context,
1209 GLenum mode,
1210 GLuint start,
1211 GLuint end,
1212 GLsizei count,
1213 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001214 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001215{
Martin Radev1be913c2016-07-11 17:59:16 +03001216 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001217 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001219 return false;
1220 }
1221
1222 if (end < start)
1223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001224 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001225 return false;
1226 }
1227
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001228 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001229 {
1230 return false;
1231 }
1232
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001233 // Use the parameter buffer to retrieve and cache the index range.
1234 const auto &params = context->getParams<HasIndexRange>();
1235 const auto &indexRangeOpt = params.getIndexRange();
1236 if (!indexRangeOpt.valid())
1237 {
1238 // Unexpected error.
1239 return false;
1240 }
1241
1242 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001243 {
1244 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001245 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001246 return false;
1247 }
1248 return true;
1249}
1250
He Yunchaoced53ae2016-11-29 15:00:51 +08001251bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001252{
Martin Radev1be913c2016-07-11 17:59:16 +03001253 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001257 }
1258
Jamie Madill78f41802014-08-25 15:47:55 -04001259 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001260}
1261
Jamie Madillb885e572015-02-03 16:16:04 -05001262bool ValidateReadBuffer(Context *context, GLenum src)
1263{
Martin Radev1be913c2016-07-11 17:59:16 +03001264 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001266 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001267 return false;
1268 }
1269
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001270 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001271
1272 if (readFBO == nullptr)
1273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001275 return false;
1276 }
1277
1278 if (src == GL_NONE)
1279 {
1280 return true;
1281 }
1282
Olli Etuaho84c9f592016-03-09 14:37:25 +02001283 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001285 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001286 return false;
1287 }
1288
1289 if (readFBO->id() == 0)
1290 {
1291 if (src != GL_BACK)
1292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001293 context->handleError(
1294 InvalidOperation()
1295 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001296 return false;
1297 }
1298 }
1299 else
1300 {
1301 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1302
1303 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001306 return false;
1307 }
1308 }
1309
1310 return true;
1311}
1312
Jamie Madill86af3d22015-07-21 15:14:07 -04001313bool ValidateCompressedTexImage3D(Context *context,
1314 GLenum target,
1315 GLint level,
1316 GLenum internalformat,
1317 GLsizei width,
1318 GLsizei height,
1319 GLsizei depth,
1320 GLint border,
1321 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001322 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001323{
Martin Radev1be913c2016-07-11 17:59:16 +03001324 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001326 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001327 return false;
1328 }
1329
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001330 if (!ValidTextureTarget(context, target))
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001333 return false;
1334 }
1335
Jamie Madille2e406c2016-06-02 13:04:10 -04001336 // Validate image size
1337 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001340 return false;
1341 }
1342
Geoff Langca271392017-04-05 12:30:00 -04001343 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001344 if (!formatInfo.compressed)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001347 return false;
1348 }
1349
Jamie Madill513558d2016-06-02 13:04:11 -04001350 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001351 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001352 if (blockSizeOrErr.isError())
1353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001354 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001355 return false;
1356 }
1357 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001360 return false;
1361 }
1362
1363 // 3D texture target validation
1364 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001367 return false;
1368 }
1369
1370 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001371 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001372 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1373 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001374 {
1375 return false;
1376 }
1377
1378 return true;
1379}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001380
Corentin Wallezb2931602017-04-11 15:58:57 -04001381bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1382 GLenum target,
1383 GLint level,
1384 GLenum internalformat,
1385 GLsizei width,
1386 GLsizei height,
1387 GLsizei depth,
1388 GLint border,
1389 GLsizei imageSize,
1390 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001391 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001392{
1393 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1394 {
1395 return false;
1396 }
1397
1398 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1399 depth, border, imageSize, data);
1400}
1401
Austin Kinrossbc781f32015-10-26 09:27:38 -07001402bool ValidateBindVertexArray(Context *context, GLuint array)
1403{
Martin Radev1be913c2016-07-11 17:59:16 +03001404 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001407 return false;
1408 }
1409
1410 return ValidateBindVertexArrayBase(context, array);
1411}
1412
Jamie Madilld7576732017-08-26 18:49:50 -04001413bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001414{
Martin Radev1be913c2016-07-11 17:59:16 +03001415 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001416 {
Jamie Madilld7576732017-08-26 18:49:50 -04001417 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001418 return false;
1419 }
1420
1421 return true;
1422}
Geoff Langc5629752015-12-07 16:29:04 -05001423
Jiajia Qin6eafb042016-12-27 17:04:07 +08001424static bool ValidateBindBufferCommon(Context *context,
1425 GLenum target,
1426 GLuint index,
1427 GLuint buffer,
1428 GLintptr offset,
1429 GLsizeiptr size)
1430{
1431 if (context->getClientMajorVersion() < 3)
1432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001434 return false;
1435 }
1436
1437 if (buffer != 0 && offset < 0)
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001440 return false;
1441 }
1442
1443 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1444 !context->isBufferGenerated(buffer))
1445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001446 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001447 return false;
1448 }
1449
1450 const Caps &caps = context->getCaps();
1451 switch (target)
1452 {
1453 case GL_TRANSFORM_FEEDBACK_BUFFER:
1454 {
1455 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001457 context->handleError(InvalidValue() << "index is greater than or equal to the "
1458 "number of TRANSFORM_FEEDBACK_BUFFER "
1459 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001460 return false;
1461 }
1462 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001464 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001465 return false;
1466 }
1467
1468 TransformFeedback *curTransformFeedback =
1469 context->getGLState().getCurrentTransformFeedback();
1470 if (curTransformFeedback && curTransformFeedback->isActive())
1471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001472 context->handleError(InvalidOperation()
1473 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1474 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001475 return false;
1476 }
1477 break;
1478 }
1479 case GL_UNIFORM_BUFFER:
1480 {
1481 if (index >= caps.maxUniformBufferBindings)
1482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001483 context->handleError(InvalidValue() << "index is greater than or equal to the "
1484 "number of UNIFORM_BUFFER indexed "
1485 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001486 return false;
1487 }
1488
1489 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1490 {
1491 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001492 InvalidValue()
1493 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001494 return false;
1495 }
1496 break;
1497 }
1498 case GL_ATOMIC_COUNTER_BUFFER:
1499 {
1500 if (context->getClientVersion() < ES_3_1)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidEnum()
1503 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001504 return false;
1505 }
1506 if (index >= caps.maxAtomicCounterBufferBindings)
1507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001508 context->handleError(InvalidValue() << "index is greater than or equal to the "
1509 "number of ATOMIC_COUNTER_BUFFER "
1510 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001511 return false;
1512 }
1513 if (buffer != 0 && (offset % 4) != 0)
1514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001516 return false;
1517 }
1518 break;
1519 }
1520 case GL_SHADER_STORAGE_BUFFER:
1521 {
1522 if (context->getClientVersion() < ES_3_1)
1523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001524 context->handleError(InvalidEnum()
1525 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001526 return false;
1527 }
1528 if (index >= caps.maxShaderStorageBufferBindings)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidValue() << "index is greater than or equal to the "
1531 "number of SHADER_STORAGE_BUFFER "
1532 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001533 return false;
1534 }
1535 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001537 context->handleError(InvalidValue() << "offset must be multiple of value of "
1538 "SHADER_STORAGE_BUFFER_OFFSET_"
1539 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001540 return false;
1541 }
1542 break;
1543 }
1544 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001545 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001546 return false;
1547 }
1548
1549 return true;
1550}
1551
1552bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1553{
1554 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1555}
1556
1557bool ValidateBindBufferRange(Context *context,
1558 GLenum target,
1559 GLuint index,
1560 GLuint buffer,
1561 GLintptr offset,
1562 GLsizeiptr size)
1563{
1564 if (buffer != 0 && size <= 0)
1565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001566 context->handleError(InvalidValue()
1567 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001568 return false;
1569 }
1570 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1571}
1572
Geoff Langc5629752015-12-07 16:29:04 -05001573bool ValidateProgramBinary(Context *context,
1574 GLuint program,
1575 GLenum binaryFormat,
1576 const void *binary,
1577 GLint length)
1578{
Martin Radev1be913c2016-07-11 17:59:16 +03001579 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001581 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001582 return false;
1583 }
1584
1585 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1586}
1587
1588bool ValidateGetProgramBinary(Context *context,
1589 GLuint program,
1590 GLsizei bufSize,
1591 GLsizei *length,
1592 GLenum *binaryFormat,
1593 void *binary)
1594{
Martin Radev1be913c2016-07-11 17:59:16 +03001595 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001598 return false;
1599 }
1600
1601 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1602}
1603
Olli Etuahof0fee072016-03-30 15:11:58 +03001604bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001605{
Martin Radev1be913c2016-07-11 17:59:16 +03001606 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001607 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001609 return false;
1610 }
1611
1612 if (GetValidProgram(context, program) == nullptr)
1613 {
1614 return false;
1615 }
1616
1617 switch (pname)
1618 {
1619 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001620 if (value != GL_FALSE && value != GL_TRUE)
1621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001622 context->handleError(InvalidValue()
1623 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001624 return false;
1625 }
Geoff Langc5629752015-12-07 16:29:04 -05001626 break;
1627
Yunchao He61afff12017-03-14 15:34:03 +08001628 case GL_PROGRAM_SEPARABLE:
1629 if (context->getClientVersion() < ES_3_1)
1630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidEnum()
1632 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001633 return false;
1634 }
1635
1636 if (value != GL_FALSE && value != GL_TRUE)
1637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidValue()
1639 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001640 return false;
1641 }
1642 break;
1643
Geoff Langc5629752015-12-07 16:29:04 -05001644 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidEnum()
1646 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001647 return false;
1648 }
1649
1650 return true;
1651}
Jamie Madillc29968b2016-01-20 11:17:23 -05001652
1653bool ValidateBlitFramebuffer(Context *context,
1654 GLint srcX0,
1655 GLint srcY0,
1656 GLint srcX1,
1657 GLint srcY1,
1658 GLint dstX0,
1659 GLint dstY0,
1660 GLint dstX1,
1661 GLint dstY1,
1662 GLbitfield mask,
1663 GLenum filter)
1664{
Martin Radev1be913c2016-07-11 17:59:16 +03001665 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001667 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001668 return false;
1669 }
1670
1671 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1672 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673}
Jamie Madillc29968b2016-01-20 11:17:23 -05001674
1675bool ValidateClearBufferiv(ValidationContext *context,
1676 GLenum buffer,
1677 GLint drawbuffer,
1678 const GLint *value)
1679{
1680 switch (buffer)
1681 {
1682 case GL_COLOR:
1683 if (drawbuffer < 0 ||
1684 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001686 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001687 return false;
1688 }
Geoff Lang76e65652017-03-27 14:58:02 -04001689 if (context->getExtensions().webglCompatibility)
1690 {
1691 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001692 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001693 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1694 {
1695 return false;
1696 }
1697 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001698 break;
1699
1700 case GL_STENCIL:
1701 if (drawbuffer != 0)
1702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001703 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001704 return false;
1705 }
1706 break;
1707
1708 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001709 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001710 return false;
1711 }
1712
1713 return ValidateClearBuffer(context);
1714}
1715
1716bool ValidateClearBufferuiv(ValidationContext *context,
1717 GLenum buffer,
1718 GLint drawbuffer,
1719 const GLuint *value)
1720{
1721 switch (buffer)
1722 {
1723 case GL_COLOR:
1724 if (drawbuffer < 0 ||
1725 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001727 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001728 return false;
1729 }
Geoff Lang76e65652017-03-27 14:58:02 -04001730 if (context->getExtensions().webglCompatibility)
1731 {
1732 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001733 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001734 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1735 {
1736 return false;
1737 }
1738 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001739 break;
1740
1741 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001742 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 return false;
1744 }
1745
1746 return ValidateClearBuffer(context);
1747}
1748
1749bool ValidateClearBufferfv(ValidationContext *context,
1750 GLenum buffer,
1751 GLint drawbuffer,
1752 const GLfloat *value)
1753{
1754 switch (buffer)
1755 {
1756 case GL_COLOR:
1757 if (drawbuffer < 0 ||
1758 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001761 return false;
1762 }
Geoff Lang76e65652017-03-27 14:58:02 -04001763 if (context->getExtensions().webglCompatibility)
1764 {
1765 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1766 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001767 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001768 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1769 {
1770 return false;
1771 }
1772 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 break;
1774
1775 case GL_DEPTH:
1776 if (drawbuffer != 0)
1777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001778 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 return false;
1780 }
1781 break;
1782
1783 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001784 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 return false;
1786 }
1787
1788 return ValidateClearBuffer(context);
1789}
1790
1791bool ValidateClearBufferfi(ValidationContext *context,
1792 GLenum buffer,
1793 GLint drawbuffer,
1794 GLfloat depth,
1795 GLint stencil)
1796{
1797 switch (buffer)
1798 {
1799 case GL_DEPTH_STENCIL:
1800 if (drawbuffer != 0)
1801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001802 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001803 return false;
1804 }
1805 break;
1806
1807 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001809 return false;
1810 }
1811
1812 return ValidateClearBuffer(context);
1813}
1814
1815bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1816{
Martin Radev1be913c2016-07-11 17:59:16 +03001817 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001818 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001819 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001820 return false;
1821 }
1822
1823 return ValidateDrawBuffersBase(context, n, bufs);
1824}
1825
1826bool ValidateCopyTexSubImage3D(Context *context,
1827 GLenum target,
1828 GLint level,
1829 GLint xoffset,
1830 GLint yoffset,
1831 GLint zoffset,
1832 GLint x,
1833 GLint y,
1834 GLsizei width,
1835 GLsizei height)
1836{
Martin Radev1be913c2016-07-11 17:59:16 +03001837 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 return false;
1841 }
1842
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001843 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1844 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001845}
1846
Jamie Madill73a84962016-02-12 09:27:23 -05001847bool ValidateTexImage3D(Context *context,
1848 GLenum target,
1849 GLint level,
1850 GLint internalformat,
1851 GLsizei width,
1852 GLsizei height,
1853 GLsizei depth,
1854 GLint border,
1855 GLenum format,
1856 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001857 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001858{
Martin Radev1be913c2016-07-11 17:59:16 +03001859 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001861 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001862 return false;
1863 }
1864
1865 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001866 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001867 pixels);
1868}
1869
Geoff Langc52f6f12016-10-14 10:18:00 -04001870bool ValidateTexImage3DRobustANGLE(Context *context,
1871 GLenum target,
1872 GLint level,
1873 GLint internalformat,
1874 GLsizei width,
1875 GLsizei height,
1876 GLsizei depth,
1877 GLint border,
1878 GLenum format,
1879 GLenum type,
1880 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001881 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001882{
1883 if (context->getClientMajorVersion() < 3)
1884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001885 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001886 return false;
1887 }
1888
1889 if (!ValidateRobustEntryPoint(context, bufSize))
1890 {
1891 return false;
1892 }
1893
1894 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1895 0, 0, width, height, depth, border, format, type,
1896 bufSize, pixels);
1897}
1898
Jamie Madill73a84962016-02-12 09:27:23 -05001899bool ValidateTexSubImage3D(Context *context,
1900 GLenum target,
1901 GLint level,
1902 GLint xoffset,
1903 GLint yoffset,
1904 GLint zoffset,
1905 GLsizei width,
1906 GLsizei height,
1907 GLsizei depth,
1908 GLenum format,
1909 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001910 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001911{
Martin Radev1be913c2016-07-11 17:59:16 +03001912 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001914 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001915 return false;
1916 }
1917
1918 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1919 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001920 -1, pixels);
1921}
1922
1923bool ValidateTexSubImage3DRobustANGLE(Context *context,
1924 GLenum target,
1925 GLint level,
1926 GLint xoffset,
1927 GLint yoffset,
1928 GLint zoffset,
1929 GLsizei width,
1930 GLsizei height,
1931 GLsizei depth,
1932 GLenum format,
1933 GLenum type,
1934 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001935 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001936{
1937 if (context->getClientMajorVersion() < 3)
1938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001939 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001940 return false;
1941 }
1942
1943 if (!ValidateRobustEntryPoint(context, bufSize))
1944 {
1945 return false;
1946 }
1947
1948 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1949 yoffset, zoffset, width, height, depth, 0, format, type,
1950 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001951}
1952
1953bool ValidateCompressedTexSubImage3D(Context *context,
1954 GLenum target,
1955 GLint level,
1956 GLint xoffset,
1957 GLint yoffset,
1958 GLint zoffset,
1959 GLsizei width,
1960 GLsizei height,
1961 GLsizei depth,
1962 GLenum format,
1963 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001964 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001965{
Martin Radev1be913c2016-07-11 17:59:16 +03001966 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001968 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001969 return false;
1970 }
1971
Geoff Langca271392017-04-05 12:30:00 -04001972 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001973 if (!formatInfo.compressed)
1974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001976 return false;
1977 }
1978
Jamie Madill513558d2016-06-02 13:04:11 -04001979 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001980 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001981 if (blockSizeOrErr.isError())
1982 {
1983 context->handleError(blockSizeOrErr.getError());
1984 return false;
1985 }
1986 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001988 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001989 return false;
1990 }
1991
1992 if (!data)
1993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001994 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001995 return false;
1996 }
1997
1998 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001999 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05002000}
Corentin Wallezb2931602017-04-11 15:58:57 -04002001bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2002 GLenum target,
2003 GLint level,
2004 GLint xoffset,
2005 GLint yoffset,
2006 GLint zoffset,
2007 GLsizei width,
2008 GLsizei height,
2009 GLsizei depth,
2010 GLenum format,
2011 GLsizei imageSize,
2012 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002013 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002014{
2015 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2016 {
2017 return false;
2018 }
2019
2020 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2021 height, depth, format, imageSize, data);
2022}
Jamie Madill73a84962016-02-12 09:27:23 -05002023
Olli Etuaho41997e72016-03-10 13:38:39 +02002024bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2025{
2026 return ValidateGenOrDeleteES3(context, n);
2027}
2028
2029bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2030{
2031 return ValidateGenOrDeleteES3(context, n);
2032}
2033
2034bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2035{
2036 return ValidateGenOrDeleteCountES3(context, count);
2037}
2038
2039bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2040{
2041 return ValidateGenOrDeleteCountES3(context, count);
2042}
2043
2044bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2045{
2046 return ValidateGenOrDeleteES3(context, n);
2047}
2048
2049bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2050{
2051 if (!ValidateGenOrDeleteES3(context, n))
2052 {
2053 return false;
2054 }
2055 for (GLint i = 0; i < n; ++i)
2056 {
2057 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2058 if (transformFeedback != nullptr && transformFeedback->isActive())
2059 {
2060 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002061 context->handleError(InvalidOperation()
2062 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002063 return false;
2064 }
2065 }
2066 return true;
2067}
2068
2069bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2070{
2071 return ValidateGenOrDeleteES3(context, n);
2072}
2073
2074bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2075{
2076 return ValidateGenOrDeleteES3(context, n);
2077}
2078
2079bool ValidateGenOrDeleteES3(Context *context, GLint n)
2080{
Martin Radev1be913c2016-07-11 17:59:16 +03002081 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002083 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002084 return false;
2085 }
2086 return ValidateGenOrDelete(context, n);
2087}
2088
2089bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2090{
Martin Radev1be913c2016-07-11 17:59:16 +03002091 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002092 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho41997e72016-03-10 13:38:39 +02002094 return false;
2095 }
2096 if (count < 0)
2097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002098 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02002099 return false;
2100 }
2101 return true;
2102}
2103
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002104bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2105{
Martin Radev1be913c2016-07-11 17:59:16 +03002106 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002107 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002109 return false;
2110 }
2111 switch (primitiveMode)
2112 {
2113 case GL_TRIANGLES:
2114 case GL_LINES:
2115 case GL_POINTS:
2116 break;
2117
2118 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002119 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002120 return false;
2121 }
2122
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002123 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002124 ASSERT(transformFeedback != nullptr);
2125
2126 if (transformFeedback->isActive())
2127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002128 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002129 return false;
2130 }
Geoff Lang79f71042017-08-14 16:43:43 -04002131
2132 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2133 {
2134 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2135 if (buffer.get() && buffer->isMapped())
2136 {
2137 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2138 return false;
2139 }
2140 }
2141
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002142 return true;
2143}
2144
Jamie Madill876429b2017-04-20 15:46:24 -04002145bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002146{
Geoff Lang496c02d2016-10-20 11:38:11 -07002147 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2148}
2149
2150bool ValidateGetBufferPointervRobustANGLE(Context *context,
2151 GLenum target,
2152 GLenum pname,
2153 GLsizei bufSize,
2154 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002155 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002156{
2157 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002158 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002159 return false;
2160 }
2161
Geoff Lang496c02d2016-10-20 11:38:11 -07002162 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2163 {
2164 return false;
2165 }
2166
2167 if (!ValidateRobustBufferSize(context, bufSize, *length))
2168 {
2169 return false;
2170 }
2171
2172 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002173}
2174
2175bool ValidateUnmapBuffer(Context *context, GLenum target)
2176{
Martin Radev1be913c2016-07-11 17:59:16 +03002177 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002180 return false;
2181 }
2182
2183 return ValidateUnmapBufferBase(context, target);
2184}
2185
2186bool ValidateMapBufferRange(Context *context,
2187 GLenum target,
2188 GLintptr offset,
2189 GLsizeiptr length,
2190 GLbitfield access)
2191{
Martin Radev1be913c2016-07-11 17:59:16 +03002192 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002195 return false;
2196 }
2197
2198 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2199}
2200
2201bool ValidateFlushMappedBufferRange(Context *context,
2202 GLenum target,
2203 GLintptr offset,
2204 GLsizeiptr length)
2205{
Martin Radev1be913c2016-07-11 17:59:16 +03002206 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002209 return false;
2210 }
2211
2212 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2213}
2214
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002215bool ValidateIndexedStateQuery(ValidationContext *context,
2216 GLenum pname,
2217 GLuint index,
2218 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002219{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002220 if (length)
2221 {
2222 *length = 0;
2223 }
2224
Martin Radev66fb8202016-07-28 11:45:20 +03002225 GLenum nativeType;
2226 unsigned int numParams;
2227 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002229 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002230 return false;
2231 }
2232
2233 const Caps &caps = context->getCaps();
2234 switch (pname)
2235 {
2236 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2237 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2238 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2239 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002241 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002242 return false;
2243 }
2244 break;
2245
2246 case GL_UNIFORM_BUFFER_START:
2247 case GL_UNIFORM_BUFFER_SIZE:
2248 case GL_UNIFORM_BUFFER_BINDING:
2249 if (index >= caps.maxUniformBufferBindings)
2250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002251 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002252 return false;
2253 }
2254 break;
Shao80957d92017-02-20 21:25:59 +08002255
Martin Radev66fb8202016-07-28 11:45:20 +03002256 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2257 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2258 if (index >= 3u)
2259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002260 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002261 return false;
2262 }
2263 break;
Shao80957d92017-02-20 21:25:59 +08002264
Jiajia Qin6eafb042016-12-27 17:04:07 +08002265 case GL_ATOMIC_COUNTER_BUFFER_START:
2266 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2267 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2268 if (context->getClientVersion() < ES_3_1)
2269 {
2270 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 InvalidEnum()
2272 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002273 return false;
2274 }
2275 if (index >= caps.maxAtomicCounterBufferBindings)
2276 {
2277 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002278 InvalidValue()
2279 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002280 return false;
2281 }
2282 break;
Shao80957d92017-02-20 21:25:59 +08002283
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002284 case GL_SHADER_STORAGE_BUFFER_START:
2285 case GL_SHADER_STORAGE_BUFFER_SIZE:
2286 case GL_SHADER_STORAGE_BUFFER_BINDING:
2287 if (context->getClientVersion() < ES_3_1)
2288 {
2289 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002290 InvalidEnum()
2291 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002292 return false;
2293 }
2294 if (index >= caps.maxShaderStorageBufferBindings)
2295 {
2296 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 InvalidValue()
2298 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002299 return false;
2300 }
2301 break;
2302
Shao80957d92017-02-20 21:25:59 +08002303 case GL_VERTEX_BINDING_BUFFER:
2304 case GL_VERTEX_BINDING_DIVISOR:
2305 case GL_VERTEX_BINDING_OFFSET:
2306 case GL_VERTEX_BINDING_STRIDE:
2307 if (context->getClientVersion() < ES_3_1)
2308 {
2309 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002310 InvalidEnum()
2311 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002312 return false;
2313 }
2314 if (index >= caps.maxVertexAttribBindings)
2315 {
2316 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002317 InvalidValue()
2318 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002319 return false;
2320 }
2321 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002322 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002324 return false;
2325 }
2326
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002327 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002328 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002329 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002330 }
2331
2332 return true;
2333}
2334
2335bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2336{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002337 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002338 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002340 return false;
2341 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002342 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002343}
2344
Geoff Langcf255ea2016-10-20 11:39:09 -07002345bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2346 GLenum target,
2347 GLuint index,
2348 GLsizei bufSize,
2349 GLsizei *length,
2350 GLint *data)
2351{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002352 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002353 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002354 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002355 return false;
2356 }
2357
2358 if (!ValidateRobustEntryPoint(context, bufSize))
2359 {
2360 return false;
2361 }
2362
2363 if (!ValidateIndexedStateQuery(context, target, index, length))
2364 {
2365 return false;
2366 }
2367
2368 if (!ValidateRobustBufferSize(context, bufSize, *length))
2369 {
2370 return false;
2371 }
2372
2373 return true;
2374}
2375
Martin Radev66fb8202016-07-28 11:45:20 +03002376bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2377{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002378 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002379 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002381 return false;
2382 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002383 return ValidateIndexedStateQuery(context, target, index, nullptr);
2384}
2385
2386bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2387 GLenum target,
2388 GLuint index,
2389 GLsizei bufSize,
2390 GLsizei *length,
2391 GLint64 *data)
2392{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002393 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002394 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002395 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002396 return false;
2397 }
2398
2399 if (!ValidateRobustEntryPoint(context, bufSize))
2400 {
2401 return false;
2402 }
2403
2404 if (!ValidateIndexedStateQuery(context, target, index, length))
2405 {
2406 return false;
2407 }
2408
2409 if (!ValidateRobustBufferSize(context, bufSize, *length))
2410 {
2411 return false;
2412 }
2413
2414 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002415}
2416
Jamie Madillb0817d12016-11-01 15:48:31 -04002417bool ValidateCopyBufferSubData(ValidationContext *context,
2418 GLenum readTarget,
2419 GLenum writeTarget,
2420 GLintptr readOffset,
2421 GLintptr writeOffset,
2422 GLsizeiptr size)
2423{
2424 if (context->getClientMajorVersion() < 3)
2425 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002427 return false;
2428 }
2429
2430 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002432 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002433 return false;
2434 }
2435
2436 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2437 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2438
2439 if (!readBuffer || !writeBuffer)
2440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002441 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002442 return false;
2443 }
2444
2445 // Verify that readBuffer and writeBuffer are not currently mapped
2446 if (readBuffer->isMapped() || writeBuffer->isMapped())
2447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002448 context->handleError(InvalidOperation()
2449 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002450 return false;
2451 }
2452
Jamie Madilld2f0c742016-11-02 10:34:41 -04002453 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2454 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2455 CheckedNumeric<GLintptr> checkedSize(size);
2456
2457 auto checkedReadSum = checkedReadOffset + checkedSize;
2458 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2459
2460 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2461 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2462 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002464 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002465 return false;
2466 }
2467
Jamie Madilld2f0c742016-11-02 10:34:41 -04002468 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002470 context->handleError(InvalidValue()
2471 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002472 return false;
2473 }
2474
Jamie Madilld2f0c742016-11-02 10:34:41 -04002475 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2476 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002478 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002479 return false;
2480 }
2481
2482 if (readBuffer == writeBuffer)
2483 {
2484 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2485 if (!checkedOffsetDiff.IsValid())
2486 {
2487 // This shold not be possible.
2488 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002489 context->handleError(InvalidValue()
2490 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002491 return false;
2492 }
2493
2494 if (checkedOffsetDiff.ValueOrDie() < size)
2495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002496 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002497 return false;
2498 }
2499 }
2500
Jamie Madillb0817d12016-11-01 15:48:31 -04002501 return true;
2502}
2503
Geoff Langc339c4e2016-11-29 10:37:36 -05002504bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2505{
2506 if (context->getClientMajorVersion() < 3)
2507 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002509 return false;
2510 }
2511
2512 switch (name)
2513 {
2514 case GL_EXTENSIONS:
2515 if (index >= context->getExtensionStringCount())
2516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002517 context->handleError(InvalidValue()
2518 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002519 return false;
2520 }
2521 break;
2522
2523 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2524 if (!context->getExtensions().requestExtension)
2525 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002527 return false;
2528 }
2529 if (index >= context->getRequestableExtensionStringCount())
2530 {
2531 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002532 InvalidValue()
2533 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002534 return false;
2535 }
2536 break;
2537
2538 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002539 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002540 return false;
2541 }
2542
2543 return true;
2544}
2545
Jamie Madille8fb6402017-02-14 17:56:40 -05002546bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2547 GLenum target,
2548 GLsizei samples,
2549 GLenum internalformat,
2550 GLsizei width,
2551 GLsizei height)
2552{
2553 if (context->getClientMajorVersion() < 3)
2554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002555 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002556 return false;
2557 }
2558
2559 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2560 height))
2561 {
2562 return false;
2563 }
2564
2565 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2566 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002567 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002568 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2569 samples > 0)
2570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002571 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002572 return false;
2573 }
2574
2575 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2576 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2577 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2578 {
2579 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002580 InvalidOperation()
2581 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002582 return false;
2583 }
2584
2585 return true;
2586}
2587
Geoff Langaa086d62017-03-23 16:47:21 -04002588bool ValidateVertexAttribIPointer(ValidationContext *context,
2589 GLuint index,
2590 GLint size,
2591 GLenum type,
2592 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002593 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002594{
2595 if (context->getClientMajorVersion() < 3)
2596 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002598 return false;
2599 }
2600
Shao80957d92017-02-20 21:25:59 +08002601 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002602 {
Geoff Langaa086d62017-03-23 16:47:21 -04002603 return false;
2604 }
2605
Geoff Langaa086d62017-03-23 16:47:21 -04002606 if (stride < 0)
2607 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002608 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002609 return false;
2610 }
2611
Shao80957d92017-02-20 21:25:59 +08002612 const Caps &caps = context->getCaps();
2613 if (context->getClientVersion() >= ES_3_1)
2614 {
2615 if (stride > caps.maxVertexAttribStride)
2616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002617 context->handleError(InvalidValue()
2618 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002619 return false;
2620 }
2621
2622 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2623 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2624 // validation should be inherited.
2625 if (index >= caps.maxVertexAttribBindings)
2626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002627 context->handleError(InvalidValue()
2628 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002629 return false;
2630 }
2631 }
2632
Geoff Langaa086d62017-03-23 16:47:21 -04002633 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2634 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2635 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2636 // and the pointer argument is not NULL.
2637 if (context->getGLState().getVertexArrayId() != 0 &&
2638 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002640 context
2641 ->handleError(InvalidOperation()
2642 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002643 return false;
2644 }
2645
Geoff Lang2d62ab72017-03-23 16:54:40 -04002646 if (context->getExtensions().webglCompatibility)
2647 {
2648 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2649 {
2650 return false;
2651 }
2652 }
2653
Geoff Langaa086d62017-03-23 16:47:21 -04002654 return true;
2655}
2656
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002657bool ValidateGetSynciv(Context *context,
2658 GLsync sync,
2659 GLenum pname,
2660 GLsizei bufSize,
2661 GLsizei *length,
2662 GLint *values)
2663{
2664 if (context->getClientMajorVersion() < 3)
2665 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002667 return false;
2668 }
2669
2670 if (bufSize < 0)
2671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002672 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002673 return false;
2674 }
2675
2676 FenceSync *fenceSync = context->getFenceSync(sync);
2677 if (!fenceSync)
2678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002679 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002680 return false;
2681 }
2682
2683 switch (pname)
2684 {
2685 case GL_OBJECT_TYPE:
2686 case GL_SYNC_CONDITION:
2687 case GL_SYNC_FLAGS:
2688 case GL_SYNC_STATUS:
2689 break;
2690
2691 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002692 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002693 return false;
2694 }
2695
2696 return true;
2697}
2698
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002699bool ValidateDrawElementsInstanced(ValidationContext *context,
2700 GLenum mode,
2701 GLsizei count,
2702 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002703 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002704 GLsizei instanceCount)
2705{
2706 if (context->getClientMajorVersion() < 3)
2707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002708 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002709 return false;
2710 }
2711
2712 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2713}
2714
Martin Radev137032d2017-07-13 10:11:12 +03002715bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2716 GLenum target,
2717 GLenum attachment,
2718 GLuint texture,
2719 GLint level,
2720 GLint baseViewIndex,
2721 GLsizei numViews)
2722{
2723
2724 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2725 numViews))
2726 {
2727 return false;
2728 }
2729
2730 if (baseViewIndex < 0)
2731 {
2732 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2733 return false;
2734 }
2735
2736 if (texture != 0)
2737 {
2738 Texture *tex = context->getTexture(texture);
2739 ASSERT(tex);
2740
2741 switch (tex->getTarget())
2742 {
2743 case GL_TEXTURE_2D_ARRAY:
2744 {
2745 const Caps &caps = context->getCaps();
2746 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2747 {
2748 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2749 "greater than "
2750 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2751 return false;
2752 }
2753 }
2754 break;
2755 default:
2756 context->handleError(InvalidOperation()
2757 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2758 return false;
2759 }
2760
2761 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2762 {
2763 return false;
2764 }
2765 }
2766
2767 return true;
2768}
2769
2770bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2771 GLenum target,
2772 GLenum attachment,
2773 GLuint texture,
2774 GLint level,
2775 GLsizei numViews,
2776 const GLint *viewportOffsets)
2777{
2778 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2779 numViews))
2780 {
2781 return false;
2782 }
2783
2784 const GLsizei numViewportOffsetValues = numViews * 2;
2785 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2786 {
2787 if (viewportOffsets[i] < 0)
2788 {
2789 context->handleError(InvalidValue()
2790 << "viewportOffsets cannot contain negative values.");
2791 return false;
2792 }
2793 }
2794
2795 if (texture != 0)
2796 {
2797 Texture *tex = context->getTexture(texture);
2798 ASSERT(tex);
2799
2800 switch (tex->getTarget())
2801 {
2802 case GL_TEXTURE_2D:
2803 break;
2804 default:
2805 context->handleError(InvalidOperation()
2806 << "Texture's target must be GL_TEXTURE_2D.");
2807 return false;
2808 }
2809
2810 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2811 {
2812 return false;
2813 }
2814 }
2815
2816 return true;
2817}
2818
Jamie Madillff325f12017-08-26 15:06:05 -04002819bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2820{
2821 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2822}
2823
2824bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2825{
2826 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2827}
2828
2829bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2830{
2831 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2832}
2833
2834bool ValidateUniform4ui(Context *context,
2835 GLint location,
2836 GLuint v0,
2837 GLuint v1,
2838 GLuint v2,
2839 GLuint v3)
2840{
2841 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2842}
2843
2844bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2845{
2846 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2847}
2848
2849bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2850{
2851 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2852}
2853
2854bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2855{
2856 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2857}
2858
2859bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2860{
2861 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2862}
2863
Jamie Madillf0e04492017-08-26 15:28:42 -04002864bool ValidateIsQuery(Context *context, GLuint id)
2865{
2866 if (context->getClientMajorVersion() < 3)
2867 {
2868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2869 return false;
2870 }
2871
2872 return true;
2873}
2874
Jamie Madillc8c95812017-08-26 18:40:09 -04002875bool ValidateUniformMatrix2x3fv(Context *context,
2876 GLint location,
2877 GLsizei count,
2878 GLboolean transpose,
2879 const GLfloat *value)
2880{
2881 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2882}
2883
2884bool ValidateUniformMatrix3x2fv(Context *context,
2885 GLint location,
2886 GLsizei count,
2887 GLboolean transpose,
2888 const GLfloat *value)
2889{
2890 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2891}
2892
2893bool ValidateUniformMatrix2x4fv(Context *context,
2894 GLint location,
2895 GLsizei count,
2896 GLboolean transpose,
2897 const GLfloat *value)
2898{
2899 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2900}
2901
2902bool ValidateUniformMatrix4x2fv(Context *context,
2903 GLint location,
2904 GLsizei count,
2905 GLboolean transpose,
2906 const GLfloat *value)
2907{
2908 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2909}
2910
2911bool ValidateUniformMatrix3x4fv(Context *context,
2912 GLint location,
2913 GLsizei count,
2914 GLboolean transpose,
2915 const GLfloat *value)
2916{
2917 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2918}
2919
2920bool ValidateUniformMatrix4x3fv(Context *context,
2921 GLint location,
2922 GLsizei count,
2923 GLboolean transpose,
2924 const GLfloat *value)
2925{
2926 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2927}
2928
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04002929bool ValidateEndTransformFeedback(Context *context)
2930{
2931 if (context->getClientMajorVersion() < 3)
2932 {
2933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2934 return false;
2935 }
2936
2937 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2938 ASSERT(transformFeedback != nullptr);
2939
2940 if (!transformFeedback->isActive())
2941 {
2942 context->handleError(InvalidOperation());
2943 return false;
2944 }
2945
2946 return true;
2947}
2948
2949bool ValidateTransformFeedbackVaryings(Context *context,
2950 GLuint program,
2951 GLsizei count,
2952 const GLchar *const *varyings,
2953 GLenum bufferMode)
2954{
2955 if (context->getClientMajorVersion() < 3)
2956 {
2957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2958 return false;
2959 }
2960
2961 if (count < 0)
2962 {
2963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2964 return false;
2965 }
2966
2967 switch (bufferMode)
2968 {
2969 case GL_INTERLEAVED_ATTRIBS:
2970 break;
2971 case GL_SEPARATE_ATTRIBS:
2972 {
2973 const Caps &caps = context->getCaps();
2974 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
2975 {
2976 context->handleError(InvalidValue());
2977 return false;
2978 }
2979 break;
2980 }
2981 default:
2982 context->handleError(InvalidEnum());
2983 return false;
2984 }
2985
2986 Program *programObject = GetValidProgram(context, program);
2987 if (!programObject)
2988 {
2989 return false;
2990 }
2991
2992 return true;
2993}
2994
2995bool ValidateGetTransformFeedbackVarying(Context *context,
2996 GLuint program,
2997 GLuint index,
2998 GLsizei bufSize,
2999 GLsizei *length,
3000 GLsizei *size,
3001 GLenum *type,
3002 GLchar *name)
3003{
3004 if (context->getClientMajorVersion() < 3)
3005 {
3006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3007 return false;
3008 }
3009
3010 if (bufSize < 0)
3011 {
3012 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3013 return false;
3014 }
3015
3016 Program *programObject = GetValidProgram(context, program);
3017 if (!programObject)
3018 {
3019 return false;
3020 }
3021
3022 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3023 {
3024 context->handleError(InvalidValue());
3025 return false;
3026 }
3027
3028 return true;
3029}
3030
3031bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3032{
3033 if (context->getClientMajorVersion() < 3)
3034 {
3035 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3036 return false;
3037 }
3038
3039 switch (target)
3040 {
3041 case GL_TRANSFORM_FEEDBACK:
3042 {
3043 // Cannot bind a transform feedback object if the current one is started and not
3044 // paused (3.0.2 pg 85 section 2.14.1)
3045 TransformFeedback *curTransformFeedback =
3046 context->getGLState().getCurrentTransformFeedback();
3047 if (curTransformFeedback && curTransformFeedback->isActive() &&
3048 !curTransformFeedback->isPaused())
3049 {
3050 context->handleError(InvalidOperation());
3051 return false;
3052 }
3053
3054 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3055 // 2.14.1)
3056 if (!context->isTransformFeedbackGenerated(id))
3057 {
3058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3059 return false;
3060 }
3061 }
3062 break;
3063
3064 default:
3065 context->handleError(InvalidEnum());
3066 return false;
3067 }
3068
3069 return true;
3070}
3071
3072bool ValidateIsTransformFeedback(Context *context, GLuint id)
3073{
3074 if (context->getClientMajorVersion() < 3)
3075 {
3076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3077 return false;
3078 }
3079
3080 return true;
3081}
3082
3083bool ValidatePauseTransformFeedback(Context *context)
3084{
3085 if (context->getClientMajorVersion() < 3)
3086 {
3087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3088 return false;
3089 }
3090
3091 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3092 ASSERT(transformFeedback != nullptr);
3093
3094 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3095 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3096 {
3097 context->handleError(InvalidOperation());
3098 return false;
3099 }
3100
3101 return true;
3102}
3103
3104bool ValidateResumeTransformFeedback(Context *context)
3105{
3106 if (context->getClientMajorVersion() < 3)
3107 {
3108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3109 return false;
3110 }
3111
3112 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3113 ASSERT(transformFeedback != nullptr);
3114
3115 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3116 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3117 {
3118 context->handleError(InvalidOperation());
3119 return false;
3120 }
3121
3122 return true;
3123}
3124
Jamie Madill12e957f2017-08-26 21:42:26 -04003125bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3126{
3127 if (context->getClientMajorVersion() < 3)
3128 {
3129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3130 return false;
3131 }
3132
3133 return ValidateVertexAttribIndex(context, index);
3134}
3135
3136bool ValidateVertexAttribI4ui(Context *context,
3137 GLuint index,
3138 GLuint x,
3139 GLuint y,
3140 GLuint z,
3141 GLuint w)
3142{
3143 if (context->getClientMajorVersion() < 3)
3144 {
3145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3146 return false;
3147 }
3148
3149 return ValidateVertexAttribIndex(context, index);
3150}
3151
3152bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3153{
3154 if (context->getClientMajorVersion() < 3)
3155 {
3156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3157 return false;
3158 }
3159
3160 return ValidateVertexAttribIndex(context, index);
3161}
3162
3163bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3164{
3165 if (context->getClientMajorVersion() < 3)
3166 {
3167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3168 return false;
3169 }
3170
3171 return ValidateVertexAttribIndex(context, index);
3172}
3173
3174bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3175{
3176 if (context->getClientMajorVersion() < 3)
3177 {
3178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3179 return false;
3180 }
3181
3182 Program *programObject = GetValidProgram(context, program);
3183 if (!programObject)
3184 {
3185 return false;
3186 }
3187
3188 if (!programObject->isLinked())
3189 {
3190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3191 return false;
3192 }
3193
3194 return true;
3195}
3196
3197bool ValidateGetUniformIndices(Context *context,
3198 GLuint program,
3199 GLsizei uniformCount,
3200 const GLchar *const *uniformNames,
3201 GLuint *uniformIndices)
3202{
3203 if (context->getClientMajorVersion() < 3)
3204 {
3205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3206 return false;
3207 }
3208
3209 if (uniformCount < 0)
3210 {
3211 context->handleError(InvalidValue());
3212 return false;
3213 }
3214
3215 Program *programObject = GetValidProgram(context, program);
3216 if (!programObject)
3217 {
3218 return false;
3219 }
3220
3221 return true;
3222}
3223
3224bool ValidateGetActiveUniformsiv(Context *context,
3225 GLuint program,
3226 GLsizei uniformCount,
3227 const GLuint *uniformIndices,
3228 GLenum pname,
3229 GLint *params)
3230{
3231 if (context->getClientMajorVersion() < 3)
3232 {
3233 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3234 return false;
3235 }
3236
3237 if (uniformCount < 0)
3238 {
3239 context->handleError(InvalidValue());
3240 return false;
3241 }
3242
3243 Program *programObject = GetValidProgram(context, program);
3244 if (!programObject)
3245 {
3246 return false;
3247 }
3248
3249 switch (pname)
3250 {
3251 case GL_UNIFORM_TYPE:
3252 case GL_UNIFORM_SIZE:
3253 case GL_UNIFORM_NAME_LENGTH:
3254 case GL_UNIFORM_BLOCK_INDEX:
3255 case GL_UNIFORM_OFFSET:
3256 case GL_UNIFORM_ARRAY_STRIDE:
3257 case GL_UNIFORM_MATRIX_STRIDE:
3258 case GL_UNIFORM_IS_ROW_MAJOR:
3259 break;
3260
3261 default:
3262 context->handleError(InvalidEnum());
3263 return false;
3264 }
3265
3266 if (uniformCount > programObject->getActiveUniformCount())
3267 {
3268 context->handleError(InvalidValue());
3269 return false;
3270 }
3271
3272 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3273 {
3274 const GLuint index = uniformIndices[uniformId];
3275
3276 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3277 {
3278 context->handleError(InvalidValue());
3279 return false;
3280 }
3281 }
3282
3283 return true;
3284}
3285
3286bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3287{
3288 if (context->getClientMajorVersion() < 3)
3289 {
3290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3291 return false;
3292 }
3293
3294 Program *programObject = GetValidProgram(context, program);
3295 if (!programObject)
3296 {
3297 return false;
3298 }
3299
3300 return true;
3301}
3302
3303bool ValidateGetActiveUniformBlockiv(Context *context,
3304 GLuint program,
3305 GLuint uniformBlockIndex,
3306 GLenum pname,
3307 GLint *params)
3308{
3309 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3310}
3311
3312bool ValidateGetActiveUniformBlockName(Context *context,
3313 GLuint program,
3314 GLuint uniformBlockIndex,
3315 GLsizei bufSize,
3316 GLsizei *length,
3317 GLchar *uniformBlockName)
3318{
3319 if (context->getClientMajorVersion() < 3)
3320 {
3321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3322 return false;
3323 }
3324
3325 Program *programObject = GetValidProgram(context, program);
3326 if (!programObject)
3327 {
3328 return false;
3329 }
3330
3331 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3332 {
3333 context->handleError(InvalidValue());
3334 return false;
3335 }
3336
3337 return true;
3338}
3339
3340bool ValidateUniformBlockBinding(Context *context,
3341 GLuint program,
3342 GLuint uniformBlockIndex,
3343 GLuint uniformBlockBinding)
3344{
3345 if (context->getClientMajorVersion() < 3)
3346 {
3347 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3348 return false;
3349 }
3350
3351 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3352 {
3353 context->handleError(InvalidValue());
3354 return false;
3355 }
3356
3357 Program *programObject = GetValidProgram(context, program);
3358 if (!programObject)
3359 {
3360 return false;
3361 }
3362
3363 // if never linked, there won't be any uniform blocks
3364 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3365 {
3366 context->handleError(InvalidValue());
3367 return false;
3368 }
3369
3370 return true;
3371}
3372
3373bool ValidateDrawArraysInstanced(Context *context,
3374 GLenum mode,
3375 GLint first,
3376 GLsizei count,
3377 GLsizei primcount)
3378{
3379 if (context->getClientMajorVersion() < 3)
3380 {
3381 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3382 return false;
3383 }
3384
3385 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3386}
3387
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003388bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3389{
3390 if (context->getClientMajorVersion() < 3)
3391 {
3392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3393 return false;
3394 }
3395
3396 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3397 {
3398 context->handleError(InvalidEnum());
3399 return false;
3400 }
3401
3402 if (flags != 0)
3403 {
3404 context->handleError(InvalidValue());
3405 return false;
3406 }
3407
3408 return true;
3409}
3410
3411bool ValidateIsSync(Context *context, GLsync sync)
3412{
3413 if (context->getClientMajorVersion() < 3)
3414 {
3415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3416 return false;
3417 }
3418
3419 return true;
3420}
3421
3422bool ValidateDeleteSync(Context *context, GLsync sync)
3423{
3424 if (context->getClientMajorVersion() < 3)
3425 {
3426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3427 return false;
3428 }
3429
3430 if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
3431 {
3432 context->handleError(InvalidValue());
3433 return false;
3434 }
3435
3436 return true;
3437}
3438
3439bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3440{
3441 if (context->getClientMajorVersion() < 3)
3442 {
3443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3444 return false;
3445 }
3446
3447 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3448 {
3449 context->handleError(InvalidValue());
3450 return false;
3451 }
3452
3453 FenceSync *fenceSync = context->getFenceSync(sync);
3454
3455 if (!fenceSync)
3456 {
3457 context->handleError(InvalidValue());
3458 return false;
3459 }
3460
3461 return true;
3462}
3463
3464bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3465{
3466 if (context->getClientMajorVersion() < 3)
3467 {
3468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3469 return false;
3470 }
3471
3472 if (flags != 0)
3473 {
3474 context->handleError(InvalidValue());
3475 return false;
3476 }
3477
3478 if (timeout != GL_TIMEOUT_IGNORED)
3479 {
3480 context->handleError(InvalidValue());
3481 return false;
3482 }
3483
3484 FenceSync *fenceSync = context->getFenceSync(sync);
3485 if (!fenceSync)
3486 {
3487 context->handleError(InvalidValue());
3488 return false;
3489 }
3490
3491 return true;
3492}
3493
3494bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3495{
3496 if (context->getClientMajorVersion() < 3)
3497 {
3498 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3499 return false;
3500 }
3501
3502 GLenum nativeType = GL_NONE;
3503 unsigned int numParams = 0;
3504 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3505 {
3506 return false;
3507 }
3508
3509 return true;
3510}
3511
Jamie Madill3ef140a2017-08-26 23:11:21 -04003512bool ValidateIsSampler(Context *context, GLuint sampler)
3513{
3514 if (context->getClientMajorVersion() < 3)
3515 {
3516 context->handleError(InvalidOperation());
3517 return false;
3518 }
3519
3520 return true;
3521}
3522
3523bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3524{
3525 if (context->getClientMajorVersion() < 3)
3526 {
3527 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3528 return false;
3529 }
3530
3531 if (sampler != 0 && !context->isSampler(sampler))
3532 {
3533 context->handleError(InvalidOperation());
3534 return false;
3535 }
3536
3537 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3538 {
3539 context->handleError(InvalidValue());
3540 return false;
3541 }
3542
3543 return true;
3544}
3545
3546bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3547{
3548 if (context->getClientMajorVersion() < 3)
3549 {
3550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3551 return false;
3552 }
3553
3554 return ValidateVertexAttribIndex(context, index);
3555}
3556
3557bool ValidateTexStorage2D(Context *context,
3558 GLenum target,
3559 GLsizei levels,
3560 GLenum internalformat,
3561 GLsizei width,
3562 GLsizei height)
3563{
3564 if (context->getClientMajorVersion() < 3)
3565 {
3566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3567 return false;
3568 }
3569
3570 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3571 1))
3572 {
3573 return false;
3574 }
3575
3576 return true;
3577}
3578
3579bool ValidateTexStorage3D(Context *context,
3580 GLenum target,
3581 GLsizei levels,
3582 GLenum internalformat,
3583 GLsizei width,
3584 GLsizei height,
3585 GLsizei depth)
3586{
3587 if (context->getClientMajorVersion() < 3)
3588 {
3589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3590 return false;
3591 }
3592
3593 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3594 depth))
3595 {
3596 return false;
3597 }
3598
3599 return true;
3600}
3601
Jamie Madillc29968b2016-01-20 11:17:23 -05003602} // namespace gl