blob: 207b44cfee8d84deb61fc8d1ec8125f8866189ee [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/validationES.h"
15#include "libANGLE/Context.h"
16#include "libANGLE/Texture.h"
17#include "libANGLE/Framebuffer.h"
18#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/FramebufferAttachment.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
Jamie Madill55e98212016-10-05 16:39:13 -040035 if (!ValidES3Format(format) || !ValidES3Type(type))
Geoff Lang5d601382014-07-22 15:14:06 -040036 {
Jamie Madill437fa652016-05-03 15:13:24 -040037 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -040038 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040039 }
40
Geoff Langca271392017-04-05 12:30:00 -040041 // From the ES 3.0 spec section 3.8.3:
42 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
43 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
44 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
45 // INVALID_OPERATION error.
46 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
47 {
48 context->handleError(Error(
49 GL_INVALID_OPERATION,
50 "Format cannot be GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL if target is GL_TEXTURE_3D"));
51 return false;
52 }
53
54 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
55 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
56 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
57 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
58 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
59 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
60 {
61 context->handleError(Error(GL_INVALID_VALUE));
62 return false;
63 }
64
Geoff Lang5d601382014-07-22 15:14:06 -040065 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040066 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040067 {
Jamie Madill437fa652016-05-03 15:13:24 -040068 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -040069 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040070 }
71
72 return true;
73}
74
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050075bool ValidateES3TexImageParametersBase(Context *context,
76 GLenum target,
77 GLint level,
78 GLenum internalformat,
79 bool isCompressed,
80 bool isSubImage,
81 GLint xoffset,
82 GLint yoffset,
83 GLint zoffset,
84 GLsizei width,
85 GLsizei height,
86 GLsizei depth,
87 GLint border,
88 GLenum format,
89 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -040090 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050091 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040092{
93 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -070094 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040095 {
Jamie Madill437fa652016-05-03 15:13:24 -040096 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040098 }
99
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400100 // Verify zero border
101 if (border != 0)
102 {
Jamie Madill437fa652016-05-03 15:13:24 -0400103 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400104 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400105 }
106
Jamie Madill6f38f822014-06-06 17:12:20 -0400107 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
108 std::numeric_limits<GLsizei>::max() - xoffset < width ||
109 std::numeric_limits<GLsizei>::max() - yoffset < height ||
110 std::numeric_limits<GLsizei>::max() - zoffset < depth)
111 {
Jamie Madill437fa652016-05-03 15:13:24 -0400112 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400113 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400114 }
115
Geoff Langaae65a42014-05-26 12:43:44 -0400116 const gl::Caps &caps = context->getCaps();
117
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 switch (target)
119 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800120 case GL_TEXTURE_2D:
121 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
122 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
123 {
124 context->handleError(Error(GL_INVALID_VALUE));
125 return false;
126 }
127 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400128
He Yunchaoced53ae2016-11-29 15:00:51 +0800129 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
130 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
131 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
132 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
133 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
134 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
135 if (!isSubImage && width != height)
136 {
137 context->handleError(Error(GL_INVALID_VALUE));
138 return false;
139 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400140
He Yunchaoced53ae2016-11-29 15:00:51 +0800141 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
142 {
143 context->handleError(Error(GL_INVALID_VALUE));
144 return false;
145 }
146 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400147
He Yunchaoced53ae2016-11-29 15:00:51 +0800148 case GL_TEXTURE_3D:
149 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
150 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
151 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
152 {
153 context->handleError(Error(GL_INVALID_VALUE));
154 return false;
155 }
156 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400157
He Yunchaoced53ae2016-11-29 15:00:51 +0800158 case GL_TEXTURE_2D_ARRAY:
159 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
160 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
161 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
162 {
163 context->handleError(Error(GL_INVALID_VALUE));
164 return false;
165 }
166 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400167
He Yunchaoced53ae2016-11-29 15:00:51 +0800168 default:
169 context->handleError(Error(GL_INVALID_ENUM));
170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400171 }
172
He Yunchaoced53ae2016-11-29 15:00:51 +0800173 gl::Texture *texture =
174 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400175 if (!texture)
176 {
Jamie Madill437fa652016-05-03 15:13:24 -0400177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400179 }
180
Geoff Lang69cce582015-09-17 13:20:36 -0400181 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 {
Jamie Madill437fa652016-05-03 15:13:24 -0400183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400184 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400185 }
186
187 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400188 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400189 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500190 if (isSubImage && actualInternalFormat == GL_NONE)
191 {
192 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
193 return false;
194 }
195
Geoff Langca271392017-04-05 12:30:00 -0400196 const gl::InternalFormat &actualFormatInfo =
197 gl::GetSizedInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 if (isCompressed)
199 {
tmartino7c102692015-10-02 16:43:40 -0400200 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400201 {
Jamie Madill437fa652016-05-03 15:13:24 -0400202 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400203 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400204 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400205 }
206
Geoff Langca271392017-04-05 12:30:00 -0400207 if (!ValidCompressedImageSize(context, actualFormatInfo.internalFormat, xoffset, yoffset,
208 width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400209 {
Jamie Madill437fa652016-05-03 15:13:24 -0400210 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400211 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400212 }
213
Geoff Langeb66a6e2016-10-31 13:06:12 -0400214 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400215 {
Jamie Madill437fa652016-05-03 15:13:24 -0400216 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400217 return false;
218 }
219
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 if (target == GL_TEXTURE_3D)
221 {
Jamie Madill437fa652016-05-03 15:13:24 -0400222 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400223 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400224 }
225 }
226 else
227 {
Geoff Langca271392017-04-05 12:30:00 -0400228 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400229 {
Geoff Lang5d601382014-07-22 15:14:06 -0400230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400231 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
234 // Validate sub image parameters
235 if (isSubImage)
236 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500237 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400238 {
Jamie Madill437fa652016-05-03 15:13:24 -0400239 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400241 }
242
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 if (width == 0 || height == 0 || depth == 0)
244 {
245 return false;
246 }
247
248 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
249 {
Jamie Madill437fa652016-05-03 15:13:24 -0400250 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400251 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400252 }
253
254 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
255 std::numeric_limits<GLsizei>::max() - yoffset < height ||
256 std::numeric_limits<GLsizei>::max() - zoffset < depth)
257 {
Jamie Madill437fa652016-05-03 15:13:24 -0400258 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400260 }
261
Geoff Langa9be0dc2014-12-17 12:34:40 -0500262 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
263 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
264 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400265 {
Jamie Madill437fa652016-05-03 15:13:24 -0400266 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400268 }
269 }
270
Geoff Langff5b2d52016-09-07 11:32:23 -0400271 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
272 imageSize))
273 {
274 return false;
275 }
276
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400277 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700278 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400279 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400280 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800281 // ...data is not evenly divisible into the number of bytes needed to store in memory a
282 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400283 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400284 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400285 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400286 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400287 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
288
Geoff Langff5b2d52016-09-07 11:32:23 -0400289 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400290 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400291 context->handleError(
292 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400293 return false;
294 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400295 }
296
Jamie Madill7a5f7382014-03-05 15:01:24 -0500297 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700298 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500299 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400300 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400301 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500302 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400303 }
304
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305 return true;
306}
307
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500308bool ValidateES3TexImage2DParameters(Context *context,
309 GLenum target,
310 GLint level,
311 GLenum internalformat,
312 bool isCompressed,
313 bool isSubImage,
314 GLint xoffset,
315 GLint yoffset,
316 GLint zoffset,
317 GLsizei width,
318 GLsizei height,
319 GLsizei depth,
320 GLint border,
321 GLenum format,
322 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400323 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500324 const GLvoid *pixels)
325{
326 if (!ValidTexture2DDestinationTarget(context, target))
327 {
Jamie Madill437fa652016-05-03 15:13:24 -0400328 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500329 return false;
330 }
331
332 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
333 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400334 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500335}
336
337bool ValidateES3TexImage3DParameters(Context *context,
338 GLenum target,
339 GLint level,
340 GLenum internalformat,
341 bool isCompressed,
342 bool isSubImage,
343 GLint xoffset,
344 GLint yoffset,
345 GLint zoffset,
346 GLsizei width,
347 GLsizei height,
348 GLsizei depth,
349 GLint border,
350 GLenum format,
351 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400352 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500353 const GLvoid *pixels)
354{
355 if (!ValidTexture3DDestinationTarget(context, target))
356 {
Jamie Madill437fa652016-05-03 15:13:24 -0400357 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500358 return false;
359 }
360
361 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
362 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400363 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500364}
365
Geoff Lang5d601382014-07-22 15:14:06 -0400366struct EffectiveInternalFormatInfo
367{
Jamie Madill76648fe2016-10-05 17:01:41 -0400368 GLenum effectiveFormat;
369 GLenum destFormat;
370 GLuint minRedBits;
371 GLuint maxRedBits;
372 GLuint minGreenBits;
373 GLuint maxGreenBits;
374 GLuint minBlueBits;
375 GLuint maxBlueBits;
376 GLuint minAlphaBits;
377 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400378};
379
Jamie Madill76648fe2016-10-05 17:01:41 -0400380static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
381 GLenum targetFormat,
382 const EffectiveInternalFormatInfo *list,
383 size_t size,
384 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400385{
Jamie Madill76648fe2016-10-05 17:01:41 -0400386 for (size_t curFormat = 0; curFormat < size; ++curFormat)
387 {
388 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
389 if ((formatInfo.destFormat == targetFormat) &&
390 (formatInfo.minRedBits <= srcFormat.redBits &&
391 formatInfo.maxRedBits >= srcFormat.redBits) &&
392 (formatInfo.minGreenBits <= srcFormat.greenBits &&
393 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
394 (formatInfo.minBlueBits <= srcFormat.blueBits &&
395 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
396 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
397 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
398 {
399 *outEffectiveFormat = formatInfo.effectiveFormat;
400 return true;
401 }
402 }
Geoff Lang5d601382014-07-22 15:14:06 -0400403
Jamie Madill76648fe2016-10-05 17:01:41 -0400404 *outEffectiveFormat = GL_NONE;
405 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400406}
407
Jamie Madill76648fe2016-10-05 17:01:41 -0400408bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
409 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400410{
Jamie Madill76648fe2016-10-05 17:01:41 -0400411 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
412 // Effective internal format coresponding to destination internal format and linear source
413 // buffer component sizes.
414 // | Source channel min/max sizes |
415 // Effective Internal Format | N/A | R | G | B | A |
416 // clang-format off
417 constexpr EffectiveInternalFormatInfo list[] = {
418 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
419 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
420 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
421 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
422 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
423 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
424 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
425 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
426 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
427 };
428 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400429
Jamie Madill76648fe2016-10-05 17:01:41 -0400430 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
431}
Geoff Lang5d601382014-07-22 15:14:06 -0400432
Jamie Madill76648fe2016-10-05 17:01:41 -0400433bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
434 const InternalFormat &destFormat,
435 GLenum *outEffectiveFormat)
436{
437 constexpr GLuint umax = UINT_MAX;
438
439 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
440 // Effective internal format coresponding to destination internal format andlinear source buffer
441 // component sizes.
442 // | Source channel min/max sizes |
443 // Effective Internal Format | Dest Format | R | G | B | A |
444 // clang-format off
445 constexpr EffectiveInternalFormatInfo list[] = {
446 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
447 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
448 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
449 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
450 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
451 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
452 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
453 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
454 };
455 // clang-format on
456
457 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
458 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400459}
460
He Yunchaoced53ae2016-11-29 15:00:51 +0800461static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
462 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400463 GLenum *outEffectiveFormat)
464{
Geoff Langca271392017-04-05 12:30:00 -0400465 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400466 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400467 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400468 }
469 else
470 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400471 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400472 }
Geoff Lang5d601382014-07-22 15:14:06 -0400473}
474
Corentin Wallez76287682016-04-25 09:23:38 -0400475static bool EqualOrFirstZero(GLuint first, GLuint second)
476{
477 return first == 0 || first == second;
478}
479
Geoff Langca271392017-04-05 12:30:00 -0400480static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
481 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400482 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400483{
Jamie Madill21b786b2016-11-01 17:41:31 -0400484 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400485 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400486 return false;
487 }
Geoff Lang5d601382014-07-22 15:14:06 -0400488
Jamie Madill21b786b2016-11-01 17:41:31 -0400489 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
490 // must both be signed, unsigned, or fixed point and both source and destinations
491 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
492 // conversion between fixed and floating point.
493
494 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
495 (framebufferFormatInfo.colorEncoding == GL_SRGB))
496 {
497 return false;
498 }
499
500 if (((textureFormatInfo.componentType == GL_INT) !=
501 (framebufferFormatInfo.componentType == GL_INT)) ||
502 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
503 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
504 {
505 return false;
506 }
507
508 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
509 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
510 textureFormatInfo.componentType == GL_FLOAT) &&
511 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
512 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
513 framebufferFormatInfo.componentType == GL_FLOAT))
514 {
515 return false;
516 }
517
518 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
519 // The effective internal format of the source buffer is determined with the following rules
520 // applied in order:
521 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
522 // format then the effective internal format is the source buffer's sized internal format.
523 // * If the source buffer is a texture that was created with an unsized base internal format,
524 // then the effective internal format is the source image array's effective internal
525 // format, as specified by table 3.12, which is determined from the <format> and <type>
526 // that were used when the source image array was specified by TexImage*.
527 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
528 // where Destination Internal Format matches internalformat and where the [source channel
529 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
530 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
531 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
532 const InternalFormat *sourceEffectiveFormat = NULL;
533 if (readBufferHandle != 0)
534 {
535 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
536 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400537 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400538 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400539 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400540 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400541 else
Geoff Lang5d601382014-07-22 15:14:06 -0400542 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400543 // Renderbuffers cannot be created with an unsized internal format, so this must be an
544 // unsized-format texture. We can use the same table we use when creating textures to
545 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400546 sourceEffectiveFormat =
547 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400548 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400549 }
550 else
551 {
552 // The effective internal format must be derived from the source framebuffer's channel
553 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
554 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400555 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400556 GLenum effectiveFormat;
557 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
558 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400559 {
Geoff Langca271392017-04-05 12:30:00 -0400560 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400561 }
562 else
563 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400564 return false;
565 }
566 }
567 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
568 {
569 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400570 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400571 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
572 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
573 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
574 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
575 {
Geoff Langca271392017-04-05 12:30:00 -0400576 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400577 }
578 else
579 {
580 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400581 }
582 }
583 else
584 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400585 UNREACHABLE();
586 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400587 }
Geoff Lang5d601382014-07-22 15:14:06 -0400588 }
589
Geoff Langca271392017-04-05 12:30:00 -0400590 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400591 {
592 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
593 // sized, component sizes of the source and destination formats must exactly match if the
594 // destination format exists.
595 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
596 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
597 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
598 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
599 {
600 return false;
601 }
602 }
603
604 return true; // A conversion function exists, and no rule in the specification has precluded
605 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400606}
607
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500608bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
609 GLenum target,
610 GLint level,
611 GLenum internalformat,
612 bool isSubImage,
613 GLint xoffset,
614 GLint yoffset,
615 GLint zoffset,
616 GLint x,
617 GLint y,
618 GLsizei width,
619 GLsizei height,
620 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400621{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400622 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400623 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400624 xoffset, yoffset, zoffset, x, y, width, height, border,
625 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400626 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400627 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400628 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400629 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400630
Jamie Madill51f40ec2016-06-15 14:06:00 -0400631 const auto &state = context->getGLState();
632 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
633 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400634
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400635 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400636 {
Jamie Madill437fa652016-05-03 15:13:24 -0400637 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400638 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400639 }
640
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400641 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400642 {
Jamie Madill437fa652016-05-03 15:13:24 -0400643 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400644 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400645 }
646
Jamie Madill0c8abca2016-07-22 20:21:26 -0400647 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400648
649 if (isSubImage)
650 {
Geoff Langca271392017-04-05 12:30:00 -0400651 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500652 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400653 {
Jamie Madill437fa652016-05-03 15:13:24 -0400654 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 }
657 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400658 else
659 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400660 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400661 const InternalFormat &framebufferFormat = *source->getFormat().info;
662 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400663 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400664 {
Jamie Madill437fa652016-05-03 15:13:24 -0400665 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400666 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400667 }
668 }
669
Geoff Lang784a8fd2013-09-24 12:33:16 -0400670 // If width or height is zero, it is a no-op. Return false without setting an error.
671 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400672}
673
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500674bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
675 GLenum target,
676 GLint level,
677 GLenum internalformat,
678 bool isSubImage,
679 GLint xoffset,
680 GLint yoffset,
681 GLint zoffset,
682 GLint x,
683 GLint y,
684 GLsizei width,
685 GLsizei height,
686 GLint border)
687{
688 if (!ValidTexture2DDestinationTarget(context, target))
689 {
Jamie Madill437fa652016-05-03 15:13:24 -0400690 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500691 return false;
692 }
693
694 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
695 xoffset, yoffset, zoffset, x, y, width, height,
696 border);
697}
698
699bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
700 GLenum target,
701 GLint level,
702 GLenum internalformat,
703 bool isSubImage,
704 GLint xoffset,
705 GLint yoffset,
706 GLint zoffset,
707 GLint x,
708 GLint y,
709 GLsizei width,
710 GLsizei height,
711 GLint border)
712{
713 if (!ValidTexture3DDestinationTarget(context, target))
714 {
Jamie Madill437fa652016-05-03 15:13:24 -0400715 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500716 return false;
717 }
718
719 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
720 xoffset, yoffset, zoffset, x, y, width, height,
721 border);
722}
723
724bool ValidateES3TexStorageParametersBase(Context *context,
725 GLenum target,
726 GLsizei levels,
727 GLenum internalformat,
728 GLsizei width,
729 GLsizei height,
730 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731{
732 if (width < 1 || height < 1 || depth < 1 || levels < 1)
733 {
Jamie Madill437fa652016-05-03 15:13:24 -0400734 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400735 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400736 }
737
Geoff Langb92c1332015-09-04 12:54:55 -0400738 GLsizei maxDim = std::max(width, height);
739 if (target != GL_TEXTURE_2D_ARRAY)
740 {
741 maxDim = std::max(maxDim, depth);
742 }
743
744 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 {
Jamie Madill437fa652016-05-03 15:13:24 -0400746 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400747 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400748 }
749
Geoff Langaae65a42014-05-26 12:43:44 -0400750 const gl::Caps &caps = context->getCaps();
751
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 switch (target)
753 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800754 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 {
Geoff Langaae65a42014-05-26 12:43:44 -0400756 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
757 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400758 {
Jamie Madill437fa652016-05-03 15:13:24 -0400759 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400760 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 }
762 }
763 break;
764
He Yunchaoced53ae2016-11-29 15:00:51 +0800765 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 if (width != height)
768 {
Jamie Madill437fa652016-05-03 15:13:24 -0400769 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 }
772
Geoff Langaae65a42014-05-26 12:43:44 -0400773 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400774 {
Jamie Madill437fa652016-05-03 15:13:24 -0400775 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400776 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777 }
778 }
779 break;
780
He Yunchaoced53ae2016-11-29 15:00:51 +0800781 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 {
Geoff Langaae65a42014-05-26 12:43:44 -0400783 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
784 static_cast<GLuint>(height) > caps.max3DTextureSize ||
785 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400786 {
Jamie Madill437fa652016-05-03 15:13:24 -0400787 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 }
790 }
791 break;
792
He Yunchaoced53ae2016-11-29 15:00:51 +0800793 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 {
Geoff Langaae65a42014-05-26 12:43:44 -0400795 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
796 static_cast<GLuint>(height) > caps.max2DTextureSize ||
797 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 {
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 }
803 break;
804
He Yunchaoced53ae2016-11-29 15:00:51 +0800805 default:
806 UNREACHABLE();
807 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808 }
809
Geoff Lang691e58c2014-12-19 17:03:25 -0500810 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 if (!texture || texture->id() == 0)
812 {
Jamie Madill437fa652016-05-03 15:13:24 -0400813 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 }
816
Geoff Lang69cce582015-09-17 13:20:36 -0400817 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 {
Jamie Madill437fa652016-05-03 15:13:24 -0400819 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 }
822
Geoff Langca271392017-04-05 12:30:00 -0400823 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400824 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 {
Jamie Madill437fa652016-05-03 15:13:24 -0400826 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 }
829
Geoff Langca271392017-04-05 12:30:00 -0400830 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 {
Jamie Madill437fa652016-05-03 15:13:24 -0400832 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400833 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 }
835
836 return true;
837}
838
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500839bool ValidateES3TexStorage2DParameters(Context *context,
840 GLenum target,
841 GLsizei levels,
842 GLenum internalformat,
843 GLsizei width,
844 GLsizei height,
845 GLsizei depth)
846{
847 if (!ValidTexture2DTarget(context, target))
848 {
Jamie Madill437fa652016-05-03 15:13:24 -0400849 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500850 return false;
851 }
852
853 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
854 height, depth);
855}
856
857bool ValidateES3TexStorage3DParameters(Context *context,
858 GLenum target,
859 GLsizei levels,
860 GLenum internalformat,
861 GLsizei width,
862 GLsizei height,
863 GLsizei depth)
864{
865 if (!ValidTexture3DTarget(context, target))
866 {
Jamie Madill437fa652016-05-03 15:13:24 -0400867 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500868 return false;
869 }
870
871 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
872 height, depth);
873}
874
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500875bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
876{
Martin Radev1be913c2016-07-11 17:59:16 +0300877 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500878 {
Jamie Madill437fa652016-05-03 15:13:24 -0400879 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500880 return false;
881 }
882
883 return ValidateBeginQueryBase(context, target, id);
884}
885
886bool ValidateEndQuery(gl::Context *context, GLenum target)
887{
Martin Radev1be913c2016-07-11 17:59:16 +0300888 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500889 {
Jamie Madill437fa652016-05-03 15:13:24 -0400890 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500891 return false;
892 }
893
894 return ValidateEndQueryBase(context, target);
895}
896
897bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
898{
Martin Radev1be913c2016-07-11 17:59:16 +0300899 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500900 {
Jamie Madill437fa652016-05-03 15:13:24 -0400901 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500902 return false;
903 }
904
Geoff Lang2186c382016-10-14 10:54:54 -0400905 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500906}
907
908bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
909{
Martin Radev1be913c2016-07-11 17:59:16 +0300910 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500911 {
Jamie Madill437fa652016-05-03 15:13:24 -0400912 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500913 return false;
914 }
915
Geoff Lang2186c382016-10-14 10:54:54 -0400916 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500917}
918
He Yunchaoced53ae2016-11-29 15:00:51 +0800919bool ValidateFramebufferTextureLayer(Context *context,
920 GLenum target,
921 GLenum attachment,
922 GLuint texture,
923 GLint level,
924 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400925{
Martin Radev1be913c2016-07-11 17:59:16 +0300926 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400930 }
931
Jamie Madill55ec3b12014-07-03 10:38:57 -0400932 if (layer < 0)
933 {
Jamie Madill437fa652016-05-03 15:13:24 -0400934 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400935 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400936 }
937
938 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
939 {
940 return false;
941 }
942
943 const gl::Caps &caps = context->getCaps();
944 if (texture != 0)
945 {
946 gl::Texture *tex = context->getTexture(texture);
947 ASSERT(tex);
948
949 switch (tex->getTarget())
950 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400952 {
953 if (level > gl::log2(caps.max2DTextureSize))
954 {
Jamie Madill437fa652016-05-03 15:13:24 -0400955 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400956 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400957 }
958
959 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
960 {
Jamie Madill437fa652016-05-03 15:13:24 -0400961 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400963 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400964 }
965 break;
966
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400968 {
969 if (level > gl::log2(caps.max3DTextureSize))
970 {
Jamie Madill437fa652016-05-03 15:13:24 -0400971 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400972 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400973 }
974
975 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
976 {
Jamie Madill437fa652016-05-03 15:13:24 -0400977 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400978 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400979 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400980 }
981 break;
982
He Yunchaoced53ae2016-11-29 15:00:51 +0800983 default:
984 context->handleError(Error(GL_INVALID_OPERATION));
985 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400986 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500987
Jamie Madilla3944d42016-07-22 22:13:26 -0400988 const auto &format = tex->getFormat(tex->getTarget(), level);
989 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500990 {
Jamie Madill437fa652016-05-03 15:13:24 -0400991 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500992 return false;
993 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400994 }
995
996 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -0400997}
998
He Yunchaoced53ae2016-11-29 15:00:51 +0800999bool ValidateInvalidateFramebuffer(Context *context,
1000 GLenum target,
1001 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001002 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003{
Martin Radev1be913c2016-07-11 17:59:16 +03001004 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001005 {
Jamie Madill437fa652016-05-03 15:13:24 -04001006 context->handleError(
1007 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001008 return false;
1009 }
1010
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 bool defaultFramebuffer = false;
1012
1013 switch (target)
1014 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001015 case GL_DRAW_FRAMEBUFFER:
1016 case GL_FRAMEBUFFER:
1017 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1018 break;
1019 case GL_READ_FRAMEBUFFER:
1020 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1021 break;
1022 default:
1023 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1024 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026
He Yunchaoced53ae2016-11-29 15:00:51 +08001027 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1028 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029}
1030
Jamie Madillc29968b2016-01-20 11:17:23 -05001031bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001032{
Martin Radev1be913c2016-07-11 17:59:16 +03001033 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001034 {
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001036 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001037 }
1038
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001039 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001040 {
Jamie Madill437fa652016-05-03 15:13:24 -04001041 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001042 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001043 }
1044
1045 return true;
1046}
1047
Olli Etuaho71dfb362016-03-10 14:04:27 +02001048bool ValidateDrawRangeElements(Context *context,
1049 GLenum mode,
1050 GLuint start,
1051 GLuint end,
1052 GLsizei count,
1053 GLenum type,
1054 const GLvoid *indices,
1055 IndexRange *indexRange)
1056{
Martin Radev1be913c2016-07-11 17:59:16 +03001057 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001060 return false;
1061 }
1062
1063 if (end < start)
1064 {
Jamie Madill437fa652016-05-03 15:13:24 -04001065 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001066 return false;
1067 }
1068
1069 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1070 {
1071 return false;
1072 }
1073
1074 if (indexRange->end > end || indexRange->start < start)
1075 {
1076 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001077 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001078 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1079 return false;
1080 }
1081 return true;
1082}
1083
He Yunchaoced53ae2016-11-29 15:00:51 +08001084bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001085{
Martin Radev1be913c2016-07-11 17:59:16 +03001086 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001090 }
1091
Jamie Madill78f41802014-08-25 15:47:55 -04001092 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001093}
1094
Jamie Madillb885e572015-02-03 16:16:04 -05001095bool ValidateReadBuffer(Context *context, GLenum src)
1096{
Martin Radev1be913c2016-07-11 17:59:16 +03001097 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001098 {
Jamie Madill437fa652016-05-03 15:13:24 -04001099 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001100 return false;
1101 }
1102
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001103 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001104
1105 if (readFBO == nullptr)
1106 {
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001108 return false;
1109 }
1110
1111 if (src == GL_NONE)
1112 {
1113 return true;
1114 }
1115
Olli Etuaho84c9f592016-03-09 14:37:25 +02001116 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001117 {
Jamie Madill437fa652016-05-03 15:13:24 -04001118 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001119 return false;
1120 }
1121
1122 if (readFBO->id() == 0)
1123 {
1124 if (src != GL_BACK)
1125 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 const char *errorMsg =
1127 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001128 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001129 return false;
1130 }
1131 }
1132 else
1133 {
1134 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1135
1136 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1137 {
1138 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001139 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001140 return false;
1141 }
1142 }
1143
1144 return true;
1145}
1146
Jamie Madill86af3d22015-07-21 15:14:07 -04001147bool ValidateCompressedTexImage3D(Context *context,
1148 GLenum target,
1149 GLint level,
1150 GLenum internalformat,
1151 GLsizei width,
1152 GLsizei height,
1153 GLsizei depth,
1154 GLint border,
1155 GLsizei imageSize,
1156 const GLvoid *data)
1157{
Martin Radev1be913c2016-07-11 17:59:16 +03001158 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001159 {
Jamie Madill437fa652016-05-03 15:13:24 -04001160 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001161 return false;
1162 }
1163
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001164 if (!ValidTextureTarget(context, target))
1165 {
1166 context->handleError(Error(GL_INVALID_ENUM));
1167 return false;
1168 }
1169
Jamie Madille2e406c2016-06-02 13:04:10 -04001170 // Validate image size
1171 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1172 {
1173 context->handleError(Error(GL_INVALID_VALUE));
1174 return false;
1175 }
1176
Geoff Langca271392017-04-05 12:30:00 -04001177 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001178 if (!formatInfo.compressed)
1179 {
1180 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1181 return false;
1182 }
1183
Jamie Madill513558d2016-06-02 13:04:11 -04001184 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001185 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001186 if (blockSizeOrErr.isError())
1187 {
Jamie Madill513558d2016-06-02 13:04:11 -04001188 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001189 return false;
1190 }
1191 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001192 {
Jamie Madill437fa652016-05-03 15:13:24 -04001193 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001194 return false;
1195 }
1196
1197 // 3D texture target validation
1198 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1199 {
Jamie Madill437fa652016-05-03 15:13:24 -04001200 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001201 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1202 return false;
1203 }
1204
1205 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001206 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001207 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1208 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001209 {
1210 return false;
1211 }
1212
1213 return true;
1214}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001215
Corentin Wallezb2931602017-04-11 15:58:57 -04001216bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1217 GLenum target,
1218 GLint level,
1219 GLenum internalformat,
1220 GLsizei width,
1221 GLsizei height,
1222 GLsizei depth,
1223 GLint border,
1224 GLsizei imageSize,
1225 GLsizei dataSize,
1226 const GLvoid *data)
1227{
1228 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1229 {
1230 return false;
1231 }
1232
1233 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1234 depth, border, imageSize, data);
1235}
1236
Austin Kinrossbc781f32015-10-26 09:27:38 -07001237bool ValidateBindVertexArray(Context *context, GLuint array)
1238{
Martin Radev1be913c2016-07-11 17:59:16 +03001239 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001242 return false;
1243 }
1244
1245 return ValidateBindVertexArrayBase(context, array);
1246}
1247
Austin Kinrossbc781f32015-10-26 09:27:38 -07001248bool ValidateIsVertexArray(Context *context)
1249{
Martin Radev1be913c2016-07-11 17:59:16 +03001250 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253 return false;
1254 }
1255
1256 return true;
1257}
Geoff Langc5629752015-12-07 16:29:04 -05001258
Jiajia Qin6eafb042016-12-27 17:04:07 +08001259static bool ValidateBindBufferCommon(Context *context,
1260 GLenum target,
1261 GLuint index,
1262 GLuint buffer,
1263 GLintptr offset,
1264 GLsizeiptr size)
1265{
1266 if (context->getClientMajorVersion() < 3)
1267 {
1268 context->handleError(Error(GL_INVALID_OPERATION));
1269 return false;
1270 }
1271
1272 if (buffer != 0 && offset < 0)
1273 {
1274 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1275 return false;
1276 }
1277
1278 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1279 !context->isBufferGenerated(buffer))
1280 {
1281 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1282 return false;
1283 }
1284
1285 const Caps &caps = context->getCaps();
1286 switch (target)
1287 {
1288 case GL_TRANSFORM_FEEDBACK_BUFFER:
1289 {
1290 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1291 {
1292 context->handleError(Error(GL_INVALID_VALUE,
1293 "index is greater than or equal to the number of "
1294 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1295 return false;
1296 }
1297 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1298 {
1299 context->handleError(
1300 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1301 return false;
1302 }
1303
1304 TransformFeedback *curTransformFeedback =
1305 context->getGLState().getCurrentTransformFeedback();
1306 if (curTransformFeedback && curTransformFeedback->isActive())
1307 {
1308 context->handleError(Error(GL_INVALID_OPERATION,
1309 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1310 "feedback is currently active."));
1311 return false;
1312 }
1313 break;
1314 }
1315 case GL_UNIFORM_BUFFER:
1316 {
1317 if (index >= caps.maxUniformBufferBindings)
1318 {
1319 context->handleError(Error(GL_INVALID_VALUE,
1320 "index is greater than or equal to the number of "
1321 "UNIFORM_BUFFER indexed binding points."));
1322 return false;
1323 }
1324
1325 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1326 {
1327 context->handleError(
1328 Error(GL_INVALID_VALUE,
1329 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1330 return false;
1331 }
1332 break;
1333 }
1334 case GL_ATOMIC_COUNTER_BUFFER:
1335 {
1336 if (context->getClientVersion() < ES_3_1)
1337 {
Yunchao He61afff12017-03-14 15:34:03 +08001338 context->handleError(Error(
1339 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001340 return false;
1341 }
1342 if (index >= caps.maxAtomicCounterBufferBindings)
1343 {
1344 context->handleError(Error(GL_INVALID_VALUE,
1345 "index is greater than or equal to the number of "
1346 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1347 return false;
1348 }
1349 if (buffer != 0 && (offset % 4) != 0)
1350 {
1351 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1352 return false;
1353 }
1354 break;
1355 }
1356 case GL_SHADER_STORAGE_BUFFER:
1357 {
1358 if (context->getClientVersion() < ES_3_1)
1359 {
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001360 context->handleError(
1361 Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
1362 return false;
1363 }
1364 if (index >= caps.maxShaderStorageBufferBindings)
1365 {
1366 context->handleError(Error(GL_INVALID_VALUE,
1367 "index is greater than or equal to the number of "
1368 "SHADER_STORAGE_BUFFER indexed binding points."));
1369 return false;
1370 }
1371 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1372 {
Yunchao He61afff12017-03-14 15:34:03 +08001373 context->handleError(Error(
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001374 GL_INVALID_VALUE,
1375 "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001376 return false;
1377 }
1378 break;
1379 }
1380 default:
1381 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1382 return false;
1383 }
1384
1385 return true;
1386}
1387
1388bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1389{
1390 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1391}
1392
1393bool ValidateBindBufferRange(Context *context,
1394 GLenum target,
1395 GLuint index,
1396 GLuint buffer,
1397 GLintptr offset,
1398 GLsizeiptr size)
1399{
1400 if (buffer != 0 && size <= 0)
1401 {
1402 context->handleError(
1403 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1404 return false;
1405 }
1406 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1407}
1408
Geoff Langc5629752015-12-07 16:29:04 -05001409bool ValidateProgramBinary(Context *context,
1410 GLuint program,
1411 GLenum binaryFormat,
1412 const void *binary,
1413 GLint length)
1414{
Martin Radev1be913c2016-07-11 17:59:16 +03001415 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001416 {
Jamie Madill437fa652016-05-03 15:13:24 -04001417 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001418 return false;
1419 }
1420
1421 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1422}
1423
1424bool ValidateGetProgramBinary(Context *context,
1425 GLuint program,
1426 GLsizei bufSize,
1427 GLsizei *length,
1428 GLenum *binaryFormat,
1429 void *binary)
1430{
Martin Radev1be913c2016-07-11 17:59:16 +03001431 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001432 {
Jamie Madill437fa652016-05-03 15:13:24 -04001433 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001434 return false;
1435 }
1436
1437 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1438}
1439
Olli Etuahof0fee072016-03-30 15:11:58 +03001440bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001441{
Martin Radev1be913c2016-07-11 17:59:16 +03001442 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001443 {
Jamie Madill437fa652016-05-03 15:13:24 -04001444 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001445 return false;
1446 }
1447
1448 if (GetValidProgram(context, program) == nullptr)
1449 {
1450 return false;
1451 }
1452
1453 switch (pname)
1454 {
1455 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001456 if (value != GL_FALSE && value != GL_TRUE)
1457 {
Jamie Madill437fa652016-05-03 15:13:24 -04001458 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001459 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1460 return false;
1461 }
Geoff Langc5629752015-12-07 16:29:04 -05001462 break;
1463
Yunchao He61afff12017-03-14 15:34:03 +08001464 case GL_PROGRAM_SEPARABLE:
1465 if (context->getClientVersion() < ES_3_1)
1466 {
1467 context->handleError(
1468 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1469 return false;
1470 }
1471
1472 if (value != GL_FALSE && value != GL_TRUE)
1473 {
1474 context->handleError(Error(
1475 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1476 return false;
1477 }
1478 break;
1479
Geoff Langc5629752015-12-07 16:29:04 -05001480 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001482 return false;
1483 }
1484
1485 return true;
1486}
Jamie Madillc29968b2016-01-20 11:17:23 -05001487
1488bool ValidateBlitFramebuffer(Context *context,
1489 GLint srcX0,
1490 GLint srcY0,
1491 GLint srcX1,
1492 GLint srcY1,
1493 GLint dstX0,
1494 GLint dstY0,
1495 GLint dstX1,
1496 GLint dstY1,
1497 GLbitfield mask,
1498 GLenum filter)
1499{
Martin Radev1be913c2016-07-11 17:59:16 +03001500 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001501 {
Jamie Madill437fa652016-05-03 15:13:24 -04001502 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001503 return false;
1504 }
1505
1506 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1507 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508}
Jamie Madillc29968b2016-01-20 11:17:23 -05001509
1510bool ValidateClearBufferiv(ValidationContext *context,
1511 GLenum buffer,
1512 GLint drawbuffer,
1513 const GLint *value)
1514{
1515 switch (buffer)
1516 {
1517 case GL_COLOR:
1518 if (drawbuffer < 0 ||
1519 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1520 {
Jamie Madill437fa652016-05-03 15:13:24 -04001521 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001522 return false;
1523 }
Geoff Lang76e65652017-03-27 14:58:02 -04001524 if (context->getExtensions().webglCompatibility)
1525 {
1526 constexpr GLenum validComponentTypes[] = {GL_INT};
1527 if (ValidateWebGLFramebufferAttachmentClearType(
1528 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1529 {
1530 return false;
1531 }
1532 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001533 break;
1534
1535 case GL_STENCIL:
1536 if (drawbuffer != 0)
1537 {
Jamie Madill437fa652016-05-03 15:13:24 -04001538 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001539 return false;
1540 }
1541 break;
1542
1543 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001544 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001545 return false;
1546 }
1547
1548 return ValidateClearBuffer(context);
1549}
1550
1551bool ValidateClearBufferuiv(ValidationContext *context,
1552 GLenum buffer,
1553 GLint drawbuffer,
1554 const GLuint *value)
1555{
1556 switch (buffer)
1557 {
1558 case GL_COLOR:
1559 if (drawbuffer < 0 ||
1560 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1561 {
Jamie Madill437fa652016-05-03 15:13:24 -04001562 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001563 return false;
1564 }
Geoff Lang76e65652017-03-27 14:58:02 -04001565 if (context->getExtensions().webglCompatibility)
1566 {
1567 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1568 if (ValidateWebGLFramebufferAttachmentClearType(
1569 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1570 {
1571 return false;
1572 }
1573 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001574 break;
1575
1576 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001577 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001578 return false;
1579 }
1580
1581 return ValidateClearBuffer(context);
1582}
1583
1584bool ValidateClearBufferfv(ValidationContext *context,
1585 GLenum buffer,
1586 GLint drawbuffer,
1587 const GLfloat *value)
1588{
1589 switch (buffer)
1590 {
1591 case GL_COLOR:
1592 if (drawbuffer < 0 ||
1593 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1594 {
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001596 return false;
1597 }
Geoff Lang76e65652017-03-27 14:58:02 -04001598 if (context->getExtensions().webglCompatibility)
1599 {
1600 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1601 GL_SIGNED_NORMALIZED};
1602 if (ValidateWebGLFramebufferAttachmentClearType(
1603 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1604 {
1605 return false;
1606 }
1607 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001608 break;
1609
1610 case GL_DEPTH:
1611 if (drawbuffer != 0)
1612 {
Jamie Madill437fa652016-05-03 15:13:24 -04001613 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001614 return false;
1615 }
1616 break;
1617
1618 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001619 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001620 return false;
1621 }
1622
1623 return ValidateClearBuffer(context);
1624}
1625
1626bool ValidateClearBufferfi(ValidationContext *context,
1627 GLenum buffer,
1628 GLint drawbuffer,
1629 GLfloat depth,
1630 GLint stencil)
1631{
1632 switch (buffer)
1633 {
1634 case GL_DEPTH_STENCIL:
1635 if (drawbuffer != 0)
1636 {
Jamie Madill437fa652016-05-03 15:13:24 -04001637 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001638 return false;
1639 }
1640 break;
1641
1642 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001643 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001644 return false;
1645 }
1646
1647 return ValidateClearBuffer(context);
1648}
1649
1650bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1651{
Martin Radev1be913c2016-07-11 17:59:16 +03001652 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001653 {
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001655 return false;
1656 }
1657
1658 return ValidateDrawBuffersBase(context, n, bufs);
1659}
1660
1661bool ValidateCopyTexSubImage3D(Context *context,
1662 GLenum target,
1663 GLint level,
1664 GLint xoffset,
1665 GLint yoffset,
1666 GLint zoffset,
1667 GLint x,
1668 GLint y,
1669 GLsizei width,
1670 GLsizei height)
1671{
Martin Radev1be913c2016-07-11 17:59:16 +03001672 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001673 {
Jamie Madill437fa652016-05-03 15:13:24 -04001674 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001675 return false;
1676 }
1677
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001678 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1679 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001680}
1681
Jamie Madill73a84962016-02-12 09:27:23 -05001682bool ValidateTexImage3D(Context *context,
1683 GLenum target,
1684 GLint level,
1685 GLint internalformat,
1686 GLsizei width,
1687 GLsizei height,
1688 GLsizei depth,
1689 GLint border,
1690 GLenum format,
1691 GLenum type,
1692 const GLvoid *pixels)
1693{
Martin Radev1be913c2016-07-11 17:59:16 +03001694 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001695 {
Jamie Madill437fa652016-05-03 15:13:24 -04001696 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001697 return false;
1698 }
1699
1700 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001701 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001702 pixels);
1703}
1704
Geoff Langc52f6f12016-10-14 10:18:00 -04001705bool ValidateTexImage3DRobustANGLE(Context *context,
1706 GLenum target,
1707 GLint level,
1708 GLint internalformat,
1709 GLsizei width,
1710 GLsizei height,
1711 GLsizei depth,
1712 GLint border,
1713 GLenum format,
1714 GLenum type,
1715 GLsizei bufSize,
1716 const GLvoid *pixels)
1717{
1718 if (context->getClientMajorVersion() < 3)
1719 {
1720 context->handleError(Error(GL_INVALID_OPERATION));
1721 return false;
1722 }
1723
1724 if (!ValidateRobustEntryPoint(context, bufSize))
1725 {
1726 return false;
1727 }
1728
1729 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1730 0, 0, width, height, depth, border, format, type,
1731 bufSize, pixels);
1732}
1733
Jamie Madill73a84962016-02-12 09:27:23 -05001734bool ValidateTexSubImage3D(Context *context,
1735 GLenum target,
1736 GLint level,
1737 GLint xoffset,
1738 GLint yoffset,
1739 GLint zoffset,
1740 GLsizei width,
1741 GLsizei height,
1742 GLsizei depth,
1743 GLenum format,
1744 GLenum type,
1745 const GLvoid *pixels)
1746{
Martin Radev1be913c2016-07-11 17:59:16 +03001747 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001748 {
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001750 return false;
1751 }
1752
1753 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1754 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001755 -1, pixels);
1756}
1757
1758bool ValidateTexSubImage3DRobustANGLE(Context *context,
1759 GLenum target,
1760 GLint level,
1761 GLint xoffset,
1762 GLint yoffset,
1763 GLint zoffset,
1764 GLsizei width,
1765 GLsizei height,
1766 GLsizei depth,
1767 GLenum format,
1768 GLenum type,
1769 GLsizei bufSize,
1770 const GLvoid *pixels)
1771{
1772 if (context->getClientMajorVersion() < 3)
1773 {
1774 context->handleError(Error(GL_INVALID_OPERATION));
1775 return false;
1776 }
1777
1778 if (!ValidateRobustEntryPoint(context, bufSize))
1779 {
1780 return false;
1781 }
1782
1783 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1784 yoffset, zoffset, width, height, depth, 0, format, type,
1785 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001786}
1787
1788bool ValidateCompressedTexSubImage3D(Context *context,
1789 GLenum target,
1790 GLint level,
1791 GLint xoffset,
1792 GLint yoffset,
1793 GLint zoffset,
1794 GLsizei width,
1795 GLsizei height,
1796 GLsizei depth,
1797 GLenum format,
1798 GLsizei imageSize,
1799 const GLvoid *data)
1800{
Martin Radev1be913c2016-07-11 17:59:16 +03001801 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001802 {
Jamie Madill437fa652016-05-03 15:13:24 -04001803 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001804 return false;
1805 }
1806
Geoff Langca271392017-04-05 12:30:00 -04001807 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001808 if (!formatInfo.compressed)
1809 {
1810 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1811 return false;
1812 }
1813
Jamie Madill513558d2016-06-02 13:04:11 -04001814 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001815 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001816 if (blockSizeOrErr.isError())
1817 {
1818 context->handleError(blockSizeOrErr.getError());
1819 return false;
1820 }
1821 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001822 {
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001824 return false;
1825 }
1826
1827 if (!data)
1828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001830 return false;
1831 }
1832
1833 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001834 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001835}
Corentin Wallezb2931602017-04-11 15:58:57 -04001836bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1837 GLenum target,
1838 GLint level,
1839 GLint xoffset,
1840 GLint yoffset,
1841 GLint zoffset,
1842 GLsizei width,
1843 GLsizei height,
1844 GLsizei depth,
1845 GLenum format,
1846 GLsizei imageSize,
1847 GLsizei dataSize,
1848 const GLvoid *data)
1849{
1850 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1851 {
1852 return false;
1853 }
1854
1855 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1856 height, depth, format, imageSize, data);
1857}
Jamie Madill73a84962016-02-12 09:27:23 -05001858
Olli Etuaho41997e72016-03-10 13:38:39 +02001859bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1860{
1861 return ValidateGenOrDeleteES3(context, n);
1862}
1863
1864bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1865{
1866 return ValidateGenOrDeleteES3(context, n);
1867}
1868
1869bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1870{
1871 return ValidateGenOrDeleteCountES3(context, count);
1872}
1873
1874bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1875{
1876 return ValidateGenOrDeleteCountES3(context, count);
1877}
1878
1879bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1880{
1881 return ValidateGenOrDeleteES3(context, n);
1882}
1883
1884bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1885{
1886 if (!ValidateGenOrDeleteES3(context, n))
1887 {
1888 return false;
1889 }
1890 for (GLint i = 0; i < n; ++i)
1891 {
1892 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1893 if (transformFeedback != nullptr && transformFeedback->isActive())
1894 {
1895 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001897 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1898 return false;
1899 }
1900 }
1901 return true;
1902}
1903
1904bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1905{
1906 return ValidateGenOrDeleteES3(context, n);
1907}
1908
1909bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1910{
1911 return ValidateGenOrDeleteES3(context, n);
1912}
1913
1914bool ValidateGenOrDeleteES3(Context *context, GLint n)
1915{
Martin Radev1be913c2016-07-11 17:59:16 +03001916 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001917 {
Jamie Madill437fa652016-05-03 15:13:24 -04001918 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001919 return false;
1920 }
1921 return ValidateGenOrDelete(context, n);
1922}
1923
1924bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1925{
Martin Radev1be913c2016-07-11 17:59:16 +03001926 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001927 {
Jamie Madill437fa652016-05-03 15:13:24 -04001928 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001929 return false;
1930 }
1931 if (count < 0)
1932 {
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001934 return false;
1935 }
1936 return true;
1937}
1938
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001939bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1940{
Martin Radev1be913c2016-07-11 17:59:16 +03001941 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001944 return false;
1945 }
1946 switch (primitiveMode)
1947 {
1948 case GL_TRIANGLES:
1949 case GL_LINES:
1950 case GL_POINTS:
1951 break;
1952
1953 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001955 return false;
1956 }
1957
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001958 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001959 ASSERT(transformFeedback != nullptr);
1960
1961 if (transformFeedback->isActive())
1962 {
Jamie Madill437fa652016-05-03 15:13:24 -04001963 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001964 return false;
1965 }
1966 return true;
1967}
1968
Olli Etuaho4f667482016-03-30 15:56:35 +03001969bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1970{
Geoff Lang496c02d2016-10-20 11:38:11 -07001971 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1972}
1973
1974bool ValidateGetBufferPointervRobustANGLE(Context *context,
1975 GLenum target,
1976 GLenum pname,
1977 GLsizei bufSize,
1978 GLsizei *length,
1979 GLvoid **params)
1980{
1981 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001982 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001983 return false;
1984 }
1985
Geoff Lang496c02d2016-10-20 11:38:11 -07001986 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1987 {
1988 return false;
1989 }
1990
1991 if (!ValidateRobustBufferSize(context, bufSize, *length))
1992 {
1993 return false;
1994 }
1995
1996 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001997}
1998
1999bool ValidateUnmapBuffer(Context *context, GLenum target)
2000{
Martin Radev1be913c2016-07-11 17:59:16 +03002001 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002002 {
Jamie Madill437fa652016-05-03 15:13:24 -04002003 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002004 return false;
2005 }
2006
2007 return ValidateUnmapBufferBase(context, target);
2008}
2009
2010bool ValidateMapBufferRange(Context *context,
2011 GLenum target,
2012 GLintptr offset,
2013 GLsizeiptr length,
2014 GLbitfield access)
2015{
Martin Radev1be913c2016-07-11 17:59:16 +03002016 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002017 {
Jamie Madill437fa652016-05-03 15:13:24 -04002018 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002019 return false;
2020 }
2021
2022 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2023}
2024
2025bool ValidateFlushMappedBufferRange(Context *context,
2026 GLenum target,
2027 GLintptr offset,
2028 GLsizeiptr length)
2029{
Martin Radev1be913c2016-07-11 17:59:16 +03002030 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002031 {
Jamie Madill437fa652016-05-03 15:13:24 -04002032 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002033 return false;
2034 }
2035
2036 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2037}
2038
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002039bool ValidateIndexedStateQuery(ValidationContext *context,
2040 GLenum pname,
2041 GLuint index,
2042 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002043{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002044 if (length)
2045 {
2046 *length = 0;
2047 }
2048
Martin Radev66fb8202016-07-28 11:45:20 +03002049 GLenum nativeType;
2050 unsigned int numParams;
2051 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2052 {
2053 context->handleError(Error(GL_INVALID_ENUM));
2054 return false;
2055 }
2056
2057 const Caps &caps = context->getCaps();
2058 switch (pname)
2059 {
2060 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2061 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2062 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2063 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2064 {
2065 context->handleError(Error(GL_INVALID_VALUE));
2066 return false;
2067 }
2068 break;
2069
2070 case GL_UNIFORM_BUFFER_START:
2071 case GL_UNIFORM_BUFFER_SIZE:
2072 case GL_UNIFORM_BUFFER_BINDING:
2073 if (index >= caps.maxUniformBufferBindings)
2074 {
2075 context->handleError(Error(GL_INVALID_VALUE));
2076 return false;
2077 }
2078 break;
Shao80957d92017-02-20 21:25:59 +08002079
Martin Radev66fb8202016-07-28 11:45:20 +03002080 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2081 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2082 if (index >= 3u)
2083 {
2084 context->handleError(Error(GL_INVALID_VALUE));
2085 return false;
2086 }
2087 break;
Shao80957d92017-02-20 21:25:59 +08002088
Jiajia Qin6eafb042016-12-27 17:04:07 +08002089 case GL_ATOMIC_COUNTER_BUFFER_START:
2090 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2091 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2092 if (context->getClientVersion() < ES_3_1)
2093 {
2094 context->handleError(
2095 Error(GL_INVALID_ENUM,
2096 "Atomic Counter buffers are not supported in this version of GL"));
2097 return false;
2098 }
2099 if (index >= caps.maxAtomicCounterBufferBindings)
2100 {
2101 context->handleError(
2102 Error(GL_INVALID_VALUE,
2103 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2104 return false;
2105 }
2106 break;
Shao80957d92017-02-20 21:25:59 +08002107
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002108 case GL_SHADER_STORAGE_BUFFER_START:
2109 case GL_SHADER_STORAGE_BUFFER_SIZE:
2110 case GL_SHADER_STORAGE_BUFFER_BINDING:
2111 if (context->getClientVersion() < ES_3_1)
2112 {
2113 context->handleError(
2114 Error(GL_INVALID_ENUM,
2115 "Shader storage buffers are not supported in this version of GL"));
2116 return false;
2117 }
2118 if (index >= caps.maxShaderStorageBufferBindings)
2119 {
2120 context->handleError(
2121 Error(GL_INVALID_VALUE,
2122 "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
2123 return false;
2124 }
2125 break;
2126
Shao80957d92017-02-20 21:25:59 +08002127 case GL_VERTEX_BINDING_BUFFER:
2128 case GL_VERTEX_BINDING_DIVISOR:
2129 case GL_VERTEX_BINDING_OFFSET:
2130 case GL_VERTEX_BINDING_STRIDE:
2131 if (context->getClientVersion() < ES_3_1)
2132 {
2133 context->handleError(
2134 Error(GL_INVALID_ENUM,
2135 "Vertex Attrib Bindings are not supported in this version of GL"));
2136 return false;
2137 }
2138 if (index >= caps.maxVertexAttribBindings)
2139 {
2140 context->handleError(
2141 Error(GL_INVALID_VALUE,
2142 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2143 return false;
2144 }
2145 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002146 default:
2147 context->handleError(Error(GL_INVALID_ENUM));
2148 return false;
2149 }
2150
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002151 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002152 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002153 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002154 }
2155
2156 return true;
2157}
2158
2159bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2160{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002161 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002162 {
2163 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2164 return false;
2165 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002166 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002167}
2168
Geoff Langcf255ea2016-10-20 11:39:09 -07002169bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2170 GLenum target,
2171 GLuint index,
2172 GLsizei bufSize,
2173 GLsizei *length,
2174 GLint *data)
2175{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002176 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002177 {
2178 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2179 return false;
2180 }
2181
2182 if (!ValidateRobustEntryPoint(context, bufSize))
2183 {
2184 return false;
2185 }
2186
2187 if (!ValidateIndexedStateQuery(context, target, index, length))
2188 {
2189 return false;
2190 }
2191
2192 if (!ValidateRobustBufferSize(context, bufSize, *length))
2193 {
2194 return false;
2195 }
2196
2197 return true;
2198}
2199
Martin Radev66fb8202016-07-28 11:45:20 +03002200bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2201{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002202 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002203 {
2204 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2205 return false;
2206 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002207 return ValidateIndexedStateQuery(context, target, index, nullptr);
2208}
2209
2210bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2211 GLenum target,
2212 GLuint index,
2213 GLsizei bufSize,
2214 GLsizei *length,
2215 GLint64 *data)
2216{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002217 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002218 {
2219 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2220 return false;
2221 }
2222
2223 if (!ValidateRobustEntryPoint(context, bufSize))
2224 {
2225 return false;
2226 }
2227
2228 if (!ValidateIndexedStateQuery(context, target, index, length))
2229 {
2230 return false;
2231 }
2232
2233 if (!ValidateRobustBufferSize(context, bufSize, *length))
2234 {
2235 return false;
2236 }
2237
2238 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002239}
2240
Jamie Madillb0817d12016-11-01 15:48:31 -04002241bool ValidateCopyBufferSubData(ValidationContext *context,
2242 GLenum readTarget,
2243 GLenum writeTarget,
2244 GLintptr readOffset,
2245 GLintptr writeOffset,
2246 GLsizeiptr size)
2247{
2248 if (context->getClientMajorVersion() < 3)
2249 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002250 context->handleError(
2251 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002252 return false;
2253 }
2254
2255 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2256 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002257 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002258 return false;
2259 }
2260
2261 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2262 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2263
2264 if (!readBuffer || !writeBuffer)
2265 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002266 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002267 return false;
2268 }
2269
2270 // Verify that readBuffer and writeBuffer are not currently mapped
2271 if (readBuffer->isMapped() || writeBuffer->isMapped())
2272 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002273 context->handleError(
2274 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002275 return false;
2276 }
2277
Jamie Madilld2f0c742016-11-02 10:34:41 -04002278 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2279 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2280 CheckedNumeric<GLintptr> checkedSize(size);
2281
2282 auto checkedReadSum = checkedReadOffset + checkedSize;
2283 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2284
2285 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2286 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2287 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002288 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002289 context->handleError(
2290 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002291 return false;
2292 }
2293
Jamie Madilld2f0c742016-11-02 10:34:41 -04002294 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002295 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002296 context->handleError(
2297 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002298 return false;
2299 }
2300
Jamie Madilld2f0c742016-11-02 10:34:41 -04002301 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2302 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2303 {
2304 context->handleError(
2305 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2306 return false;
2307 }
2308
2309 if (readBuffer == writeBuffer)
2310 {
2311 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2312 if (!checkedOffsetDiff.IsValid())
2313 {
2314 // This shold not be possible.
2315 UNREACHABLE();
2316 context->handleError(
2317 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2318 return false;
2319 }
2320
2321 if (checkedOffsetDiff.ValueOrDie() < size)
2322 {
2323 context->handleError(Error(GL_INVALID_VALUE));
2324 return false;
2325 }
2326 }
2327
Jamie Madillb0817d12016-11-01 15:48:31 -04002328 return true;
2329}
2330
Geoff Langc339c4e2016-11-29 10:37:36 -05002331bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2332{
2333 if (context->getClientMajorVersion() < 3)
2334 {
2335 context->handleError(
2336 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2337 return false;
2338 }
2339
2340 switch (name)
2341 {
2342 case GL_EXTENSIONS:
2343 if (index >= context->getExtensionStringCount())
2344 {
2345 context->handleError(Error(
2346 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2347 return false;
2348 }
2349 break;
2350
2351 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2352 if (!context->getExtensions().requestExtension)
2353 {
2354 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2355 return false;
2356 }
2357 if (index >= context->getRequestableExtensionStringCount())
2358 {
2359 context->handleError(
2360 Error(GL_INVALID_VALUE,
2361 "index must be less than the number of requestable extension strings."));
2362 return false;
2363 }
2364 break;
2365
2366 default:
2367 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2368 return false;
2369 }
2370
2371 return true;
2372}
2373
Jamie Madille8fb6402017-02-14 17:56:40 -05002374bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2375 GLenum target,
2376 GLsizei samples,
2377 GLenum internalformat,
2378 GLsizei width,
2379 GLsizei height)
2380{
2381 if (context->getClientMajorVersion() < 3)
2382 {
2383 context->handleError(Error(GL_INVALID_OPERATION));
2384 return false;
2385 }
2386
2387 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2388 height))
2389 {
2390 return false;
2391 }
2392
2393 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2394 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002395 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002396 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2397 samples > 0)
2398 {
2399 context->handleError(Error(GL_INVALID_OPERATION));
2400 return false;
2401 }
2402
2403 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2404 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2405 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2406 {
2407 context->handleError(
2408 Error(GL_INVALID_OPERATION,
2409 "Samples must not be greater than maximum supported value for the format."));
2410 return false;
2411 }
2412
2413 return true;
2414}
2415
Geoff Langaa086d62017-03-23 16:47:21 -04002416bool ValidateVertexAttribIPointer(ValidationContext *context,
2417 GLuint index,
2418 GLint size,
2419 GLenum type,
2420 GLsizei stride,
2421 const GLvoid *pointer)
2422{
2423 if (context->getClientMajorVersion() < 3)
2424 {
Geoff Langaa086d62017-03-23 16:47:21 -04002425 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002426 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002427 return false;
2428 }
2429
Shao80957d92017-02-20 21:25:59 +08002430 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002431 {
Geoff Langaa086d62017-03-23 16:47:21 -04002432 return false;
2433 }
2434
Geoff Langaa086d62017-03-23 16:47:21 -04002435 if (stride < 0)
2436 {
Shao80957d92017-02-20 21:25:59 +08002437 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002438 return false;
2439 }
2440
Shao80957d92017-02-20 21:25:59 +08002441 const Caps &caps = context->getCaps();
2442 if (context->getClientVersion() >= ES_3_1)
2443 {
2444 if (stride > caps.maxVertexAttribStride)
2445 {
2446 context->handleError(
2447 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2448 return false;
2449 }
2450
2451 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2452 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2453 // validation should be inherited.
2454 if (index >= caps.maxVertexAttribBindings)
2455 {
2456 context->handleError(
2457 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2458 return false;
2459 }
2460 }
2461
Geoff Langaa086d62017-03-23 16:47:21 -04002462 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2463 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2464 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2465 // and the pointer argument is not NULL.
2466 if (context->getGLState().getVertexArrayId() != 0 &&
2467 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2468 {
2469 context->handleError(
2470 Error(GL_INVALID_OPERATION,
2471 "Client data cannot be used with a non-default vertex array object."));
2472 return false;
2473 }
2474
Geoff Lang2d62ab72017-03-23 16:54:40 -04002475 if (context->getExtensions().webglCompatibility)
2476 {
2477 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2478 {
2479 return false;
2480 }
2481 }
2482
Geoff Langaa086d62017-03-23 16:47:21 -04002483 return true;
2484}
2485
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002486bool ValidateGetSynciv(Context *context,
2487 GLsync sync,
2488 GLenum pname,
2489 GLsizei bufSize,
2490 GLsizei *length,
2491 GLint *values)
2492{
2493 if (context->getClientMajorVersion() < 3)
2494 {
2495 context->handleError(
2496 Error(GL_INVALID_OPERATION, "GetSynciv requires OpenGL ES 3.0 or higher."));
2497 return false;
2498 }
2499
2500 if (bufSize < 0)
2501 {
2502 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
2503 return false;
2504 }
2505
2506 FenceSync *fenceSync = context->getFenceSync(sync);
2507 if (!fenceSync)
2508 {
2509 context->handleError(Error(GL_INVALID_VALUE, "Invalid sync object."));
2510 return false;
2511 }
2512
2513 switch (pname)
2514 {
2515 case GL_OBJECT_TYPE:
2516 case GL_SYNC_CONDITION:
2517 case GL_SYNC_FLAGS:
2518 case GL_SYNC_STATUS:
2519 break;
2520
2521 default:
2522 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
2523 return false;
2524 }
2525
2526 return true;
2527}
2528
Jamie Madillc29968b2016-01-20 11:17:23 -05002529} // namespace gl