blob: 125e839615233928a0af8fd7a4a6d29664fe881a [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 Madilld2f0c742016-11-02 10:34:41 -040011#include "base/numerics/safe_conversions.h"
12#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040017#include "libANGLE/Renderbuffer.h"
18#include "libANGLE/Texture.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
He Yunchaoced53ae2016-11-29 15:00:51 +080027static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -040028 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +080029 GLenum internalFormat,
30 GLenum format,
31 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040032{
Geoff Lang5d601382014-07-22 15:14:06 -040033
34 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -040035 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -040036 {
Geoff Lang6d1ccf02017-04-24 14:09:58 -040037 context->handleError(Error(GL_INVALID_ENUM, "Invalid format."));
38 return false;
39 }
40
41 if (!ValidES3Type(type))
42 {
43 context->handleError(Error(GL_INVALID_ENUM, "Invalid type."));
44 return false;
45 }
46
47 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
48 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
49 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
50 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
51 if (!ValidES3InternalFormat(internalFormat))
52 {
53 context->handleError(Error(GL_INVALID_VALUE, "Invalid internalFormat."));
Geoff Langb1196682014-07-23 13:47:29 -040054 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040055 }
56
Geoff Langca271392017-04-05 12:30:00 -040057 // From the ES 3.0 spec section 3.8.3:
58 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
59 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
60 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
61 // INVALID_OPERATION error.
62 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
63 {
64 context->handleError(Error(
65 GL_INVALID_OPERATION,
66 "Format cannot be GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL if target is GL_TEXTURE_3D"));
67 return false;
68 }
69
Geoff Lang5d601382014-07-22 15:14:06 -040070 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040071 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040072 {
Geoff Lang6d1ccf02017-04-24 14:09:58 -040073 context->handleError(
74 Error(GL_INVALID_OPERATION, "Invalid combination of format, type and internalFormat."));
75 return false;
76 }
77
78 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
79 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
80 {
Geoff Lang8ceaedf2017-05-09 10:32:22 -040081 context->handleError(Error(GL_INVALID_OPERATION, "Unsupported internal format."));
Geoff Langb1196682014-07-23 13:47:29 -040082 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040083 }
84
85 return true;
86}
87
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050088bool ValidateES3TexImageParametersBase(Context *context,
89 GLenum target,
90 GLint level,
91 GLenum internalformat,
92 bool isCompressed,
93 bool isSubImage,
94 GLint xoffset,
95 GLint yoffset,
96 GLint zoffset,
97 GLsizei width,
98 GLsizei height,
99 GLsizei depth,
100 GLint border,
101 GLenum format,
102 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400103 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400104 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400105{
106 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700107 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108 {
Jamie Madill437fa652016-05-03 15:13:24 -0400109 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400110 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400111 }
112
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400113 // Verify zero border
114 if (border != 0)
115 {
Jamie Madill437fa652016-05-03 15:13:24 -0400116 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 }
119
Jamie Madill6f38f822014-06-06 17:12:20 -0400120 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
121 std::numeric_limits<GLsizei>::max() - xoffset < width ||
122 std::numeric_limits<GLsizei>::max() - yoffset < height ||
123 std::numeric_limits<GLsizei>::max() - zoffset < depth)
124 {
Jamie Madill437fa652016-05-03 15:13:24 -0400125 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400126 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400127 }
128
Geoff Langaae65a42014-05-26 12:43:44 -0400129 const gl::Caps &caps = context->getCaps();
130
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400131 switch (target)
132 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800133 case GL_TEXTURE_2D:
134 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
135 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
136 {
137 context->handleError(Error(GL_INVALID_VALUE));
138 return false;
139 }
140 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400141
He Yunchaoced53ae2016-11-29 15:00:51 +0800142 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
143 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
144 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
145 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
146 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
147 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
148 if (!isSubImage && width != height)
149 {
150 context->handleError(Error(GL_INVALID_VALUE));
151 return false;
152 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400153
He Yunchaoced53ae2016-11-29 15:00:51 +0800154 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
155 {
156 context->handleError(Error(GL_INVALID_VALUE));
157 return false;
158 }
159 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160
He Yunchaoced53ae2016-11-29 15:00:51 +0800161 case GL_TEXTURE_3D:
162 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
163 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
164 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
165 {
166 context->handleError(Error(GL_INVALID_VALUE));
167 return false;
168 }
169 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400170
He Yunchaoced53ae2016-11-29 15:00:51 +0800171 case GL_TEXTURE_2D_ARRAY:
172 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
173 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
174 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
175 {
176 context->handleError(Error(GL_INVALID_VALUE));
177 return false;
178 }
179 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400180
He Yunchaoced53ae2016-11-29 15:00:51 +0800181 default:
182 context->handleError(Error(GL_INVALID_ENUM));
183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400184 }
185
He Yunchaoced53ae2016-11-29 15:00:51 +0800186 gl::Texture *texture =
187 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400188 if (!texture)
189 {
Jamie Madill437fa652016-05-03 15:13:24 -0400190 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400191 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400192 }
193
Geoff Lang69cce582015-09-17 13:20:36 -0400194 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400195 {
Jamie Madill437fa652016-05-03 15:13:24 -0400196 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 }
199
200 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400201 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400202 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500203 if (isSubImage && actualInternalFormat == GL_NONE)
204 {
205 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
206 return false;
207 }
208
Geoff Langc4e93662017-05-01 10:45:59 -0400209 const gl::InternalFormat &actualFormatInfo = isSubImage
210 ? *texture->getFormat(target, level).info
211 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400212 if (isCompressed)
213 {
tmartino7c102692015-10-02 16:43:40 -0400214 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400215 {
Jamie Madill437fa652016-05-03 15:13:24 -0400216 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400217 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400218 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400219 }
220
Geoff Lang966c9402017-04-18 12:38:27 -0400221 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 {
Geoff Lang966c9402017-04-18 12:38:27 -0400223 if (!ValidCompressedSubImageSize(
224 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
225 texture->getWidth(target, level), texture->getHeight(target, level)))
226 {
227 context->handleError(
228 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
229 return false;
230 }
231
232 if (format != actualInternalFormat)
233 {
234 context->handleError(Error(
235 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
236 return false;
237 }
238 }
239 else
240 {
241 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
242 {
243 context->handleError(
244 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
245 return false;
246 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400247 }
248
Geoff Langeb66a6e2016-10-31 13:06:12 -0400249 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400250 {
Jamie Madill437fa652016-05-03 15:13:24 -0400251 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400252 return false;
253 }
254
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 if (target == GL_TEXTURE_3D)
256 {
Jamie Madill437fa652016-05-03 15:13:24 -0400257 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400259 }
260 }
261 else
262 {
Geoff Langca271392017-04-05 12:30:00 -0400263 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400264 {
Geoff Lang5d601382014-07-22 15:14:06 -0400265 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400266 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400267 }
268
269 // Validate sub image parameters
270 if (isSubImage)
271 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500272 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400273 {
Jamie Madill437fa652016-05-03 15:13:24 -0400274 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400275 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400276 }
277
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400278 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
279 {
Jamie Madill437fa652016-05-03 15:13:24 -0400280 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400281 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400282 }
283
284 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
285 std::numeric_limits<GLsizei>::max() - yoffset < height ||
286 std::numeric_limits<GLsizei>::max() - zoffset < depth)
287 {
Jamie Madill437fa652016-05-03 15:13:24 -0400288 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400289 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400290 }
291
Geoff Langa9be0dc2014-12-17 12:34:40 -0500292 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
293 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
294 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295 {
Jamie Madill437fa652016-05-03 15:13:24 -0400296 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400297 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298 }
299 }
300
Corentin Wallezd2627992017-04-28 17:17:03 -0400301 if (!ValidImageDataSize(context, target, width, height, depth, actualInternalFormat, type,
302 pixels, imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400303 {
304 return false;
305 }
306
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400307 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700308 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400309 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400310 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800311 // ...data is not evenly divisible into the number of bytes needed to store in memory a
312 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400313 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400314 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400315 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400316 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400317 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
318
Geoff Langff5b2d52016-09-07 11:32:23 -0400319 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400320 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400321 context->handleError(
322 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400323 return false;
324 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400325 }
326
Jamie Madill7a5f7382014-03-05 15:01:24 -0500327 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700328 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500329 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400330 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400331 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500332 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400333 }
334
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 return true;
336}
337
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500338bool ValidateES3TexImage2DParameters(Context *context,
339 GLenum target,
340 GLint level,
341 GLenum internalformat,
342 bool isCompressed,
343 bool isSubImage,
344 GLint xoffset,
345 GLint yoffset,
346 GLint zoffset,
347 GLsizei width,
348 GLsizei height,
349 GLsizei depth,
350 GLint border,
351 GLenum format,
352 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400353 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400354 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500355{
356 if (!ValidTexture2DDestinationTarget(context, target))
357 {
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500359 return false;
360 }
361
362 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
363 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400364 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500365}
366
367bool ValidateES3TexImage3DParameters(Context *context,
368 GLenum target,
369 GLint level,
370 GLenum internalformat,
371 bool isCompressed,
372 bool isSubImage,
373 GLint xoffset,
374 GLint yoffset,
375 GLint zoffset,
376 GLsizei width,
377 GLsizei height,
378 GLsizei depth,
379 GLint border,
380 GLenum format,
381 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400382 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400383 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500384{
385 if (!ValidTexture3DDestinationTarget(context, target))
386 {
Jamie Madill437fa652016-05-03 15:13:24 -0400387 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500388 return false;
389 }
390
391 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
392 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400393 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500394}
395
Geoff Lang5d601382014-07-22 15:14:06 -0400396struct EffectiveInternalFormatInfo
397{
Jamie Madill76648fe2016-10-05 17:01:41 -0400398 GLenum effectiveFormat;
399 GLenum destFormat;
400 GLuint minRedBits;
401 GLuint maxRedBits;
402 GLuint minGreenBits;
403 GLuint maxGreenBits;
404 GLuint minBlueBits;
405 GLuint maxBlueBits;
406 GLuint minAlphaBits;
407 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400408};
409
Jamie Madill76648fe2016-10-05 17:01:41 -0400410static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
411 GLenum targetFormat,
412 const EffectiveInternalFormatInfo *list,
413 size_t size,
414 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400415{
Jamie Madill76648fe2016-10-05 17:01:41 -0400416 for (size_t curFormat = 0; curFormat < size; ++curFormat)
417 {
418 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
419 if ((formatInfo.destFormat == targetFormat) &&
420 (formatInfo.minRedBits <= srcFormat.redBits &&
421 formatInfo.maxRedBits >= srcFormat.redBits) &&
422 (formatInfo.minGreenBits <= srcFormat.greenBits &&
423 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
424 (formatInfo.minBlueBits <= srcFormat.blueBits &&
425 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
426 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
427 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
428 {
429 *outEffectiveFormat = formatInfo.effectiveFormat;
430 return true;
431 }
432 }
Geoff Lang5d601382014-07-22 15:14:06 -0400433
Jamie Madill76648fe2016-10-05 17:01:41 -0400434 *outEffectiveFormat = GL_NONE;
435 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400436}
437
Jamie Madill76648fe2016-10-05 17:01:41 -0400438bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
439 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400440{
Jamie Madill76648fe2016-10-05 17:01:41 -0400441 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
442 // Effective internal format coresponding to destination internal format and linear source
443 // buffer component sizes.
444 // | Source channel min/max sizes |
445 // Effective Internal Format | N/A | R | G | B | A |
446 // clang-format off
447 constexpr EffectiveInternalFormatInfo list[] = {
448 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
449 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
450 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
451 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
452 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
453 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
454 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
455 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
456 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
457 };
458 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400459
Jamie Madill76648fe2016-10-05 17:01:41 -0400460 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
461}
Geoff Lang5d601382014-07-22 15:14:06 -0400462
Jamie Madill76648fe2016-10-05 17:01:41 -0400463bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
464 const InternalFormat &destFormat,
465 GLenum *outEffectiveFormat)
466{
467 constexpr GLuint umax = UINT_MAX;
468
469 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
470 // Effective internal format coresponding to destination internal format andlinear source buffer
471 // component sizes.
472 // | Source channel min/max sizes |
473 // Effective Internal Format | Dest Format | R | G | B | A |
474 // clang-format off
475 constexpr EffectiveInternalFormatInfo list[] = {
476 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
477 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
478 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
479 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
480 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
481 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
482 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
483 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
484 };
485 // clang-format on
486
487 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
488 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400489}
490
He Yunchaoced53ae2016-11-29 15:00:51 +0800491static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
492 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400493 GLenum *outEffectiveFormat)
494{
Geoff Langca271392017-04-05 12:30:00 -0400495 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400496 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400497 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400498 }
499 else
500 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400501 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400502 }
Geoff Lang5d601382014-07-22 15:14:06 -0400503}
504
Corentin Wallez76287682016-04-25 09:23:38 -0400505static bool EqualOrFirstZero(GLuint first, GLuint second)
506{
507 return first == 0 || first == second;
508}
509
Geoff Langca271392017-04-05 12:30:00 -0400510static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
511 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400512 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400513{
Jamie Madill21b786b2016-11-01 17:41:31 -0400514 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400515 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400516 return false;
517 }
Geoff Lang5d601382014-07-22 15:14:06 -0400518
Jamie Madill21b786b2016-11-01 17:41:31 -0400519 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
520 // must both be signed, unsigned, or fixed point and both source and destinations
521 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
522 // conversion between fixed and floating point.
523
524 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
525 (framebufferFormatInfo.colorEncoding == GL_SRGB))
526 {
527 return false;
528 }
529
530 if (((textureFormatInfo.componentType == GL_INT) !=
531 (framebufferFormatInfo.componentType == GL_INT)) ||
532 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
533 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
534 {
535 return false;
536 }
537
538 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
539 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
540 textureFormatInfo.componentType == GL_FLOAT) &&
541 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
542 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
543 framebufferFormatInfo.componentType == GL_FLOAT))
544 {
545 return false;
546 }
547
548 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
549 // The effective internal format of the source buffer is determined with the following rules
550 // applied in order:
551 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
552 // format then the effective internal format is the source buffer's sized internal format.
553 // * If the source buffer is a texture that was created with an unsized base internal format,
554 // then the effective internal format is the source image array's effective internal
555 // format, as specified by table 3.12, which is determined from the <format> and <type>
556 // that were used when the source image array was specified by TexImage*.
557 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
558 // where Destination Internal Format matches internalformat and where the [source channel
559 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
560 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
561 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800562 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400563 if (readBufferHandle != 0)
564 {
565 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
566 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400567 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400568 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400569 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400570 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400571 else
Geoff Lang5d601382014-07-22 15:14:06 -0400572 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400573 // Renderbuffers cannot be created with an unsized internal format, so this must be an
574 // unsized-format texture. We can use the same table we use when creating textures to
575 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400576 sourceEffectiveFormat =
577 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400578 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400579 }
580 else
581 {
582 // The effective internal format must be derived from the source framebuffer's channel
583 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
584 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400585 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400586 GLenum effectiveFormat;
587 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
588 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400589 {
Geoff Langca271392017-04-05 12:30:00 -0400590 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400591 }
592 else
593 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400594 return false;
595 }
596 }
597 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
598 {
599 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400600 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400601 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
602 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
603 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
604 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
605 {
Geoff Langca271392017-04-05 12:30:00 -0400606 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400607 }
608 else
609 {
610 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400611 }
612 }
613 else
614 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400615 UNREACHABLE();
616 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400617 }
Geoff Lang5d601382014-07-22 15:14:06 -0400618 }
619
Geoff Langca271392017-04-05 12:30:00 -0400620 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400621 {
622 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
623 // sized, component sizes of the source and destination formats must exactly match if the
624 // destination format exists.
625 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
626 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
627 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
628 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
629 {
630 return false;
631 }
632 }
633
634 return true; // A conversion function exists, and no rule in the specification has precluded
635 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400636}
637
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500638bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
639 GLenum target,
640 GLint level,
641 GLenum internalformat,
642 bool isSubImage,
643 GLint xoffset,
644 GLint yoffset,
645 GLint zoffset,
646 GLint x,
647 GLint y,
648 GLsizei width,
649 GLsizei height,
650 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400651{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400652 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400653 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400654 xoffset, yoffset, zoffset, x, y, width, height, border,
655 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400656 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400657 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400658 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400659 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400660
Jamie Madill51f40ec2016-06-15 14:06:00 -0400661 const auto &state = context->getGLState();
662 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
663 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400664
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400665 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400666 {
Jamie Madill437fa652016-05-03 15:13:24 -0400667 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400668 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400669 }
670
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400671 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400672 {
Jamie Madill437fa652016-05-03 15:13:24 -0400673 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400674 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400675 }
676
Jamie Madill0c8abca2016-07-22 20:21:26 -0400677 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400678
679 if (isSubImage)
680 {
Geoff Langca271392017-04-05 12:30:00 -0400681 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500682 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400683 {
Jamie Madill437fa652016-05-03 15:13:24 -0400684 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400685 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400686 }
687 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400688 else
689 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400690 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400691 const InternalFormat &framebufferFormat = *source->getFormat().info;
692 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400693 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400694 {
Jamie Madill437fa652016-05-03 15:13:24 -0400695 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400696 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400697 }
698 }
699
Geoff Lang784a8fd2013-09-24 12:33:16 -0400700 // If width or height is zero, it is a no-op. Return false without setting an error.
701 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400702}
703
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500704bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
705 GLenum target,
706 GLint level,
707 GLenum internalformat,
708 bool isSubImage,
709 GLint xoffset,
710 GLint yoffset,
711 GLint zoffset,
712 GLint x,
713 GLint y,
714 GLsizei width,
715 GLsizei height,
716 GLint border)
717{
718 if (!ValidTexture2DDestinationTarget(context, target))
719 {
Jamie Madill437fa652016-05-03 15:13:24 -0400720 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500721 return false;
722 }
723
724 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
725 xoffset, yoffset, zoffset, x, y, width, height,
726 border);
727}
728
729bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
730 GLenum target,
731 GLint level,
732 GLenum internalformat,
733 bool isSubImage,
734 GLint xoffset,
735 GLint yoffset,
736 GLint zoffset,
737 GLint x,
738 GLint y,
739 GLsizei width,
740 GLsizei height,
741 GLint border)
742{
743 if (!ValidTexture3DDestinationTarget(context, target))
744 {
Jamie Madill437fa652016-05-03 15:13:24 -0400745 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500746 return false;
747 }
748
749 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
750 xoffset, yoffset, zoffset, x, y, width, height,
751 border);
752}
753
754bool ValidateES3TexStorageParametersBase(Context *context,
755 GLenum target,
756 GLsizei levels,
757 GLenum internalformat,
758 GLsizei width,
759 GLsizei height,
760 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761{
762 if (width < 1 || height < 1 || depth < 1 || levels < 1)
763 {
Jamie Madill437fa652016-05-03 15:13:24 -0400764 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766 }
767
Geoff Langb92c1332015-09-04 12:54:55 -0400768 GLsizei maxDim = std::max(width, height);
769 if (target != GL_TEXTURE_2D_ARRAY)
770 {
771 maxDim = std::max(maxDim, depth);
772 }
773
774 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 {
Jamie Madill437fa652016-05-03 15:13:24 -0400776 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400777 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400778 }
779
Geoff Langaae65a42014-05-26 12:43:44 -0400780 const gl::Caps &caps = context->getCaps();
781
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 switch (target)
783 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800784 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 {
Geoff Langaae65a42014-05-26 12:43:44 -0400786 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
787 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 {
Jamie Madill437fa652016-05-03 15:13:24 -0400789 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 }
792 }
793 break;
794
He Yunchaoced53ae2016-11-29 15:00:51 +0800795 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400797 if (width != height)
798 {
Jamie Madill437fa652016-05-03 15:13:24 -0400799 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 }
802
Geoff Langaae65a42014-05-26 12:43:44 -0400803 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 {
Jamie Madill437fa652016-05-03 15:13:24 -0400805 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400806 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400807 }
808 }
809 break;
810
He Yunchaoced53ae2016-11-29 15:00:51 +0800811 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 {
Geoff Langaae65a42014-05-26 12:43:44 -0400813 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
814 static_cast<GLuint>(height) > caps.max3DTextureSize ||
815 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400816 {
Jamie Madill437fa652016-05-03 15:13:24 -0400817 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820 }
821 break;
822
He Yunchaoced53ae2016-11-29 15:00:51 +0800823 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 {
Geoff Langaae65a42014-05-26 12:43:44 -0400825 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
826 static_cast<GLuint>(height) > caps.max2DTextureSize ||
827 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 {
Jamie Madill437fa652016-05-03 15:13:24 -0400829 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400830 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 }
832 }
833 break;
834
He Yunchaoced53ae2016-11-29 15:00:51 +0800835 default:
836 UNREACHABLE();
837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 }
839
Geoff Lang691e58c2014-12-19 17:03:25 -0500840 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 if (!texture || texture->id() == 0)
842 {
Jamie Madill437fa652016-05-03 15:13:24 -0400843 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400844 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400845 }
846
Geoff Lang69cce582015-09-17 13:20:36 -0400847 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848 {
Jamie Madill437fa652016-05-03 15:13:24 -0400849 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400850 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400851 }
852
Geoff Langca271392017-04-05 12:30:00 -0400853 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400854 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Jamie Madill437fa652016-05-03 15:13:24 -0400856 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859
Geoff Langca271392017-04-05 12:30:00 -0400860 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 {
Jamie Madill437fa652016-05-03 15:13:24 -0400862 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400863 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400864 }
865
866 return true;
867}
868
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500869bool ValidateES3TexStorage2DParameters(Context *context,
870 GLenum target,
871 GLsizei levels,
872 GLenum internalformat,
873 GLsizei width,
874 GLsizei height,
875 GLsizei depth)
876{
877 if (!ValidTexture2DTarget(context, target))
878 {
Jamie Madill437fa652016-05-03 15:13:24 -0400879 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500880 return false;
881 }
882
883 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
884 height, depth);
885}
886
887bool ValidateES3TexStorage3DParameters(Context *context,
888 GLenum target,
889 GLsizei levels,
890 GLenum internalformat,
891 GLsizei width,
892 GLsizei height,
893 GLsizei depth)
894{
895 if (!ValidTexture3DTarget(context, target))
896 {
Jamie Madill437fa652016-05-03 15:13:24 -0400897 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500898 return false;
899 }
900
901 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
902 height, depth);
903}
904
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500905bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
906{
Martin Radev1be913c2016-07-11 17:59:16 +0300907 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500908 {
Jamie Madill437fa652016-05-03 15:13:24 -0400909 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500910 return false;
911 }
912
913 return ValidateBeginQueryBase(context, target, id);
914}
915
916bool ValidateEndQuery(gl::Context *context, GLenum target)
917{
Martin Radev1be913c2016-07-11 17:59:16 +0300918 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500919 {
Jamie Madill437fa652016-05-03 15:13:24 -0400920 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500921 return false;
922 }
923
924 return ValidateEndQueryBase(context, target);
925}
926
927bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
928{
Martin Radev1be913c2016-07-11 17:59:16 +0300929 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500930 {
Jamie Madill437fa652016-05-03 15:13:24 -0400931 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500932 return false;
933 }
934
Geoff Lang2186c382016-10-14 10:54:54 -0400935 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500936}
937
938bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
939{
Martin Radev1be913c2016-07-11 17:59:16 +0300940 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500941 {
Jamie Madill437fa652016-05-03 15:13:24 -0400942 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500943 return false;
944 }
945
Geoff Lang2186c382016-10-14 10:54:54 -0400946 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500947}
948
He Yunchaoced53ae2016-11-29 15:00:51 +0800949bool ValidateFramebufferTextureLayer(Context *context,
950 GLenum target,
951 GLenum attachment,
952 GLuint texture,
953 GLint level,
954 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400955{
Martin Radev1be913c2016-07-11 17:59:16 +0300956 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400957 {
Jamie Madill437fa652016-05-03 15:13:24 -0400958 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400959 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400960 }
961
Jamie Madill55ec3b12014-07-03 10:38:57 -0400962 if (layer < 0)
963 {
Jamie Madill437fa652016-05-03 15:13:24 -0400964 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400965 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400966 }
967
968 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
969 {
970 return false;
971 }
972
973 const gl::Caps &caps = context->getCaps();
974 if (texture != 0)
975 {
976 gl::Texture *tex = context->getTexture(texture);
977 ASSERT(tex);
978
979 switch (tex->getTarget())
980 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400982 {
983 if (level > gl::log2(caps.max2DTextureSize))
984 {
Jamie Madill437fa652016-05-03 15:13:24 -0400985 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400986 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400987 }
988
989 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
990 {
Jamie Madill437fa652016-05-03 15:13:24 -0400991 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400992 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400993 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400994 }
995 break;
996
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400998 {
999 if (level > gl::log2(caps.max3DTextureSize))
1000 {
Jamie Madill437fa652016-05-03 15:13:24 -04001001 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001002 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001003 }
1004
1005 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1006 {
Jamie Madill437fa652016-05-03 15:13:24 -04001007 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001008 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001009 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001010 }
1011 break;
1012
He Yunchaoced53ae2016-11-29 15:00:51 +08001013 default:
1014 context->handleError(Error(GL_INVALID_OPERATION));
1015 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001016 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001017
Jamie Madilla3944d42016-07-22 22:13:26 -04001018 const auto &format = tex->getFormat(tex->getTarget(), level);
1019 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001020 {
Jamie Madill437fa652016-05-03 15:13:24 -04001021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001022 return false;
1023 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001024 }
1025
1026 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001027}
1028
He Yunchaoced53ae2016-11-29 15:00:51 +08001029bool ValidateInvalidateFramebuffer(Context *context,
1030 GLenum target,
1031 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001032 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033{
Martin Radev1be913c2016-07-11 17:59:16 +03001034 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001035 {
Jamie Madill437fa652016-05-03 15:13:24 -04001036 context->handleError(
1037 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001038 return false;
1039 }
1040
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 bool defaultFramebuffer = false;
1042
1043 switch (target)
1044 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001045 case GL_DRAW_FRAMEBUFFER:
1046 case GL_FRAMEBUFFER:
1047 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1048 break;
1049 case GL_READ_FRAMEBUFFER:
1050 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1051 break;
1052 default:
1053 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 }
1056
He Yunchaoced53ae2016-11-29 15:00:51 +08001057 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1058 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059}
1060
Jamie Madillc29968b2016-01-20 11:17:23 -05001061bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001062{
Martin Radev1be913c2016-07-11 17:59:16 +03001063 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001064 {
Jamie Madill437fa652016-05-03 15:13:24 -04001065 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001066 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001067 }
1068
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001069 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001070 {
Jamie Madill437fa652016-05-03 15:13:24 -04001071 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001072 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001073 }
1074
1075 return true;
1076}
1077
Olli Etuaho71dfb362016-03-10 14:04:27 +02001078bool ValidateDrawRangeElements(Context *context,
1079 GLenum mode,
1080 GLuint start,
1081 GLuint end,
1082 GLsizei count,
1083 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001084 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001085{
Martin Radev1be913c2016-07-11 17:59:16 +03001086 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001089 return false;
1090 }
1091
1092 if (end < start)
1093 {
Jamie Madill437fa652016-05-03 15:13:24 -04001094 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001095 return false;
1096 }
1097
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001098 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001099 {
1100 return false;
1101 }
1102
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001103 // Use the parameter buffer to retrieve and cache the index range.
1104 const auto &params = context->getParams<HasIndexRange>();
1105 const auto &indexRangeOpt = params.getIndexRange();
1106 if (!indexRangeOpt.valid())
1107 {
1108 // Unexpected error.
1109 return false;
1110 }
1111
1112 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001113 {
1114 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001115 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001116 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1117 return false;
1118 }
1119 return true;
1120}
1121
He Yunchaoced53ae2016-11-29 15:00:51 +08001122bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001123{
Martin Radev1be913c2016-07-11 17:59:16 +03001124 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001125 {
Jamie Madill437fa652016-05-03 15:13:24 -04001126 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001127 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001128 }
1129
Jamie Madill78f41802014-08-25 15:47:55 -04001130 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001131}
1132
Jamie Madillb885e572015-02-03 16:16:04 -05001133bool ValidateReadBuffer(Context *context, GLenum src)
1134{
Martin Radev1be913c2016-07-11 17:59:16 +03001135 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001136 {
Jamie Madill437fa652016-05-03 15:13:24 -04001137 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001138 return false;
1139 }
1140
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001141 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001142
1143 if (readFBO == nullptr)
1144 {
Jamie Madill437fa652016-05-03 15:13:24 -04001145 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001146 return false;
1147 }
1148
1149 if (src == GL_NONE)
1150 {
1151 return true;
1152 }
1153
Olli Etuaho84c9f592016-03-09 14:37:25 +02001154 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001155 {
Jamie Madill437fa652016-05-03 15:13:24 -04001156 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001157 return false;
1158 }
1159
1160 if (readFBO->id() == 0)
1161 {
1162 if (src != GL_BACK)
1163 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001164 const char *errorMsg =
1165 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001166 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001167 return false;
1168 }
1169 }
1170 else
1171 {
1172 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1173
1174 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1175 {
1176 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001177 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001178 return false;
1179 }
1180 }
1181
1182 return true;
1183}
1184
Jamie Madill86af3d22015-07-21 15:14:07 -04001185bool ValidateCompressedTexImage3D(Context *context,
1186 GLenum target,
1187 GLint level,
1188 GLenum internalformat,
1189 GLsizei width,
1190 GLsizei height,
1191 GLsizei depth,
1192 GLint border,
1193 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001194 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001195{
Martin Radev1be913c2016-07-11 17:59:16 +03001196 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001197 {
Jamie Madill437fa652016-05-03 15:13:24 -04001198 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001199 return false;
1200 }
1201
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001202 if (!ValidTextureTarget(context, target))
1203 {
1204 context->handleError(Error(GL_INVALID_ENUM));
1205 return false;
1206 }
1207
Jamie Madille2e406c2016-06-02 13:04:10 -04001208 // Validate image size
1209 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1210 {
1211 context->handleError(Error(GL_INVALID_VALUE));
1212 return false;
1213 }
1214
Geoff Langca271392017-04-05 12:30:00 -04001215 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001216 if (!formatInfo.compressed)
1217 {
1218 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1219 return false;
1220 }
1221
Jamie Madill513558d2016-06-02 13:04:11 -04001222 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001223 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001224 if (blockSizeOrErr.isError())
1225 {
Jamie Madill513558d2016-06-02 13:04:11 -04001226 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001227 return false;
1228 }
1229 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001232 return false;
1233 }
1234
1235 // 3D texture target validation
1236 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1237 {
Jamie Madill437fa652016-05-03 15:13:24 -04001238 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001239 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1240 return false;
1241 }
1242
1243 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001244 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001245 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1246 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001247 {
1248 return false;
1249 }
1250
1251 return true;
1252}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253
Corentin Wallezb2931602017-04-11 15:58:57 -04001254bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1255 GLenum target,
1256 GLint level,
1257 GLenum internalformat,
1258 GLsizei width,
1259 GLsizei height,
1260 GLsizei depth,
1261 GLint border,
1262 GLsizei imageSize,
1263 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001264 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001265{
1266 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1267 {
1268 return false;
1269 }
1270
1271 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1272 depth, border, imageSize, data);
1273}
1274
Austin Kinrossbc781f32015-10-26 09:27:38 -07001275bool ValidateBindVertexArray(Context *context, GLuint array)
1276{
Martin Radev1be913c2016-07-11 17:59:16 +03001277 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001278 {
Jamie Madill437fa652016-05-03 15:13:24 -04001279 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001280 return false;
1281 }
1282
1283 return ValidateBindVertexArrayBase(context, array);
1284}
1285
Austin Kinrossbc781f32015-10-26 09:27:38 -07001286bool ValidateIsVertexArray(Context *context)
1287{
Martin Radev1be913c2016-07-11 17:59:16 +03001288 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001289 {
Jamie Madill437fa652016-05-03 15:13:24 -04001290 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001291 return false;
1292 }
1293
1294 return true;
1295}
Geoff Langc5629752015-12-07 16:29:04 -05001296
Jiajia Qin6eafb042016-12-27 17:04:07 +08001297static bool ValidateBindBufferCommon(Context *context,
1298 GLenum target,
1299 GLuint index,
1300 GLuint buffer,
1301 GLintptr offset,
1302 GLsizeiptr size)
1303{
1304 if (context->getClientMajorVersion() < 3)
1305 {
1306 context->handleError(Error(GL_INVALID_OPERATION));
1307 return false;
1308 }
1309
1310 if (buffer != 0 && offset < 0)
1311 {
1312 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1313 return false;
1314 }
1315
1316 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1317 !context->isBufferGenerated(buffer))
1318 {
1319 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1320 return false;
1321 }
1322
1323 const Caps &caps = context->getCaps();
1324 switch (target)
1325 {
1326 case GL_TRANSFORM_FEEDBACK_BUFFER:
1327 {
1328 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1329 {
1330 context->handleError(Error(GL_INVALID_VALUE,
1331 "index is greater than or equal to the number of "
1332 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1333 return false;
1334 }
1335 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1336 {
1337 context->handleError(
1338 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1339 return false;
1340 }
1341
1342 TransformFeedback *curTransformFeedback =
1343 context->getGLState().getCurrentTransformFeedback();
1344 if (curTransformFeedback && curTransformFeedback->isActive())
1345 {
1346 context->handleError(Error(GL_INVALID_OPERATION,
1347 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1348 "feedback is currently active."));
1349 return false;
1350 }
1351 break;
1352 }
1353 case GL_UNIFORM_BUFFER:
1354 {
1355 if (index >= caps.maxUniformBufferBindings)
1356 {
1357 context->handleError(Error(GL_INVALID_VALUE,
1358 "index is greater than or equal to the number of "
1359 "UNIFORM_BUFFER indexed binding points."));
1360 return false;
1361 }
1362
1363 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1364 {
1365 context->handleError(
1366 Error(GL_INVALID_VALUE,
1367 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1368 return false;
1369 }
1370 break;
1371 }
1372 case GL_ATOMIC_COUNTER_BUFFER:
1373 {
1374 if (context->getClientVersion() < ES_3_1)
1375 {
Yunchao He61afff12017-03-14 15:34:03 +08001376 context->handleError(Error(
1377 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001378 return false;
1379 }
1380 if (index >= caps.maxAtomicCounterBufferBindings)
1381 {
1382 context->handleError(Error(GL_INVALID_VALUE,
1383 "index is greater than or equal to the number of "
1384 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1385 return false;
1386 }
1387 if (buffer != 0 && (offset % 4) != 0)
1388 {
1389 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1390 return false;
1391 }
1392 break;
1393 }
1394 case GL_SHADER_STORAGE_BUFFER:
1395 {
1396 if (context->getClientVersion() < ES_3_1)
1397 {
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001398 context->handleError(
1399 Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
1400 return false;
1401 }
1402 if (index >= caps.maxShaderStorageBufferBindings)
1403 {
1404 context->handleError(Error(GL_INVALID_VALUE,
1405 "index is greater than or equal to the number of "
1406 "SHADER_STORAGE_BUFFER indexed binding points."));
1407 return false;
1408 }
1409 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1410 {
Yunchao He61afff12017-03-14 15:34:03 +08001411 context->handleError(Error(
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001412 GL_INVALID_VALUE,
1413 "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001414 return false;
1415 }
1416 break;
1417 }
1418 default:
1419 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1420 return false;
1421 }
1422
1423 return true;
1424}
1425
1426bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1427{
1428 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1429}
1430
1431bool ValidateBindBufferRange(Context *context,
1432 GLenum target,
1433 GLuint index,
1434 GLuint buffer,
1435 GLintptr offset,
1436 GLsizeiptr size)
1437{
1438 if (buffer != 0 && size <= 0)
1439 {
1440 context->handleError(
1441 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1442 return false;
1443 }
1444 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1445}
1446
Geoff Langc5629752015-12-07 16:29:04 -05001447bool ValidateProgramBinary(Context *context,
1448 GLuint program,
1449 GLenum binaryFormat,
1450 const void *binary,
1451 GLint length)
1452{
Martin Radev1be913c2016-07-11 17:59:16 +03001453 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001456 return false;
1457 }
1458
1459 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1460}
1461
1462bool ValidateGetProgramBinary(Context *context,
1463 GLuint program,
1464 GLsizei bufSize,
1465 GLsizei *length,
1466 GLenum *binaryFormat,
1467 void *binary)
1468{
Martin Radev1be913c2016-07-11 17:59:16 +03001469 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001470 {
Jamie Madill437fa652016-05-03 15:13:24 -04001471 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001472 return false;
1473 }
1474
1475 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1476}
1477
Olli Etuahof0fee072016-03-30 15:11:58 +03001478bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001479{
Martin Radev1be913c2016-07-11 17:59:16 +03001480 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001481 {
Jamie Madill437fa652016-05-03 15:13:24 -04001482 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001483 return false;
1484 }
1485
1486 if (GetValidProgram(context, program) == nullptr)
1487 {
1488 return false;
1489 }
1490
1491 switch (pname)
1492 {
1493 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001494 if (value != GL_FALSE && value != GL_TRUE)
1495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001497 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1498 return false;
1499 }
Geoff Langc5629752015-12-07 16:29:04 -05001500 break;
1501
Yunchao He61afff12017-03-14 15:34:03 +08001502 case GL_PROGRAM_SEPARABLE:
1503 if (context->getClientVersion() < ES_3_1)
1504 {
1505 context->handleError(
1506 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1507 return false;
1508 }
1509
1510 if (value != GL_FALSE && value != GL_TRUE)
1511 {
1512 context->handleError(Error(
1513 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1514 return false;
1515 }
1516 break;
1517
Geoff Langc5629752015-12-07 16:29:04 -05001518 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001519 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001520 return false;
1521 }
1522
1523 return true;
1524}
Jamie Madillc29968b2016-01-20 11:17:23 -05001525
1526bool ValidateBlitFramebuffer(Context *context,
1527 GLint srcX0,
1528 GLint srcY0,
1529 GLint srcX1,
1530 GLint srcY1,
1531 GLint dstX0,
1532 GLint dstY0,
1533 GLint dstX1,
1534 GLint dstY1,
1535 GLbitfield mask,
1536 GLenum filter)
1537{
Martin Radev1be913c2016-07-11 17:59:16 +03001538 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001539 {
Jamie Madill437fa652016-05-03 15:13:24 -04001540 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001541 return false;
1542 }
1543
1544 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1545 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001546}
Jamie Madillc29968b2016-01-20 11:17:23 -05001547
1548bool ValidateClearBufferiv(ValidationContext *context,
1549 GLenum buffer,
1550 GLint drawbuffer,
1551 const GLint *value)
1552{
1553 switch (buffer)
1554 {
1555 case GL_COLOR:
1556 if (drawbuffer < 0 ||
1557 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001560 return false;
1561 }
Geoff Lang76e65652017-03-27 14:58:02 -04001562 if (context->getExtensions().webglCompatibility)
1563 {
1564 constexpr GLenum validComponentTypes[] = {GL_INT};
1565 if (ValidateWebGLFramebufferAttachmentClearType(
1566 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1567 {
1568 return false;
1569 }
1570 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001571 break;
1572
1573 case GL_STENCIL:
1574 if (drawbuffer != 0)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001577 return false;
1578 }
1579 break;
1580
1581 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001582 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001583 return false;
1584 }
1585
1586 return ValidateClearBuffer(context);
1587}
1588
1589bool ValidateClearBufferuiv(ValidationContext *context,
1590 GLenum buffer,
1591 GLint drawbuffer,
1592 const GLuint *value)
1593{
1594 switch (buffer)
1595 {
1596 case GL_COLOR:
1597 if (drawbuffer < 0 ||
1598 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1599 {
Jamie Madill437fa652016-05-03 15:13:24 -04001600 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001601 return false;
1602 }
Geoff Lang76e65652017-03-27 14:58:02 -04001603 if (context->getExtensions().webglCompatibility)
1604 {
1605 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1606 if (ValidateWebGLFramebufferAttachmentClearType(
1607 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1608 {
1609 return false;
1610 }
1611 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001612 break;
1613
1614 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001616 return false;
1617 }
1618
1619 return ValidateClearBuffer(context);
1620}
1621
1622bool ValidateClearBufferfv(ValidationContext *context,
1623 GLenum buffer,
1624 GLint drawbuffer,
1625 const GLfloat *value)
1626{
1627 switch (buffer)
1628 {
1629 case GL_COLOR:
1630 if (drawbuffer < 0 ||
1631 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1632 {
Jamie Madill437fa652016-05-03 15:13:24 -04001633 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001634 return false;
1635 }
Geoff Lang76e65652017-03-27 14:58:02 -04001636 if (context->getExtensions().webglCompatibility)
1637 {
1638 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1639 GL_SIGNED_NORMALIZED};
1640 if (ValidateWebGLFramebufferAttachmentClearType(
1641 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1642 {
1643 return false;
1644 }
1645 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001646 break;
1647
1648 case GL_DEPTH:
1649 if (drawbuffer != 0)
1650 {
Jamie Madill437fa652016-05-03 15:13:24 -04001651 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001652 return false;
1653 }
1654 break;
1655
1656 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001657 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001658 return false;
1659 }
1660
1661 return ValidateClearBuffer(context);
1662}
1663
1664bool ValidateClearBufferfi(ValidationContext *context,
1665 GLenum buffer,
1666 GLint drawbuffer,
1667 GLfloat depth,
1668 GLint stencil)
1669{
1670 switch (buffer)
1671 {
1672 case GL_DEPTH_STENCIL:
1673 if (drawbuffer != 0)
1674 {
Jamie Madill437fa652016-05-03 15:13:24 -04001675 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001676 return false;
1677 }
1678 break;
1679
1680 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001682 return false;
1683 }
1684
1685 return ValidateClearBuffer(context);
1686}
1687
1688bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1689{
Martin Radev1be913c2016-07-11 17:59:16 +03001690 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001693 return false;
1694 }
1695
1696 return ValidateDrawBuffersBase(context, n, bufs);
1697}
1698
1699bool ValidateCopyTexSubImage3D(Context *context,
1700 GLenum target,
1701 GLint level,
1702 GLint xoffset,
1703 GLint yoffset,
1704 GLint zoffset,
1705 GLint x,
1706 GLint y,
1707 GLsizei width,
1708 GLsizei height)
1709{
Martin Radev1be913c2016-07-11 17:59:16 +03001710 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001711 {
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001713 return false;
1714 }
1715
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001716 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1717 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001718}
1719
Jamie Madill73a84962016-02-12 09:27:23 -05001720bool ValidateTexImage3D(Context *context,
1721 GLenum target,
1722 GLint level,
1723 GLint internalformat,
1724 GLsizei width,
1725 GLsizei height,
1726 GLsizei depth,
1727 GLint border,
1728 GLenum format,
1729 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001730 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001731{
Martin Radev1be913c2016-07-11 17:59:16 +03001732 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001733 {
Jamie Madill437fa652016-05-03 15:13:24 -04001734 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001735 return false;
1736 }
1737
1738 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001739 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001740 pixels);
1741}
1742
Geoff Langc52f6f12016-10-14 10:18:00 -04001743bool ValidateTexImage3DRobustANGLE(Context *context,
1744 GLenum target,
1745 GLint level,
1746 GLint internalformat,
1747 GLsizei width,
1748 GLsizei height,
1749 GLsizei depth,
1750 GLint border,
1751 GLenum format,
1752 GLenum type,
1753 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001754 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001755{
1756 if (context->getClientMajorVersion() < 3)
1757 {
1758 context->handleError(Error(GL_INVALID_OPERATION));
1759 return false;
1760 }
1761
1762 if (!ValidateRobustEntryPoint(context, bufSize))
1763 {
1764 return false;
1765 }
1766
1767 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1768 0, 0, width, height, depth, border, format, type,
1769 bufSize, pixels);
1770}
1771
Jamie Madill73a84962016-02-12 09:27:23 -05001772bool ValidateTexSubImage3D(Context *context,
1773 GLenum target,
1774 GLint level,
1775 GLint xoffset,
1776 GLint yoffset,
1777 GLint zoffset,
1778 GLsizei width,
1779 GLsizei height,
1780 GLsizei depth,
1781 GLenum format,
1782 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001783 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001784{
Martin Radev1be913c2016-07-11 17:59:16 +03001785 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001786 {
Jamie Madill437fa652016-05-03 15:13:24 -04001787 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001788 return false;
1789 }
1790
1791 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1792 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001793 -1, pixels);
1794}
1795
1796bool ValidateTexSubImage3DRobustANGLE(Context *context,
1797 GLenum target,
1798 GLint level,
1799 GLint xoffset,
1800 GLint yoffset,
1801 GLint zoffset,
1802 GLsizei width,
1803 GLsizei height,
1804 GLsizei depth,
1805 GLenum format,
1806 GLenum type,
1807 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001808 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001809{
1810 if (context->getClientMajorVersion() < 3)
1811 {
1812 context->handleError(Error(GL_INVALID_OPERATION));
1813 return false;
1814 }
1815
1816 if (!ValidateRobustEntryPoint(context, bufSize))
1817 {
1818 return false;
1819 }
1820
1821 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1822 yoffset, zoffset, width, height, depth, 0, format, type,
1823 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001824}
1825
1826bool ValidateCompressedTexSubImage3D(Context *context,
1827 GLenum target,
1828 GLint level,
1829 GLint xoffset,
1830 GLint yoffset,
1831 GLint zoffset,
1832 GLsizei width,
1833 GLsizei height,
1834 GLsizei depth,
1835 GLenum format,
1836 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001837 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001838{
Martin Radev1be913c2016-07-11 17:59:16 +03001839 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001840 {
Jamie Madill437fa652016-05-03 15:13:24 -04001841 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001842 return false;
1843 }
1844
Geoff Langca271392017-04-05 12:30:00 -04001845 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001846 if (!formatInfo.compressed)
1847 {
1848 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1849 return false;
1850 }
1851
Jamie Madill513558d2016-06-02 13:04:11 -04001852 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001853 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001854 if (blockSizeOrErr.isError())
1855 {
1856 context->handleError(blockSizeOrErr.getError());
1857 return false;
1858 }
1859 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001862 return false;
1863 }
1864
1865 if (!data)
1866 {
Jamie Madill437fa652016-05-03 15:13:24 -04001867 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001868 return false;
1869 }
1870
1871 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001872 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001873}
Corentin Wallezb2931602017-04-11 15:58:57 -04001874bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1875 GLenum target,
1876 GLint level,
1877 GLint xoffset,
1878 GLint yoffset,
1879 GLint zoffset,
1880 GLsizei width,
1881 GLsizei height,
1882 GLsizei depth,
1883 GLenum format,
1884 GLsizei imageSize,
1885 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001886 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001887{
1888 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1889 {
1890 return false;
1891 }
1892
1893 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1894 height, depth, format, imageSize, data);
1895}
Jamie Madill73a84962016-02-12 09:27:23 -05001896
Olli Etuaho41997e72016-03-10 13:38:39 +02001897bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1898{
1899 return ValidateGenOrDeleteES3(context, n);
1900}
1901
1902bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1903{
1904 return ValidateGenOrDeleteES3(context, n);
1905}
1906
1907bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1908{
1909 return ValidateGenOrDeleteCountES3(context, count);
1910}
1911
1912bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1913{
1914 return ValidateGenOrDeleteCountES3(context, count);
1915}
1916
1917bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1918{
1919 return ValidateGenOrDeleteES3(context, n);
1920}
1921
1922bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1923{
1924 if (!ValidateGenOrDeleteES3(context, n))
1925 {
1926 return false;
1927 }
1928 for (GLint i = 0; i < n; ++i)
1929 {
1930 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1931 if (transformFeedback != nullptr && transformFeedback->isActive())
1932 {
1933 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001935 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1936 return false;
1937 }
1938 }
1939 return true;
1940}
1941
1942bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1943{
1944 return ValidateGenOrDeleteES3(context, n);
1945}
1946
1947bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1948{
1949 return ValidateGenOrDeleteES3(context, n);
1950}
1951
1952bool ValidateGenOrDeleteES3(Context *context, GLint n)
1953{
Martin Radev1be913c2016-07-11 17:59:16 +03001954 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001955 {
Jamie Madill437fa652016-05-03 15:13:24 -04001956 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001957 return false;
1958 }
1959 return ValidateGenOrDelete(context, n);
1960}
1961
1962bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1963{
Martin Radev1be913c2016-07-11 17:59:16 +03001964 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001965 {
Jamie Madill437fa652016-05-03 15:13:24 -04001966 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001967 return false;
1968 }
1969 if (count < 0)
1970 {
Jamie Madill437fa652016-05-03 15:13:24 -04001971 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001972 return false;
1973 }
1974 return true;
1975}
1976
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001977bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1978{
Martin Radev1be913c2016-07-11 17:59:16 +03001979 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001980 {
Jamie Madill437fa652016-05-03 15:13:24 -04001981 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001982 return false;
1983 }
1984 switch (primitiveMode)
1985 {
1986 case GL_TRIANGLES:
1987 case GL_LINES:
1988 case GL_POINTS:
1989 break;
1990
1991 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001992 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001993 return false;
1994 }
1995
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001996 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001997 ASSERT(transformFeedback != nullptr);
1998
1999 if (transformFeedback->isActive())
2000 {
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002002 return false;
2003 }
2004 return true;
2005}
2006
Jamie Madill876429b2017-04-20 15:46:24 -04002007bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002008{
Geoff Lang496c02d2016-10-20 11:38:11 -07002009 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2010}
2011
2012bool ValidateGetBufferPointervRobustANGLE(Context *context,
2013 GLenum target,
2014 GLenum pname,
2015 GLsizei bufSize,
2016 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002017 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002018{
2019 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002020 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002021 return false;
2022 }
2023
Geoff Lang496c02d2016-10-20 11:38:11 -07002024 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2025 {
2026 return false;
2027 }
2028
2029 if (!ValidateRobustBufferSize(context, bufSize, *length))
2030 {
2031 return false;
2032 }
2033
2034 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002035}
2036
2037bool ValidateUnmapBuffer(Context *context, GLenum target)
2038{
Martin Radev1be913c2016-07-11 17:59:16 +03002039 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002040 {
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002042 return false;
2043 }
2044
2045 return ValidateUnmapBufferBase(context, target);
2046}
2047
2048bool ValidateMapBufferRange(Context *context,
2049 GLenum target,
2050 GLintptr offset,
2051 GLsizeiptr length,
2052 GLbitfield access)
2053{
Martin Radev1be913c2016-07-11 17:59:16 +03002054 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002057 return false;
2058 }
2059
2060 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2061}
2062
2063bool ValidateFlushMappedBufferRange(Context *context,
2064 GLenum target,
2065 GLintptr offset,
2066 GLsizeiptr length)
2067{
Martin Radev1be913c2016-07-11 17:59:16 +03002068 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002069 {
Jamie Madill437fa652016-05-03 15:13:24 -04002070 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002071 return false;
2072 }
2073
2074 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2075}
2076
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002077bool ValidateIndexedStateQuery(ValidationContext *context,
2078 GLenum pname,
2079 GLuint index,
2080 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002081{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002082 if (length)
2083 {
2084 *length = 0;
2085 }
2086
Martin Radev66fb8202016-07-28 11:45:20 +03002087 GLenum nativeType;
2088 unsigned int numParams;
2089 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2090 {
2091 context->handleError(Error(GL_INVALID_ENUM));
2092 return false;
2093 }
2094
2095 const Caps &caps = context->getCaps();
2096 switch (pname)
2097 {
2098 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2099 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2100 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2101 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2102 {
2103 context->handleError(Error(GL_INVALID_VALUE));
2104 return false;
2105 }
2106 break;
2107
2108 case GL_UNIFORM_BUFFER_START:
2109 case GL_UNIFORM_BUFFER_SIZE:
2110 case GL_UNIFORM_BUFFER_BINDING:
2111 if (index >= caps.maxUniformBufferBindings)
2112 {
2113 context->handleError(Error(GL_INVALID_VALUE));
2114 return false;
2115 }
2116 break;
Shao80957d92017-02-20 21:25:59 +08002117
Martin Radev66fb8202016-07-28 11:45:20 +03002118 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2119 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2120 if (index >= 3u)
2121 {
2122 context->handleError(Error(GL_INVALID_VALUE));
2123 return false;
2124 }
2125 break;
Shao80957d92017-02-20 21:25:59 +08002126
Jiajia Qin6eafb042016-12-27 17:04:07 +08002127 case GL_ATOMIC_COUNTER_BUFFER_START:
2128 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2129 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2130 if (context->getClientVersion() < ES_3_1)
2131 {
2132 context->handleError(
2133 Error(GL_INVALID_ENUM,
2134 "Atomic Counter buffers are not supported in this version of GL"));
2135 return false;
2136 }
2137 if (index >= caps.maxAtomicCounterBufferBindings)
2138 {
2139 context->handleError(
2140 Error(GL_INVALID_VALUE,
2141 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2142 return false;
2143 }
2144 break;
Shao80957d92017-02-20 21:25:59 +08002145
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002146 case GL_SHADER_STORAGE_BUFFER_START:
2147 case GL_SHADER_STORAGE_BUFFER_SIZE:
2148 case GL_SHADER_STORAGE_BUFFER_BINDING:
2149 if (context->getClientVersion() < ES_3_1)
2150 {
2151 context->handleError(
2152 Error(GL_INVALID_ENUM,
2153 "Shader storage buffers are not supported in this version of GL"));
2154 return false;
2155 }
2156 if (index >= caps.maxShaderStorageBufferBindings)
2157 {
2158 context->handleError(
2159 Error(GL_INVALID_VALUE,
2160 "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
2161 return false;
2162 }
2163 break;
2164
Shao80957d92017-02-20 21:25:59 +08002165 case GL_VERTEX_BINDING_BUFFER:
2166 case GL_VERTEX_BINDING_DIVISOR:
2167 case GL_VERTEX_BINDING_OFFSET:
2168 case GL_VERTEX_BINDING_STRIDE:
2169 if (context->getClientVersion() < ES_3_1)
2170 {
2171 context->handleError(
2172 Error(GL_INVALID_ENUM,
2173 "Vertex Attrib Bindings are not supported in this version of GL"));
2174 return false;
2175 }
2176 if (index >= caps.maxVertexAttribBindings)
2177 {
2178 context->handleError(
2179 Error(GL_INVALID_VALUE,
2180 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2181 return false;
2182 }
2183 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002184 default:
2185 context->handleError(Error(GL_INVALID_ENUM));
2186 return false;
2187 }
2188
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002189 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002190 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002191 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002192 }
2193
2194 return true;
2195}
2196
2197bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2198{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002199 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002200 {
2201 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2202 return false;
2203 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002204 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002205}
2206
Geoff Langcf255ea2016-10-20 11:39:09 -07002207bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2208 GLenum target,
2209 GLuint index,
2210 GLsizei bufSize,
2211 GLsizei *length,
2212 GLint *data)
2213{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002214 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002215 {
2216 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2217 return false;
2218 }
2219
2220 if (!ValidateRobustEntryPoint(context, bufSize))
2221 {
2222 return false;
2223 }
2224
2225 if (!ValidateIndexedStateQuery(context, target, index, length))
2226 {
2227 return false;
2228 }
2229
2230 if (!ValidateRobustBufferSize(context, bufSize, *length))
2231 {
2232 return false;
2233 }
2234
2235 return true;
2236}
2237
Martin Radev66fb8202016-07-28 11:45:20 +03002238bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2239{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002240 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002241 {
2242 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2243 return false;
2244 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002245 return ValidateIndexedStateQuery(context, target, index, nullptr);
2246}
2247
2248bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2249 GLenum target,
2250 GLuint index,
2251 GLsizei bufSize,
2252 GLsizei *length,
2253 GLint64 *data)
2254{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002255 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002256 {
2257 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2258 return false;
2259 }
2260
2261 if (!ValidateRobustEntryPoint(context, bufSize))
2262 {
2263 return false;
2264 }
2265
2266 if (!ValidateIndexedStateQuery(context, target, index, length))
2267 {
2268 return false;
2269 }
2270
2271 if (!ValidateRobustBufferSize(context, bufSize, *length))
2272 {
2273 return false;
2274 }
2275
2276 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002277}
2278
Jamie Madillb0817d12016-11-01 15:48:31 -04002279bool ValidateCopyBufferSubData(ValidationContext *context,
2280 GLenum readTarget,
2281 GLenum writeTarget,
2282 GLintptr readOffset,
2283 GLintptr writeOffset,
2284 GLsizeiptr size)
2285{
2286 if (context->getClientMajorVersion() < 3)
2287 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002288 context->handleError(
2289 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002290 return false;
2291 }
2292
2293 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2294 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002295 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002296 return false;
2297 }
2298
2299 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2300 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2301
2302 if (!readBuffer || !writeBuffer)
2303 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002304 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002305 return false;
2306 }
2307
2308 // Verify that readBuffer and writeBuffer are not currently mapped
2309 if (readBuffer->isMapped() || writeBuffer->isMapped())
2310 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002311 context->handleError(
2312 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002313 return false;
2314 }
2315
Jamie Madilld2f0c742016-11-02 10:34:41 -04002316 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2317 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2318 CheckedNumeric<GLintptr> checkedSize(size);
2319
2320 auto checkedReadSum = checkedReadOffset + checkedSize;
2321 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2322
2323 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2324 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2325 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002326 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002327 context->handleError(
2328 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002329 return false;
2330 }
2331
Jamie Madilld2f0c742016-11-02 10:34:41 -04002332 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002333 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002334 context->handleError(
2335 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002336 return false;
2337 }
2338
Jamie Madilld2f0c742016-11-02 10:34:41 -04002339 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2340 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2341 {
2342 context->handleError(
2343 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2344 return false;
2345 }
2346
2347 if (readBuffer == writeBuffer)
2348 {
2349 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2350 if (!checkedOffsetDiff.IsValid())
2351 {
2352 // This shold not be possible.
2353 UNREACHABLE();
2354 context->handleError(
2355 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2356 return false;
2357 }
2358
2359 if (checkedOffsetDiff.ValueOrDie() < size)
2360 {
2361 context->handleError(Error(GL_INVALID_VALUE));
2362 return false;
2363 }
2364 }
2365
Jamie Madillb0817d12016-11-01 15:48:31 -04002366 return true;
2367}
2368
Geoff Langc339c4e2016-11-29 10:37:36 -05002369bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2370{
2371 if (context->getClientMajorVersion() < 3)
2372 {
2373 context->handleError(
2374 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2375 return false;
2376 }
2377
2378 switch (name)
2379 {
2380 case GL_EXTENSIONS:
2381 if (index >= context->getExtensionStringCount())
2382 {
2383 context->handleError(Error(
2384 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2385 return false;
2386 }
2387 break;
2388
2389 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2390 if (!context->getExtensions().requestExtension)
2391 {
2392 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2393 return false;
2394 }
2395 if (index >= context->getRequestableExtensionStringCount())
2396 {
2397 context->handleError(
2398 Error(GL_INVALID_VALUE,
2399 "index must be less than the number of requestable extension strings."));
2400 return false;
2401 }
2402 break;
2403
2404 default:
2405 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2406 return false;
2407 }
2408
2409 return true;
2410}
2411
Jamie Madille8fb6402017-02-14 17:56:40 -05002412bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2413 GLenum target,
2414 GLsizei samples,
2415 GLenum internalformat,
2416 GLsizei width,
2417 GLsizei height)
2418{
2419 if (context->getClientMajorVersion() < 3)
2420 {
2421 context->handleError(Error(GL_INVALID_OPERATION));
2422 return false;
2423 }
2424
2425 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2426 height))
2427 {
2428 return false;
2429 }
2430
2431 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2432 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002433 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002434 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2435 samples > 0)
2436 {
2437 context->handleError(Error(GL_INVALID_OPERATION));
2438 return false;
2439 }
2440
2441 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2442 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2443 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2444 {
2445 context->handleError(
2446 Error(GL_INVALID_OPERATION,
2447 "Samples must not be greater than maximum supported value for the format."));
2448 return false;
2449 }
2450
2451 return true;
2452}
2453
Geoff Langaa086d62017-03-23 16:47:21 -04002454bool ValidateVertexAttribIPointer(ValidationContext *context,
2455 GLuint index,
2456 GLint size,
2457 GLenum type,
2458 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002459 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002460{
2461 if (context->getClientMajorVersion() < 3)
2462 {
Geoff Langaa086d62017-03-23 16:47:21 -04002463 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002464 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002465 return false;
2466 }
2467
Shao80957d92017-02-20 21:25:59 +08002468 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002469 {
Geoff Langaa086d62017-03-23 16:47:21 -04002470 return false;
2471 }
2472
Geoff Langaa086d62017-03-23 16:47:21 -04002473 if (stride < 0)
2474 {
Shao80957d92017-02-20 21:25:59 +08002475 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002476 return false;
2477 }
2478
Shao80957d92017-02-20 21:25:59 +08002479 const Caps &caps = context->getCaps();
2480 if (context->getClientVersion() >= ES_3_1)
2481 {
2482 if (stride > caps.maxVertexAttribStride)
2483 {
2484 context->handleError(
2485 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2486 return false;
2487 }
2488
2489 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2490 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2491 // validation should be inherited.
2492 if (index >= caps.maxVertexAttribBindings)
2493 {
2494 context->handleError(
2495 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2496 return false;
2497 }
2498 }
2499
Geoff Langaa086d62017-03-23 16:47:21 -04002500 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2501 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2502 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2503 // and the pointer argument is not NULL.
2504 if (context->getGLState().getVertexArrayId() != 0 &&
2505 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2506 {
2507 context->handleError(
2508 Error(GL_INVALID_OPERATION,
2509 "Client data cannot be used with a non-default vertex array object."));
2510 return false;
2511 }
2512
Geoff Lang2d62ab72017-03-23 16:54:40 -04002513 if (context->getExtensions().webglCompatibility)
2514 {
2515 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2516 {
2517 return false;
2518 }
2519 }
2520
Geoff Langaa086d62017-03-23 16:47:21 -04002521 return true;
2522}
2523
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002524bool ValidateGetSynciv(Context *context,
2525 GLsync sync,
2526 GLenum pname,
2527 GLsizei bufSize,
2528 GLsizei *length,
2529 GLint *values)
2530{
2531 if (context->getClientMajorVersion() < 3)
2532 {
2533 context->handleError(
2534 Error(GL_INVALID_OPERATION, "GetSynciv requires OpenGL ES 3.0 or higher."));
2535 return false;
2536 }
2537
2538 if (bufSize < 0)
2539 {
2540 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
2541 return false;
2542 }
2543
2544 FenceSync *fenceSync = context->getFenceSync(sync);
2545 if (!fenceSync)
2546 {
2547 context->handleError(Error(GL_INVALID_VALUE, "Invalid sync object."));
2548 return false;
2549 }
2550
2551 switch (pname)
2552 {
2553 case GL_OBJECT_TYPE:
2554 case GL_SYNC_CONDITION:
2555 case GL_SYNC_FLAGS:
2556 case GL_SYNC_STATUS:
2557 break;
2558
2559 default:
2560 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
2561 return false;
2562 }
2563
2564 return true;
2565}
2566
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002567bool ValidateDrawElementsInstanced(ValidationContext *context,
2568 GLenum mode,
2569 GLsizei count,
2570 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002571 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002572 GLsizei instanceCount)
2573{
2574 if (context->getClientMajorVersion() < 3)
2575 {
2576 context->handleError(Error(GL_INVALID_OPERATION, "Requires a GLES 3.0 or higher context."));
2577 return false;
2578 }
2579
2580 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2581}
2582
Jamie Madillc29968b2016-01-20 11:17:23 -05002583} // namespace gl