blob: 6cc18273dfcc501233db435f8e465258d16e8dc1 [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
85} // namespace
86
He Yunchaoced53ae2016-11-29 15:00:51 +080087static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -040088 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +080089 GLenum internalFormat,
90 GLenum format,
91 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040092{
Geoff Lang5d601382014-07-22 15:14:06 -040093
94 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -040095 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -040096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050097 context->handleError(InvalidEnum() << "Invalid format.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -040098 return false;
99 }
100
101 if (!ValidES3Type(type))
102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500103 context->handleError(InvalidEnum() << "Invalid type.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400104 return false;
105 }
106
107 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
108 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
109 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
110 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
111 if (!ValidES3InternalFormat(internalFormat))
112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500113 context->handleError(InvalidValue() << "Invalid internalFormat.");
Geoff Langb1196682014-07-23 13:47:29 -0400114 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400115 }
116
Geoff Langca271392017-04-05 12:30:00 -0400117 // From the ES 3.0 spec section 3.8.3:
118 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
119 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
120 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
121 // INVALID_OPERATION error.
122 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500124 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
125 "GL_DEPTH_STENCIL if target is "
126 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400127 return false;
128 }
129
Geoff Lang5d601382014-07-22 15:14:06 -0400130 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400131 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500133 context->handleError(InvalidOperation()
134 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400135 return false;
136 }
137
138 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
139 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500141 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400142 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400143 }
144
145 return true;
146}
147
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500148bool ValidateES3TexImageParametersBase(Context *context,
149 GLenum target,
150 GLint level,
151 GLenum internalformat,
152 bool isCompressed,
153 bool isSubImage,
154 GLint xoffset,
155 GLint yoffset,
156 GLint zoffset,
157 GLsizei width,
158 GLsizei height,
159 GLsizei depth,
160 GLint border,
161 GLenum format,
162 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400163 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400164 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400165{
166 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700167 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500169 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400171 }
172
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400173 // Verify zero border
174 if (border != 0)
175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400177 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400178 }
179
Jamie Madill6f38f822014-06-06 17:12:20 -0400180 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
181 std::numeric_limits<GLsizei>::max() - xoffset < width ||
182 std::numeric_limits<GLsizei>::max() - yoffset < height ||
183 std::numeric_limits<GLsizei>::max() - zoffset < depth)
184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400186 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400187 }
188
Geoff Langaae65a42014-05-26 12:43:44 -0400189 const gl::Caps &caps = context->getCaps();
190
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400191 switch (target)
192 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800193 case GL_TEXTURE_2D:
194 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
195 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500197 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800198 return false;
199 }
200 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400201
He Yunchaoced53ae2016-11-29 15:00:51 +0800202 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
203 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
204 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
205 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
206 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
207 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
208 if (!isSubImage && width != height)
209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500210 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800211 return false;
212 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400213
He Yunchaoced53ae2016-11-29 15:00:51 +0800214 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500216 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800217 return false;
218 }
219 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220
He Yunchaoced53ae2016-11-29 15:00:51 +0800221 case GL_TEXTURE_3D:
222 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
223 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
224 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500226 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800227 return false;
228 }
229 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230
He Yunchaoced53ae2016-11-29 15:00:51 +0800231 case GL_TEXTURE_2D_ARRAY:
232 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
233 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
234 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500236 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800237 return false;
238 }
239 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400240
He Yunchaoced53ae2016-11-29 15:00:51 +0800241 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500242 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800243 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400244 }
245
He Yunchaoced53ae2016-11-29 15:00:51 +0800246 gl::Texture *texture =
247 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400248 if (!texture)
249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500250 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400251 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400252 }
253
Geoff Lang69cce582015-09-17 13:20:36 -0400254 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500256 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400257 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258 }
259
260 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400261 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400262 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500263 if (isSubImage && actualInternalFormat == GL_NONE)
264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500265 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500266 return false;
267 }
268
Geoff Langc4e93662017-05-01 10:45:59 -0400269 const gl::InternalFormat &actualFormatInfo = isSubImage
270 ? *texture->getFormat(target, level).info
271 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400272 if (isCompressed)
273 {
tmartino7c102692015-10-02 16:43:40 -0400274 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500276 context->handleError(
277 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400278 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400279 }
280
Geoff Lang966c9402017-04-18 12:38:27 -0400281 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400282 {
Geoff Lang966c9402017-04-18 12:38:27 -0400283 if (!ValidCompressedSubImageSize(
284 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
285 texture->getWidth(target, level), texture->getHeight(target, level)))
286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500287 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400288 return false;
289 }
290
291 if (format != actualInternalFormat)
292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500293 context->handleError(InvalidOperation()
294 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400295 return false;
296 }
297 }
298 else
299 {
300 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500302 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400303 return false;
304 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305 }
306
Geoff Langeb66a6e2016-10-31 13:06:12 -0400307 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500309 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400310 return false;
311 }
312
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400313 if (target == GL_TEXTURE_3D)
314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500315 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400316 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400317 }
318 }
319 else
320 {
Geoff Langca271392017-04-05 12:30:00 -0400321 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 {
Geoff Lang5d601382014-07-22 15:14:06 -0400323 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 }
326
327 // Validate sub image parameters
328 if (isSubImage)
329 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500330 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500332 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400334 }
335
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500338 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400339 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 }
341
342 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
343 std::numeric_limits<GLsizei>::max() - yoffset < height ||
344 std::numeric_limits<GLsizei>::max() - zoffset < depth)
345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500346 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400347 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348 }
349
Geoff Langa9be0dc2014-12-17 12:34:40 -0500350 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
351 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
352 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500354 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400355 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 }
357 }
358
Geoff Langdbcced82017-06-06 15:55:54 -0400359 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
360 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
361 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400362 {
363 return false;
364 }
365
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400366 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700367 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400368 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400369 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800370 // ...data is not evenly divisible into the number of bytes needed to store in memory a
371 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400372 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400373 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400374 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400375 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400376 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
377
Geoff Langff5b2d52016-09-07 11:32:23 -0400378 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500380 context->handleError(InvalidOperation()
381 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400382 return false;
383 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400384 }
385
Jamie Madill7a5f7382014-03-05 15:01:24 -0500386 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700387 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500389 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400390 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500391 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400392 }
393
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400394 return true;
395}
396
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500397bool ValidateES3TexImage2DParameters(Context *context,
398 GLenum target,
399 GLint level,
400 GLenum internalformat,
401 bool isCompressed,
402 bool isSubImage,
403 GLint xoffset,
404 GLint yoffset,
405 GLint zoffset,
406 GLsizei width,
407 GLsizei height,
408 GLsizei depth,
409 GLint border,
410 GLenum format,
411 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400412 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400413 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500414{
415 if (!ValidTexture2DDestinationTarget(context, target))
416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500418 return false;
419 }
420
421 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
422 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400423 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500424}
425
426bool ValidateES3TexImage3DParameters(Context *context,
427 GLenum target,
428 GLint level,
429 GLenum internalformat,
430 bool isCompressed,
431 bool isSubImage,
432 GLint xoffset,
433 GLint yoffset,
434 GLint zoffset,
435 GLsizei width,
436 GLsizei height,
437 GLsizei depth,
438 GLint border,
439 GLenum format,
440 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400441 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400442 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500443{
444 if (!ValidTexture3DDestinationTarget(context, target))
445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500446 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500447 return false;
448 }
449
450 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
451 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400452 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500453}
454
Geoff Lang5d601382014-07-22 15:14:06 -0400455struct EffectiveInternalFormatInfo
456{
Jamie Madill76648fe2016-10-05 17:01:41 -0400457 GLenum effectiveFormat;
458 GLenum destFormat;
459 GLuint minRedBits;
460 GLuint maxRedBits;
461 GLuint minGreenBits;
462 GLuint maxGreenBits;
463 GLuint minBlueBits;
464 GLuint maxBlueBits;
465 GLuint minAlphaBits;
466 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400467};
468
Jamie Madill76648fe2016-10-05 17:01:41 -0400469static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
470 GLenum targetFormat,
471 const EffectiveInternalFormatInfo *list,
472 size_t size,
473 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400474{
Jamie Madill76648fe2016-10-05 17:01:41 -0400475 for (size_t curFormat = 0; curFormat < size; ++curFormat)
476 {
477 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
478 if ((formatInfo.destFormat == targetFormat) &&
479 (formatInfo.minRedBits <= srcFormat.redBits &&
480 formatInfo.maxRedBits >= srcFormat.redBits) &&
481 (formatInfo.minGreenBits <= srcFormat.greenBits &&
482 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
483 (formatInfo.minBlueBits <= srcFormat.blueBits &&
484 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
485 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
486 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
487 {
488 *outEffectiveFormat = formatInfo.effectiveFormat;
489 return true;
490 }
491 }
Geoff Lang5d601382014-07-22 15:14:06 -0400492
Jamie Madill76648fe2016-10-05 17:01:41 -0400493 *outEffectiveFormat = GL_NONE;
494 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400495}
496
Jamie Madill76648fe2016-10-05 17:01:41 -0400497bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
498 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400499{
Jamie Madill76648fe2016-10-05 17:01:41 -0400500 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
501 // Effective internal format coresponding to destination internal format and linear source
502 // buffer component sizes.
503 // | Source channel min/max sizes |
504 // Effective Internal Format | N/A | R | G | B | A |
505 // clang-format off
506 constexpr EffectiveInternalFormatInfo list[] = {
507 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
508 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
509 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
510 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
511 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
512 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
513 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
514 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
515 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
516 };
517 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400518
Jamie Madill76648fe2016-10-05 17:01:41 -0400519 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
520}
Geoff Lang5d601382014-07-22 15:14:06 -0400521
Jamie Madill76648fe2016-10-05 17:01:41 -0400522bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
523 const InternalFormat &destFormat,
524 GLenum *outEffectiveFormat)
525{
526 constexpr GLuint umax = UINT_MAX;
527
528 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
529 // Effective internal format coresponding to destination internal format andlinear source buffer
530 // component sizes.
531 // | Source channel min/max sizes |
532 // Effective Internal Format | Dest Format | R | G | B | A |
533 // clang-format off
534 constexpr EffectiveInternalFormatInfo list[] = {
535 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
536 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
537 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
538 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
539 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
540 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
541 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
542 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
543 };
544 // clang-format on
545
546 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
547 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400548}
549
He Yunchaoced53ae2016-11-29 15:00:51 +0800550static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
551 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400552 GLenum *outEffectiveFormat)
553{
Geoff Langca271392017-04-05 12:30:00 -0400554 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400555 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400556 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400557 }
558 else
559 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400560 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400561 }
Geoff Lang5d601382014-07-22 15:14:06 -0400562}
563
Corentin Wallez76287682016-04-25 09:23:38 -0400564static bool EqualOrFirstZero(GLuint first, GLuint second)
565{
566 return first == 0 || first == second;
567}
568
Geoff Langca271392017-04-05 12:30:00 -0400569static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
570 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400571 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400572{
Jamie Madill21b786b2016-11-01 17:41:31 -0400573 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400574 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400575 return false;
576 }
Geoff Lang5d601382014-07-22 15:14:06 -0400577
Jamie Madill21b786b2016-11-01 17:41:31 -0400578 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
579 // must both be signed, unsigned, or fixed point and both source and destinations
580 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
581 // conversion between fixed and floating point.
582
583 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
584 (framebufferFormatInfo.colorEncoding == GL_SRGB))
585 {
586 return false;
587 }
588
589 if (((textureFormatInfo.componentType == GL_INT) !=
590 (framebufferFormatInfo.componentType == GL_INT)) ||
591 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
592 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
593 {
594 return false;
595 }
596
597 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
598 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
599 textureFormatInfo.componentType == GL_FLOAT) &&
600 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
601 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
602 framebufferFormatInfo.componentType == GL_FLOAT))
603 {
604 return false;
605 }
606
607 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
608 // The effective internal format of the source buffer is determined with the following rules
609 // applied in order:
610 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
611 // format then the effective internal format is the source buffer's sized internal format.
612 // * If the source buffer is a texture that was created with an unsized base internal format,
613 // then the effective internal format is the source image array's effective internal
614 // format, as specified by table 3.12, which is determined from the <format> and <type>
615 // that were used when the source image array was specified by TexImage*.
616 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
617 // where Destination Internal Format matches internalformat and where the [source channel
618 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
619 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
620 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800621 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400622 if (readBufferHandle != 0)
623 {
624 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
625 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400626 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400627 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400628 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400629 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400630 else
Geoff Lang5d601382014-07-22 15:14:06 -0400631 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400632 // Renderbuffers cannot be created with an unsized internal format, so this must be an
633 // unsized-format texture. We can use the same table we use when creating textures to
634 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400635 sourceEffectiveFormat =
636 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400637 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400638 }
639 else
640 {
641 // The effective internal format must be derived from the source framebuffer's channel
642 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
643 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400644 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400645 GLenum effectiveFormat;
646 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
647 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400648 {
Geoff Langca271392017-04-05 12:30:00 -0400649 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400650 }
651 else
652 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400653 return false;
654 }
655 }
656 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
657 {
658 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400659 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400660 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
661 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
662 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
663 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
664 {
Geoff Langca271392017-04-05 12:30:00 -0400665 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400666 }
667 else
668 {
669 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400670 }
671 }
672 else
673 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400674 UNREACHABLE();
675 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400676 }
Geoff Lang5d601382014-07-22 15:14:06 -0400677 }
678
Geoff Langca271392017-04-05 12:30:00 -0400679 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400680 {
681 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
682 // sized, component sizes of the source and destination formats must exactly match if the
683 // destination format exists.
684 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
685 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
686 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
687 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
688 {
689 return false;
690 }
691 }
692
693 return true; // A conversion function exists, and no rule in the specification has precluded
694 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400695}
696
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500697bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
698 GLenum target,
699 GLint level,
700 GLenum internalformat,
701 bool isSubImage,
702 GLint xoffset,
703 GLint yoffset,
704 GLint zoffset,
705 GLint x,
706 GLint y,
707 GLsizei width,
708 GLsizei height,
709 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400710{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400711 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400712 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400713 xoffset, yoffset, zoffset, x, y, width, height, border,
714 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400715 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400716 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400717 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400718 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719
Jamie Madill51f40ec2016-06-15 14:06:00 -0400720 const auto &state = context->getGLState();
721 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
722 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400723
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400724 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400727 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400728 }
729
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400730 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500732 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400733 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400734 }
735
Jamie Madill0c8abca2016-07-22 20:21:26 -0400736 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400737
738 if (isSubImage)
739 {
Geoff Langca271392017-04-05 12:30:00 -0400740 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500741 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500743 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400744 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 }
746 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400747 else
748 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400749 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400750 const InternalFormat &framebufferFormat = *source->getFormat().info;
751 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400752 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500754 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400755 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400756 }
757 }
758
Geoff Lang784a8fd2013-09-24 12:33:16 -0400759 // If width or height is zero, it is a no-op. Return false without setting an error.
760 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761}
762
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500763bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
764 GLenum target,
765 GLint level,
766 GLenum internalformat,
767 bool isSubImage,
768 GLint xoffset,
769 GLint yoffset,
770 GLint zoffset,
771 GLint x,
772 GLint y,
773 GLsizei width,
774 GLsizei height,
775 GLint border)
776{
777 if (!ValidTexture2DDestinationTarget(context, target))
778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500779 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500780 return false;
781 }
782
783 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
784 xoffset, yoffset, zoffset, x, y, width, height,
785 border);
786}
787
788bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
789 GLenum target,
790 GLint level,
791 GLenum internalformat,
792 bool isSubImage,
793 GLint xoffset,
794 GLint yoffset,
795 GLint zoffset,
796 GLint x,
797 GLint y,
798 GLsizei width,
799 GLsizei height,
800 GLint border)
801{
802 if (!ValidTexture3DDestinationTarget(context, target))
803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500804 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500805 return false;
806 }
807
808 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
809 xoffset, yoffset, zoffset, x, y, width, height,
810 border);
811}
812
813bool ValidateES3TexStorageParametersBase(Context *context,
814 GLenum target,
815 GLsizei levels,
816 GLenum internalformat,
817 GLsizei width,
818 GLsizei height,
819 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820{
821 if (width < 1 || height < 1 || depth < 1 || levels < 1)
822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500823 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400824 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 }
826
Geoff Langb92c1332015-09-04 12:54:55 -0400827 GLsizei maxDim = std::max(width, height);
828 if (target != GL_TEXTURE_2D_ARRAY)
829 {
830 maxDim = std::max(maxDim, depth);
831 }
832
833 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500835 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 }
838
Geoff Langaae65a42014-05-26 12:43:44 -0400839 const gl::Caps &caps = context->getCaps();
840
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 switch (target)
842 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800843 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 {
Geoff Langaae65a42014-05-26 12:43:44 -0400845 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
846 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500848 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851 }
852 break;
853
He Yunchaoced53ae2016-11-29 15:00:51 +0800854 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400856 if (width != height)
857 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500858 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400859 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 }
861
Geoff Langaae65a42014-05-26 12:43:44 -0400862 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500864 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400865 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 }
867 }
868 break;
869
He Yunchaoced53ae2016-11-29 15:00:51 +0800870 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 {
Geoff Langaae65a42014-05-26 12:43:44 -0400872 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
873 static_cast<GLuint>(height) > caps.max3DTextureSize ||
874 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500876 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 }
879 }
880 break;
881
He Yunchaoced53ae2016-11-29 15:00:51 +0800882 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400883 {
Geoff Langaae65a42014-05-26 12:43:44 -0400884 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
885 static_cast<GLuint>(height) > caps.max2DTextureSize ||
886 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500888 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400889 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 }
891 }
892 break;
893
He Yunchaoced53ae2016-11-29 15:00:51 +0800894 default:
895 UNREACHABLE();
896 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400897 }
898
Geoff Lang691e58c2014-12-19 17:03:25 -0500899 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400900 if (!texture || texture->id() == 0)
901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500902 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400903 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400904 }
905
Geoff Lang69cce582015-09-17 13:20:36 -0400906 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500908 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400909 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 }
911
Geoff Langca271392017-04-05 12:30:00 -0400912 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400913 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500915 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400916 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917 }
918
Geoff Langca271392017-04-05 12:30:00 -0400919 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500921 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400922 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923 }
924
925 return true;
926}
927
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500928bool ValidateES3TexStorage2DParameters(Context *context,
929 GLenum target,
930 GLsizei levels,
931 GLenum internalformat,
932 GLsizei width,
933 GLsizei height,
934 GLsizei depth)
935{
936 if (!ValidTexture2DTarget(context, target))
937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500938 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500939 return false;
940 }
941
942 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
943 height, depth);
944}
945
946bool ValidateES3TexStorage3DParameters(Context *context,
947 GLenum target,
948 GLsizei levels,
949 GLenum internalformat,
950 GLsizei width,
951 GLsizei height,
952 GLsizei depth)
953{
954 if (!ValidTexture3DTarget(context, target))
955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500957 return false;
958 }
959
960 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
961 height, depth);
962}
963
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500964bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
965{
Martin Radev1be913c2016-07-11 17:59:16 +0300966 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500969 return false;
970 }
971
972 return ValidateBeginQueryBase(context, target, id);
973}
974
975bool ValidateEndQuery(gl::Context *context, GLenum target)
976{
Martin Radev1be913c2016-07-11 17:59:16 +0300977 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500979 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500980 return false;
981 }
982
983 return ValidateEndQueryBase(context, target);
984}
985
986bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
987{
Martin Radev1be913c2016-07-11 17:59:16 +0300988 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500990 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500991 return false;
992 }
993
Geoff Lang2186c382016-10-14 10:54:54 -0400994 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500995}
996
997bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
998{
Martin Radev1be913c2016-07-11 17:59:16 +0300999 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001001 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001002 return false;
1003 }
1004
Geoff Lang2186c382016-10-14 10:54:54 -04001005 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001006}
1007
He Yunchaoced53ae2016-11-29 15:00:51 +08001008bool ValidateFramebufferTextureLayer(Context *context,
1009 GLenum target,
1010 GLenum attachment,
1011 GLuint texture,
1012 GLint level,
1013 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001014{
Martin Radev1be913c2016-07-11 17:59:16 +03001015 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001019 }
1020
Jamie Madill55ec3b12014-07-03 10:38:57 -04001021 if (layer < 0)
1022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001025 }
1026
1027 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1028 {
1029 return false;
1030 }
1031
1032 const gl::Caps &caps = context->getCaps();
1033 if (texture != 0)
1034 {
1035 gl::Texture *tex = context->getTexture(texture);
1036 ASSERT(tex);
1037
1038 switch (tex->getTarget())
1039 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001040 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001041 {
1042 if (level > gl::log2(caps.max2DTextureSize))
1043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001044 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001045 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001046 }
1047
1048 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001050 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001052 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001053 }
1054 break;
1055
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001057 {
1058 if (level > gl::log2(caps.max3DTextureSize))
1059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001060 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001061 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001062 }
1063
1064 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001066 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001067 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001068 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001069 }
1070 break;
1071
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001073 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001074 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001075 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001076
Jamie Madilla3944d42016-07-22 22:13:26 -04001077 const auto &format = tex->getFormat(tex->getTarget(), level);
1078 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001080 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001081 return false;
1082 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001083 }
1084
1085 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001086}
1087
He Yunchaoced53ae2016-11-29 15:00:51 +08001088bool ValidateInvalidateFramebuffer(Context *context,
1089 GLenum target,
1090 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001091 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092{
Martin Radev1be913c2016-07-11 17:59:16 +03001093 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001095 context->handleError(InvalidOperation() << "Operation only supported on ES 3.0 and above");
Austin Kinross08332632015-05-05 13:35:47 -07001096 return false;
1097 }
1098
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 bool defaultFramebuffer = false;
1100
1101 switch (target)
1102 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 case GL_DRAW_FRAMEBUFFER:
1104 case GL_FRAMEBUFFER:
1105 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1106 break;
1107 case GL_READ_FRAMEBUFFER:
1108 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1109 break;
1110 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001111 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001112 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 }
1114
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1116 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117}
1118
Jamie Madillc29968b2016-01-20 11:17:23 -05001119bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001120{
Martin Radev1be913c2016-07-11 17:59:16 +03001121 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001123 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001125 }
1126
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001127 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001129 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001130 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001131 }
1132
1133 return true;
1134}
1135
Olli Etuaho71dfb362016-03-10 14:04:27 +02001136bool ValidateDrawRangeElements(Context *context,
1137 GLenum mode,
1138 GLuint start,
1139 GLuint end,
1140 GLsizei count,
1141 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001142 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001143{
Martin Radev1be913c2016-07-11 17:59:16 +03001144 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001146 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001147 return false;
1148 }
1149
1150 if (end < start)
1151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001152 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001153 return false;
1154 }
1155
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001156 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001157 {
1158 return false;
1159 }
1160
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001161 // Use the parameter buffer to retrieve and cache the index range.
1162 const auto &params = context->getParams<HasIndexRange>();
1163 const auto &indexRangeOpt = params.getIndexRange();
1164 if (!indexRangeOpt.valid())
1165 {
1166 // Unexpected error.
1167 return false;
1168 }
1169
1170 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001171 {
1172 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001173 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001174 return false;
1175 }
1176 return true;
1177}
1178
He Yunchaoced53ae2016-11-29 15:00:51 +08001179bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001180{
Martin Radev1be913c2016-07-11 17:59:16 +03001181 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001183 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001184 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001185 }
1186
Jamie Madill78f41802014-08-25 15:47:55 -04001187 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001188}
1189
Jamie Madillb885e572015-02-03 16:16:04 -05001190bool ValidateReadBuffer(Context *context, GLenum src)
1191{
Martin Radev1be913c2016-07-11 17:59:16 +03001192 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001194 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001195 return false;
1196 }
1197
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001198 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001199
1200 if (readFBO == nullptr)
1201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001202 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001203 return false;
1204 }
1205
1206 if (src == GL_NONE)
1207 {
1208 return true;
1209 }
1210
Olli Etuaho84c9f592016-03-09 14:37:25 +02001211 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001213 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001214 return false;
1215 }
1216
1217 if (readFBO->id() == 0)
1218 {
1219 if (src != GL_BACK)
1220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(
1222 InvalidOperation()
1223 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001224 return false;
1225 }
1226 }
1227 else
1228 {
1229 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1230
1231 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001234 return false;
1235 }
1236 }
1237
1238 return true;
1239}
1240
Jamie Madill86af3d22015-07-21 15:14:07 -04001241bool ValidateCompressedTexImage3D(Context *context,
1242 GLenum target,
1243 GLint level,
1244 GLenum internalformat,
1245 GLsizei width,
1246 GLsizei height,
1247 GLsizei depth,
1248 GLint border,
1249 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001250 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001251{
Martin Radev1be913c2016-07-11 17:59:16 +03001252 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001255 return false;
1256 }
1257
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001258 if (!ValidTextureTarget(context, target))
1259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001261 return false;
1262 }
1263
Jamie Madille2e406c2016-06-02 13:04:10 -04001264 // Validate image size
1265 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001267 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001268 return false;
1269 }
1270
Geoff Langca271392017-04-05 12:30:00 -04001271 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001272 if (!formatInfo.compressed)
1273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001275 return false;
1276 }
1277
Jamie Madill513558d2016-06-02 13:04:11 -04001278 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001279 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001280 if (blockSizeOrErr.isError())
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001283 return false;
1284 }
1285 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001287 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001288 return false;
1289 }
1290
1291 // 3D texture target validation
1292 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001294 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001295 return false;
1296 }
1297
1298 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001299 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001300 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1301 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001302 {
1303 return false;
1304 }
1305
1306 return true;
1307}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001308
Corentin Wallezb2931602017-04-11 15:58:57 -04001309bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1310 GLenum target,
1311 GLint level,
1312 GLenum internalformat,
1313 GLsizei width,
1314 GLsizei height,
1315 GLsizei depth,
1316 GLint border,
1317 GLsizei imageSize,
1318 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001319 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001320{
1321 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1322 {
1323 return false;
1324 }
1325
1326 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1327 depth, border, imageSize, data);
1328}
1329
Austin Kinrossbc781f32015-10-26 09:27:38 -07001330bool ValidateBindVertexArray(Context *context, GLuint array)
1331{
Martin Radev1be913c2016-07-11 17:59:16 +03001332 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001334 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001335 return false;
1336 }
1337
1338 return ValidateBindVertexArrayBase(context, array);
1339}
1340
Austin Kinrossbc781f32015-10-26 09:27:38 -07001341bool ValidateIsVertexArray(Context *context)
1342{
Martin Radev1be913c2016-07-11 17:59:16 +03001343 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001345 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001346 return false;
1347 }
1348
1349 return true;
1350}
Geoff Langc5629752015-12-07 16:29:04 -05001351
Jiajia Qin6eafb042016-12-27 17:04:07 +08001352static bool ValidateBindBufferCommon(Context *context,
1353 GLenum target,
1354 GLuint index,
1355 GLuint buffer,
1356 GLintptr offset,
1357 GLsizeiptr size)
1358{
1359 if (context->getClientMajorVersion() < 3)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001362 return false;
1363 }
1364
1365 if (buffer != 0 && offset < 0)
1366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001368 return false;
1369 }
1370
1371 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1372 !context->isBufferGenerated(buffer))
1373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001375 return false;
1376 }
1377
1378 const Caps &caps = context->getCaps();
1379 switch (target)
1380 {
1381 case GL_TRANSFORM_FEEDBACK_BUFFER:
1382 {
1383 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidValue() << "index is greater than or equal to the "
1386 "number of TRANSFORM_FEEDBACK_BUFFER "
1387 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001388 return false;
1389 }
1390 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001393 return false;
1394 }
1395
1396 TransformFeedback *curTransformFeedback =
1397 context->getGLState().getCurrentTransformFeedback();
1398 if (curTransformFeedback && curTransformFeedback->isActive())
1399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001400 context->handleError(InvalidOperation()
1401 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1402 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001403 return false;
1404 }
1405 break;
1406 }
1407 case GL_UNIFORM_BUFFER:
1408 {
1409 if (index >= caps.maxUniformBufferBindings)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue() << "index is greater than or equal to the "
1412 "number of UNIFORM_BUFFER indexed "
1413 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001414 return false;
1415 }
1416
1417 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1418 {
1419 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001420 InvalidValue()
1421 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001422 return false;
1423 }
1424 break;
1425 }
1426 case GL_ATOMIC_COUNTER_BUFFER:
1427 {
1428 if (context->getClientVersion() < ES_3_1)
1429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidEnum()
1431 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001432 return false;
1433 }
1434 if (index >= caps.maxAtomicCounterBufferBindings)
1435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidValue() << "index is greater than or equal to the "
1437 "number of ATOMIC_COUNTER_BUFFER "
1438 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001439 return false;
1440 }
1441 if (buffer != 0 && (offset % 4) != 0)
1442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001444 return false;
1445 }
1446 break;
1447 }
1448 case GL_SHADER_STORAGE_BUFFER:
1449 {
1450 if (context->getClientVersion() < ES_3_1)
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidEnum()
1453 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001454 return false;
1455 }
1456 if (index >= caps.maxShaderStorageBufferBindings)
1457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001458 context->handleError(InvalidValue() << "index is greater than or equal to the "
1459 "number of SHADER_STORAGE_BUFFER "
1460 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001461 return false;
1462 }
1463 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001465 context->handleError(InvalidValue() << "offset must be multiple of value of "
1466 "SHADER_STORAGE_BUFFER_OFFSET_"
1467 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001468 return false;
1469 }
1470 break;
1471 }
1472 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001473 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001474 return false;
1475 }
1476
1477 return true;
1478}
1479
1480bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1481{
1482 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1483}
1484
1485bool ValidateBindBufferRange(Context *context,
1486 GLenum target,
1487 GLuint index,
1488 GLuint buffer,
1489 GLintptr offset,
1490 GLsizeiptr size)
1491{
1492 if (buffer != 0 && size <= 0)
1493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001494 context->handleError(InvalidValue()
1495 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001496 return false;
1497 }
1498 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1499}
1500
Geoff Langc5629752015-12-07 16:29:04 -05001501bool ValidateProgramBinary(Context *context,
1502 GLuint program,
1503 GLenum binaryFormat,
1504 const void *binary,
1505 GLint length)
1506{
Martin Radev1be913c2016-07-11 17:59:16 +03001507 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001510 return false;
1511 }
1512
1513 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1514}
1515
1516bool ValidateGetProgramBinary(Context *context,
1517 GLuint program,
1518 GLsizei bufSize,
1519 GLsizei *length,
1520 GLenum *binaryFormat,
1521 void *binary)
1522{
Martin Radev1be913c2016-07-11 17:59:16 +03001523 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001525 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001526 return false;
1527 }
1528
1529 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1530}
1531
Olli Etuahof0fee072016-03-30 15:11:58 +03001532bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001533{
Martin Radev1be913c2016-07-11 17:59:16 +03001534 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001536 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Geoff Langc5629752015-12-07 16:29:04 -05001537 return false;
1538 }
1539
1540 if (GetValidProgram(context, program) == nullptr)
1541 {
1542 return false;
1543 }
1544
1545 switch (pname)
1546 {
1547 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001548 if (value != GL_FALSE && value != GL_TRUE)
1549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001550 context->handleError(InvalidValue()
1551 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001552 return false;
1553 }
Geoff Langc5629752015-12-07 16:29:04 -05001554 break;
1555
Yunchao He61afff12017-03-14 15:34:03 +08001556 case GL_PROGRAM_SEPARABLE:
1557 if (context->getClientVersion() < ES_3_1)
1558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001559 context->handleError(InvalidEnum()
1560 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001561 return false;
1562 }
1563
1564 if (value != GL_FALSE && value != GL_TRUE)
1565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001566 context->handleError(InvalidValue()
1567 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001568 return false;
1569 }
1570 break;
1571
Geoff Langc5629752015-12-07 16:29:04 -05001572 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001573 context->handleError(InvalidEnum()
1574 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001575 return false;
1576 }
1577
1578 return true;
1579}
Jamie Madillc29968b2016-01-20 11:17:23 -05001580
1581bool ValidateBlitFramebuffer(Context *context,
1582 GLint srcX0,
1583 GLint srcY0,
1584 GLint srcX1,
1585 GLint srcY1,
1586 GLint dstX0,
1587 GLint dstY0,
1588 GLint dstX1,
1589 GLint dstY1,
1590 GLbitfield mask,
1591 GLenum filter)
1592{
Martin Radev1be913c2016-07-11 17:59:16 +03001593 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001595 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001596 return false;
1597 }
1598
1599 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1600 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001601}
Jamie Madillc29968b2016-01-20 11:17:23 -05001602
1603bool ValidateClearBufferiv(ValidationContext *context,
1604 GLenum buffer,
1605 GLint drawbuffer,
1606 const GLint *value)
1607{
1608 switch (buffer)
1609 {
1610 case GL_COLOR:
1611 if (drawbuffer < 0 ||
1612 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001614 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001615 return false;
1616 }
Geoff Lang76e65652017-03-27 14:58:02 -04001617 if (context->getExtensions().webglCompatibility)
1618 {
1619 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001620 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001621 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1622 {
1623 return false;
1624 }
1625 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001626 break;
1627
1628 case GL_STENCIL:
1629 if (drawbuffer != 0)
1630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001632 return false;
1633 }
1634 break;
1635
1636 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001637 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001638 return false;
1639 }
1640
1641 return ValidateClearBuffer(context);
1642}
1643
1644bool ValidateClearBufferuiv(ValidationContext *context,
1645 GLenum buffer,
1646 GLint drawbuffer,
1647 const GLuint *value)
1648{
1649 switch (buffer)
1650 {
1651 case GL_COLOR:
1652 if (drawbuffer < 0 ||
1653 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001656 return false;
1657 }
Geoff Lang76e65652017-03-27 14:58:02 -04001658 if (context->getExtensions().webglCompatibility)
1659 {
1660 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001661 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001662 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1663 {
1664 return false;
1665 }
1666 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001667 break;
1668
1669 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001671 return false;
1672 }
1673
1674 return ValidateClearBuffer(context);
1675}
1676
1677bool ValidateClearBufferfv(ValidationContext *context,
1678 GLenum buffer,
1679 GLint drawbuffer,
1680 const GLfloat *value)
1681{
1682 switch (buffer)
1683 {
1684 case GL_COLOR:
1685 if (drawbuffer < 0 ||
1686 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001689 return false;
1690 }
Geoff Lang76e65652017-03-27 14:58:02 -04001691 if (context->getExtensions().webglCompatibility)
1692 {
1693 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1694 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001695 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001696 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1697 {
1698 return false;
1699 }
1700 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001701 break;
1702
1703 case GL_DEPTH:
1704 if (drawbuffer != 0)
1705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001706 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001707 return false;
1708 }
1709 break;
1710
1711 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001712 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001713 return false;
1714 }
1715
1716 return ValidateClearBuffer(context);
1717}
1718
1719bool ValidateClearBufferfi(ValidationContext *context,
1720 GLenum buffer,
1721 GLint drawbuffer,
1722 GLfloat depth,
1723 GLint stencil)
1724{
1725 switch (buffer)
1726 {
1727 case GL_DEPTH_STENCIL:
1728 if (drawbuffer != 0)
1729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001731 return false;
1732 }
1733 break;
1734
1735 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 return false;
1738 }
1739
1740 return ValidateClearBuffer(context);
1741}
1742
1743bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1744{
Martin Radev1be913c2016-07-11 17:59:16 +03001745 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001747 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750
1751 return ValidateDrawBuffersBase(context, n, bufs);
1752}
1753
1754bool ValidateCopyTexSubImage3D(Context *context,
1755 GLenum target,
1756 GLint level,
1757 GLint xoffset,
1758 GLint yoffset,
1759 GLint zoffset,
1760 GLint x,
1761 GLint y,
1762 GLsizei width,
1763 GLsizei height)
1764{
Martin Radev1be913c2016-07-11 17:59:16 +03001765 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001767 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001768 return false;
1769 }
1770
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001771 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1772 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001773}
1774
Jamie Madill73a84962016-02-12 09:27:23 -05001775bool ValidateTexImage3D(Context *context,
1776 GLenum target,
1777 GLint level,
1778 GLint internalformat,
1779 GLsizei width,
1780 GLsizei height,
1781 GLsizei depth,
1782 GLint border,
1783 GLenum format,
1784 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001785 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001786{
Martin Radev1be913c2016-07-11 17:59:16 +03001787 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001790 return false;
1791 }
1792
1793 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001794 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001795 pixels);
1796}
1797
Geoff Langc52f6f12016-10-14 10:18:00 -04001798bool ValidateTexImage3DRobustANGLE(Context *context,
1799 GLenum target,
1800 GLint level,
1801 GLint internalformat,
1802 GLsizei width,
1803 GLsizei height,
1804 GLsizei depth,
1805 GLint border,
1806 GLenum format,
1807 GLenum type,
1808 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001809 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001810{
1811 if (context->getClientMajorVersion() < 3)
1812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001813 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001814 return false;
1815 }
1816
1817 if (!ValidateRobustEntryPoint(context, bufSize))
1818 {
1819 return false;
1820 }
1821
1822 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1823 0, 0, width, height, depth, border, format, type,
1824 bufSize, pixels);
1825}
1826
Jamie Madill73a84962016-02-12 09:27:23 -05001827bool ValidateTexSubImage3D(Context *context,
1828 GLenum target,
1829 GLint level,
1830 GLint xoffset,
1831 GLint yoffset,
1832 GLint zoffset,
1833 GLsizei width,
1834 GLsizei height,
1835 GLsizei depth,
1836 GLenum format,
1837 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001838 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001839{
Martin Radev1be913c2016-07-11 17:59:16 +03001840 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001842 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001843 return false;
1844 }
1845
1846 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1847 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001848 -1, pixels);
1849}
1850
1851bool ValidateTexSubImage3DRobustANGLE(Context *context,
1852 GLenum target,
1853 GLint level,
1854 GLint xoffset,
1855 GLint yoffset,
1856 GLint zoffset,
1857 GLsizei width,
1858 GLsizei height,
1859 GLsizei depth,
1860 GLenum format,
1861 GLenum type,
1862 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001863 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001864{
1865 if (context->getClientMajorVersion() < 3)
1866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001867 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001868 return false;
1869 }
1870
1871 if (!ValidateRobustEntryPoint(context, bufSize))
1872 {
1873 return false;
1874 }
1875
1876 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1877 yoffset, zoffset, width, height, depth, 0, format, type,
1878 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001879}
1880
1881bool ValidateCompressedTexSubImage3D(Context *context,
1882 GLenum target,
1883 GLint level,
1884 GLint xoffset,
1885 GLint yoffset,
1886 GLint zoffset,
1887 GLsizei width,
1888 GLsizei height,
1889 GLsizei depth,
1890 GLenum format,
1891 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001892 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001893{
Martin Radev1be913c2016-07-11 17:59:16 +03001894 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001896 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001897 return false;
1898 }
1899
Geoff Langca271392017-04-05 12:30:00 -04001900 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001901 if (!formatInfo.compressed)
1902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001903 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001904 return false;
1905 }
1906
Jamie Madill513558d2016-06-02 13:04:11 -04001907 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001908 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001909 if (blockSizeOrErr.isError())
1910 {
1911 context->handleError(blockSizeOrErr.getError());
1912 return false;
1913 }
1914 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001916 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001917 return false;
1918 }
1919
1920 if (!data)
1921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001922 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001923 return false;
1924 }
1925
1926 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001927 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001928}
Corentin Wallezb2931602017-04-11 15:58:57 -04001929bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1930 GLenum target,
1931 GLint level,
1932 GLint xoffset,
1933 GLint yoffset,
1934 GLint zoffset,
1935 GLsizei width,
1936 GLsizei height,
1937 GLsizei depth,
1938 GLenum format,
1939 GLsizei imageSize,
1940 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001941 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001942{
1943 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1944 {
1945 return false;
1946 }
1947
1948 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1949 height, depth, format, imageSize, data);
1950}
Jamie Madill73a84962016-02-12 09:27:23 -05001951
Olli Etuaho41997e72016-03-10 13:38:39 +02001952bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1953{
1954 return ValidateGenOrDeleteES3(context, n);
1955}
1956
1957bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1958{
1959 return ValidateGenOrDeleteES3(context, n);
1960}
1961
1962bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1963{
1964 return ValidateGenOrDeleteCountES3(context, count);
1965}
1966
1967bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1968{
1969 return ValidateGenOrDeleteCountES3(context, count);
1970}
1971
1972bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1973{
1974 return ValidateGenOrDeleteES3(context, n);
1975}
1976
1977bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1978{
1979 if (!ValidateGenOrDeleteES3(context, n))
1980 {
1981 return false;
1982 }
1983 for (GLint i = 0; i < n; ++i)
1984 {
1985 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1986 if (transformFeedback != nullptr && transformFeedback->isActive())
1987 {
1988 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001989 context->handleError(InvalidOperation()
1990 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001991 return false;
1992 }
1993 }
1994 return true;
1995}
1996
1997bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1998{
1999 return ValidateGenOrDeleteES3(context, n);
2000}
2001
2002bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2003{
2004 return ValidateGenOrDeleteES3(context, n);
2005}
2006
2007bool ValidateGenOrDeleteES3(Context *context, GLint n)
2008{
Martin Radev1be913c2016-07-11 17:59:16 +03002009 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002011 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002012 return false;
2013 }
2014 return ValidateGenOrDelete(context, n);
2015}
2016
2017bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2018{
Martin Radev1be913c2016-07-11 17:59:16 +03002019 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002021 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002022 return false;
2023 }
2024 if (count < 0)
2025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002026 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02002027 return false;
2028 }
2029 return true;
2030}
2031
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002032bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2033{
Martin Radev1be913c2016-07-11 17:59:16 +03002034 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002036 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002037 return false;
2038 }
2039 switch (primitiveMode)
2040 {
2041 case GL_TRIANGLES:
2042 case GL_LINES:
2043 case GL_POINTS:
2044 break;
2045
2046 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002047 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002048 return false;
2049 }
2050
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002051 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002052 ASSERT(transformFeedback != nullptr);
2053
2054 if (transformFeedback->isActive())
2055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002056 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002057 return false;
2058 }
2059 return true;
2060}
2061
Jamie Madill876429b2017-04-20 15:46:24 -04002062bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002063{
Geoff Lang496c02d2016-10-20 11:38:11 -07002064 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2065}
2066
2067bool ValidateGetBufferPointervRobustANGLE(Context *context,
2068 GLenum target,
2069 GLenum pname,
2070 GLsizei bufSize,
2071 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002072 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002073{
2074 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002075 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002076 return false;
2077 }
2078
Geoff Lang496c02d2016-10-20 11:38:11 -07002079 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2080 {
2081 return false;
2082 }
2083
2084 if (!ValidateRobustBufferSize(context, bufSize, *length))
2085 {
2086 return false;
2087 }
2088
2089 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002090}
2091
2092bool ValidateUnmapBuffer(Context *context, GLenum target)
2093{
Martin Radev1be913c2016-07-11 17:59:16 +03002094 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002096 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002097 return false;
2098 }
2099
2100 return ValidateUnmapBufferBase(context, target);
2101}
2102
2103bool ValidateMapBufferRange(Context *context,
2104 GLenum target,
2105 GLintptr offset,
2106 GLsizeiptr length,
2107 GLbitfield access)
2108{
Martin Radev1be913c2016-07-11 17:59:16 +03002109 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002111 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002112 return false;
2113 }
2114
2115 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2116}
2117
2118bool ValidateFlushMappedBufferRange(Context *context,
2119 GLenum target,
2120 GLintptr offset,
2121 GLsizeiptr length)
2122{
Martin Radev1be913c2016-07-11 17:59:16 +03002123 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002125 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002126 return false;
2127 }
2128
2129 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2130}
2131
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002132bool ValidateIndexedStateQuery(ValidationContext *context,
2133 GLenum pname,
2134 GLuint index,
2135 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002136{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002137 if (length)
2138 {
2139 *length = 0;
2140 }
2141
Martin Radev66fb8202016-07-28 11:45:20 +03002142 GLenum nativeType;
2143 unsigned int numParams;
2144 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002147 return false;
2148 }
2149
2150 const Caps &caps = context->getCaps();
2151 switch (pname)
2152 {
2153 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2154 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2155 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2156 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002158 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002159 return false;
2160 }
2161 break;
2162
2163 case GL_UNIFORM_BUFFER_START:
2164 case GL_UNIFORM_BUFFER_SIZE:
2165 case GL_UNIFORM_BUFFER_BINDING:
2166 if (index >= caps.maxUniformBufferBindings)
2167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002168 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002169 return false;
2170 }
2171 break;
Shao80957d92017-02-20 21:25:59 +08002172
Martin Radev66fb8202016-07-28 11:45:20 +03002173 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2174 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2175 if (index >= 3u)
2176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002177 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002178 return false;
2179 }
2180 break;
Shao80957d92017-02-20 21:25:59 +08002181
Jiajia Qin6eafb042016-12-27 17:04:07 +08002182 case GL_ATOMIC_COUNTER_BUFFER_START:
2183 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2184 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2185 if (context->getClientVersion() < ES_3_1)
2186 {
2187 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002188 InvalidEnum()
2189 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002190 return false;
2191 }
2192 if (index >= caps.maxAtomicCounterBufferBindings)
2193 {
2194 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 InvalidValue()
2196 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002197 return false;
2198 }
2199 break;
Shao80957d92017-02-20 21:25:59 +08002200
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002201 case GL_SHADER_STORAGE_BUFFER_START:
2202 case GL_SHADER_STORAGE_BUFFER_SIZE:
2203 case GL_SHADER_STORAGE_BUFFER_BINDING:
2204 if (context->getClientVersion() < ES_3_1)
2205 {
2206 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 InvalidEnum()
2208 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002209 return false;
2210 }
2211 if (index >= caps.maxShaderStorageBufferBindings)
2212 {
2213 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002214 InvalidValue()
2215 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002216 return false;
2217 }
2218 break;
2219
Shao80957d92017-02-20 21:25:59 +08002220 case GL_VERTEX_BINDING_BUFFER:
2221 case GL_VERTEX_BINDING_DIVISOR:
2222 case GL_VERTEX_BINDING_OFFSET:
2223 case GL_VERTEX_BINDING_STRIDE:
2224 if (context->getClientVersion() < ES_3_1)
2225 {
2226 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002227 InvalidEnum()
2228 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002229 return false;
2230 }
2231 if (index >= caps.maxVertexAttribBindings)
2232 {
2233 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002234 InvalidValue()
2235 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002236 return false;
2237 }
2238 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002239 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002240 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002241 return false;
2242 }
2243
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002244 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002245 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002246 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002247 }
2248
2249 return true;
2250}
2251
2252bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2253{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002254 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002256 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002257 return false;
2258 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002259 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002260}
2261
Geoff Langcf255ea2016-10-20 11:39:09 -07002262bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2263 GLenum target,
2264 GLuint index,
2265 GLsizei bufSize,
2266 GLsizei *length,
2267 GLint *data)
2268{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002269 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Langcf255ea2016-10-20 11:39:09 -07002272 return false;
2273 }
2274
2275 if (!ValidateRobustEntryPoint(context, bufSize))
2276 {
2277 return false;
2278 }
2279
2280 if (!ValidateIndexedStateQuery(context, target, index, length))
2281 {
2282 return false;
2283 }
2284
2285 if (!ValidateRobustBufferSize(context, bufSize, *length))
2286 {
2287 return false;
2288 }
2289
2290 return true;
2291}
2292
Martin Radev66fb8202016-07-28 11:45:20 +03002293bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2294{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002295 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002298 return false;
2299 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002300 return ValidateIndexedStateQuery(context, target, index, nullptr);
2301}
2302
2303bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2304 GLenum target,
2305 GLuint index,
2306 GLsizei bufSize,
2307 GLsizei *length,
2308 GLint64 *data)
2309{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002310 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002312 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002313 return false;
2314 }
2315
2316 if (!ValidateRobustEntryPoint(context, bufSize))
2317 {
2318 return false;
2319 }
2320
2321 if (!ValidateIndexedStateQuery(context, target, index, length))
2322 {
2323 return false;
2324 }
2325
2326 if (!ValidateRobustBufferSize(context, bufSize, *length))
2327 {
2328 return false;
2329 }
2330
2331 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002332}
2333
Jamie Madillb0817d12016-11-01 15:48:31 -04002334bool ValidateCopyBufferSubData(ValidationContext *context,
2335 GLenum readTarget,
2336 GLenum writeTarget,
2337 GLintptr readOffset,
2338 GLintptr writeOffset,
2339 GLsizeiptr size)
2340{
2341 if (context->getClientMajorVersion() < 3)
2342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002343 context->handleError(InvalidOperation() << "CopyBufferSubData requires ES 3 or greater");
Jamie Madillb0817d12016-11-01 15:48:31 -04002344 return false;
2345 }
2346
2347 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002349 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002350 return false;
2351 }
2352
2353 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2354 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2355
2356 if (!readBuffer || !writeBuffer)
2357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002358 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002359 return false;
2360 }
2361
2362 // Verify that readBuffer and writeBuffer are not currently mapped
2363 if (readBuffer->isMapped() || writeBuffer->isMapped())
2364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 context->handleError(InvalidOperation()
2366 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002367 return false;
2368 }
2369
Jamie Madilld2f0c742016-11-02 10:34:41 -04002370 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2371 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2372 CheckedNumeric<GLintptr> checkedSize(size);
2373
2374 auto checkedReadSum = checkedReadOffset + checkedSize;
2375 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2376
2377 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2378 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2379 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002381 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002382 return false;
2383 }
2384
Jamie Madilld2f0c742016-11-02 10:34:41 -04002385 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002387 context->handleError(InvalidValue()
2388 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002389 return false;
2390 }
2391
Jamie Madilld2f0c742016-11-02 10:34:41 -04002392 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2393 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002395 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002396 return false;
2397 }
2398
2399 if (readBuffer == writeBuffer)
2400 {
2401 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2402 if (!checkedOffsetDiff.IsValid())
2403 {
2404 // This shold not be possible.
2405 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidValue()
2407 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002408 return false;
2409 }
2410
2411 if (checkedOffsetDiff.ValueOrDie() < size)
2412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002413 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002414 return false;
2415 }
2416 }
2417
Jamie Madillb0817d12016-11-01 15:48:31 -04002418 return true;
2419}
2420
Geoff Langc339c4e2016-11-29 10:37:36 -05002421bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2422{
2423 if (context->getClientMajorVersion() < 3)
2424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002425 context->handleError(InvalidOperation()
2426 << "glGetStringi requires OpenGL ES 3.0 or higher.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002427 return false;
2428 }
2429
2430 switch (name)
2431 {
2432 case GL_EXTENSIONS:
2433 if (index >= context->getExtensionStringCount())
2434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002435 context->handleError(InvalidValue()
2436 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002437 return false;
2438 }
2439 break;
2440
2441 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2442 if (!context->getExtensions().requestExtension)
2443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002444 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002445 return false;
2446 }
2447 if (index >= context->getRequestableExtensionStringCount())
2448 {
2449 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002450 InvalidValue()
2451 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002452 return false;
2453 }
2454 break;
2455
2456 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002457 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002458 return false;
2459 }
2460
2461 return true;
2462}
2463
Jamie Madille8fb6402017-02-14 17:56:40 -05002464bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2465 GLenum target,
2466 GLsizei samples,
2467 GLenum internalformat,
2468 GLsizei width,
2469 GLsizei height)
2470{
2471 if (context->getClientMajorVersion() < 3)
2472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002473 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002474 return false;
2475 }
2476
2477 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2478 height))
2479 {
2480 return false;
2481 }
2482
2483 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2484 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002485 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002486 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2487 samples > 0)
2488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002489 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002490 return false;
2491 }
2492
2493 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2494 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2495 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2496 {
2497 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 InvalidOperation()
2499 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002500 return false;
2501 }
2502
2503 return true;
2504}
2505
Geoff Langaa086d62017-03-23 16:47:21 -04002506bool ValidateVertexAttribIPointer(ValidationContext *context,
2507 GLuint index,
2508 GLint size,
2509 GLenum type,
2510 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002511 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002512{
2513 if (context->getClientMajorVersion() < 3)
2514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002515 context->handleError(InvalidOperation()
2516 << "VertexAttribIPointer requires OpenGL ES 3.0 or higher.");
Geoff Langaa086d62017-03-23 16:47:21 -04002517 return false;
2518 }
2519
Shao80957d92017-02-20 21:25:59 +08002520 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002521 {
Geoff Langaa086d62017-03-23 16:47:21 -04002522 return false;
2523 }
2524
Geoff Langaa086d62017-03-23 16:47:21 -04002525 if (stride < 0)
2526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002527 context->handleError(InvalidValue() << "stride cannot be negative.");
Geoff Langaa086d62017-03-23 16:47:21 -04002528 return false;
2529 }
2530
Shao80957d92017-02-20 21:25:59 +08002531 const Caps &caps = context->getCaps();
2532 if (context->getClientVersion() >= ES_3_1)
2533 {
2534 if (stride > caps.maxVertexAttribStride)
2535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002536 context->handleError(InvalidValue()
2537 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002538 return false;
2539 }
2540
2541 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2542 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2543 // validation should be inherited.
2544 if (index >= caps.maxVertexAttribBindings)
2545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002546 context->handleError(InvalidValue()
2547 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002548 return false;
2549 }
2550 }
2551
Geoff Langaa086d62017-03-23 16:47:21 -04002552 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2553 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2554 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2555 // and the pointer argument is not NULL.
2556 if (context->getGLState().getVertexArrayId() != 0 &&
2557 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context
2560 ->handleError(InvalidOperation()
2561 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002562 return false;
2563 }
2564
Geoff Lang2d62ab72017-03-23 16:54:40 -04002565 if (context->getExtensions().webglCompatibility)
2566 {
2567 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2568 {
2569 return false;
2570 }
2571 }
2572
Geoff Langaa086d62017-03-23 16:47:21 -04002573 return true;
2574}
2575
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002576bool ValidateGetSynciv(Context *context,
2577 GLsync sync,
2578 GLenum pname,
2579 GLsizei bufSize,
2580 GLsizei *length,
2581 GLint *values)
2582{
2583 if (context->getClientMajorVersion() < 3)
2584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002585 context->handleError(InvalidOperation() << "GetSynciv requires OpenGL ES 3.0 or higher.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002586 return false;
2587 }
2588
2589 if (bufSize < 0)
2590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002591 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002592 return false;
2593 }
2594
2595 FenceSync *fenceSync = context->getFenceSync(sync);
2596 if (!fenceSync)
2597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002599 return false;
2600 }
2601
2602 switch (pname)
2603 {
2604 case GL_OBJECT_TYPE:
2605 case GL_SYNC_CONDITION:
2606 case GL_SYNC_FLAGS:
2607 case GL_SYNC_STATUS:
2608 break;
2609
2610 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002611 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002612 return false;
2613 }
2614
2615 return true;
2616}
2617
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002618bool ValidateDrawElementsInstanced(ValidationContext *context,
2619 GLenum mode,
2620 GLsizei count,
2621 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002622 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002623 GLsizei instanceCount)
2624{
2625 if (context->getClientMajorVersion() < 3)
2626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002627 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002628 return false;
2629 }
2630
2631 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2632}
2633
Martin Radev137032d2017-07-13 10:11:12 +03002634bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2635 GLenum target,
2636 GLenum attachment,
2637 GLuint texture,
2638 GLint level,
2639 GLint baseViewIndex,
2640 GLsizei numViews)
2641{
2642
2643 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2644 numViews))
2645 {
2646 return false;
2647 }
2648
2649 if (baseViewIndex < 0)
2650 {
2651 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2652 return false;
2653 }
2654
2655 if (texture != 0)
2656 {
2657 Texture *tex = context->getTexture(texture);
2658 ASSERT(tex);
2659
2660 switch (tex->getTarget())
2661 {
2662 case GL_TEXTURE_2D_ARRAY:
2663 {
2664 const Caps &caps = context->getCaps();
2665 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2666 {
2667 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2668 "greater than "
2669 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2670 return false;
2671 }
2672 }
2673 break;
2674 default:
2675 context->handleError(InvalidOperation()
2676 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2677 return false;
2678 }
2679
2680 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2681 {
2682 return false;
2683 }
2684 }
2685
2686 return true;
2687}
2688
2689bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2690 GLenum target,
2691 GLenum attachment,
2692 GLuint texture,
2693 GLint level,
2694 GLsizei numViews,
2695 const GLint *viewportOffsets)
2696{
2697 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2698 numViews))
2699 {
2700 return false;
2701 }
2702
2703 const GLsizei numViewportOffsetValues = numViews * 2;
2704 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2705 {
2706 if (viewportOffsets[i] < 0)
2707 {
2708 context->handleError(InvalidValue()
2709 << "viewportOffsets cannot contain negative values.");
2710 return false;
2711 }
2712 }
2713
2714 if (texture != 0)
2715 {
2716 Texture *tex = context->getTexture(texture);
2717 ASSERT(tex);
2718
2719 switch (tex->getTarget())
2720 {
2721 case GL_TEXTURE_2D:
2722 break;
2723 default:
2724 context->handleError(InvalidOperation()
2725 << "Texture's target must be GL_TEXTURE_2D.");
2726 return false;
2727 }
2728
2729 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2730 {
2731 return false;
2732 }
2733 }
2734
2735 return true;
2736}
2737
Jamie Madillc29968b2016-01-20 11:17:23 -05002738} // namespace gl