blob: 9070a157485f3b5da13390f720a286c811120275 [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 Lang966c9402017-04-18 12:38:27 -0400207 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400208 {
Geoff Lang966c9402017-04-18 12:38:27 -0400209 if (!ValidCompressedSubImageSize(
210 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
211 texture->getWidth(target, level), texture->getHeight(target, level)))
212 {
213 context->handleError(
214 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
215 return false;
216 }
217
218 if (format != actualInternalFormat)
219 {
220 context->handleError(Error(
221 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
222 return false;
223 }
224 }
225 else
226 {
227 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
228 {
229 context->handleError(
230 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
231 return false;
232 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400233 }
234
Geoff Langeb66a6e2016-10-31 13:06:12 -0400235 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400236 {
Jamie Madill437fa652016-05-03 15:13:24 -0400237 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400238 return false;
239 }
240
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400241 if (target == GL_TEXTURE_3D)
242 {
Jamie Madill437fa652016-05-03 15:13:24 -0400243 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400244 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400245 }
246 }
247 else
248 {
Geoff Langca271392017-04-05 12:30:00 -0400249 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400250 {
Geoff Lang5d601382014-07-22 15:14:06 -0400251 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400252 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253 }
254
255 // Validate sub image parameters
256 if (isSubImage)
257 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500258 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400259 {
Jamie Madill437fa652016-05-03 15:13:24 -0400260 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400262 }
263
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400264 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
265 {
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 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
271 std::numeric_limits<GLsizei>::max() - yoffset < height ||
272 std::numeric_limits<GLsizei>::max() - zoffset < depth)
273 {
Jamie Madill437fa652016-05-03 15:13:24 -0400274 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400275 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400276 }
277
Geoff Langa9be0dc2014-12-17 12:34:40 -0500278 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
279 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
280 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281 {
Jamie Madill437fa652016-05-03 15:13:24 -0400282 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400283 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400284 }
285 }
286
Geoff Langff5b2d52016-09-07 11:32:23 -0400287 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
288 imageSize))
289 {
290 return false;
291 }
292
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400293 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700294 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400295 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400296 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800297 // ...data is not evenly divisible into the number of bytes needed to store in memory a
298 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400299 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400300 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400301 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400302 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400303 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
304
Geoff Langff5b2d52016-09-07 11:32:23 -0400305 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400306 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400307 context->handleError(
308 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400309 return false;
310 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400311 }
312
Jamie Madill7a5f7382014-03-05 15:01:24 -0500313 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700314 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500315 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400316 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400317 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500318 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400319 }
320
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321 return true;
322}
323
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500324bool ValidateES3TexImage2DParameters(Context *context,
325 GLenum target,
326 GLint level,
327 GLenum internalformat,
328 bool isCompressed,
329 bool isSubImage,
330 GLint xoffset,
331 GLint yoffset,
332 GLint zoffset,
333 GLsizei width,
334 GLsizei height,
335 GLsizei depth,
336 GLint border,
337 GLenum format,
338 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400339 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500340 const GLvoid *pixels)
341{
342 if (!ValidTexture2DDestinationTarget(context, target))
343 {
Jamie Madill437fa652016-05-03 15:13:24 -0400344 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500345 return false;
346 }
347
348 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
349 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400350 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500351}
352
353bool ValidateES3TexImage3DParameters(Context *context,
354 GLenum target,
355 GLint level,
356 GLenum internalformat,
357 bool isCompressed,
358 bool isSubImage,
359 GLint xoffset,
360 GLint yoffset,
361 GLint zoffset,
362 GLsizei width,
363 GLsizei height,
364 GLsizei depth,
365 GLint border,
366 GLenum format,
367 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400368 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500369 const GLvoid *pixels)
370{
371 if (!ValidTexture3DDestinationTarget(context, target))
372 {
Jamie Madill437fa652016-05-03 15:13:24 -0400373 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500374 return false;
375 }
376
377 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
378 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400379 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500380}
381
Geoff Lang5d601382014-07-22 15:14:06 -0400382struct EffectiveInternalFormatInfo
383{
Jamie Madill76648fe2016-10-05 17:01:41 -0400384 GLenum effectiveFormat;
385 GLenum destFormat;
386 GLuint minRedBits;
387 GLuint maxRedBits;
388 GLuint minGreenBits;
389 GLuint maxGreenBits;
390 GLuint minBlueBits;
391 GLuint maxBlueBits;
392 GLuint minAlphaBits;
393 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400394};
395
Jamie Madill76648fe2016-10-05 17:01:41 -0400396static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
397 GLenum targetFormat,
398 const EffectiveInternalFormatInfo *list,
399 size_t size,
400 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400401{
Jamie Madill76648fe2016-10-05 17:01:41 -0400402 for (size_t curFormat = 0; curFormat < size; ++curFormat)
403 {
404 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
405 if ((formatInfo.destFormat == targetFormat) &&
406 (formatInfo.minRedBits <= srcFormat.redBits &&
407 formatInfo.maxRedBits >= srcFormat.redBits) &&
408 (formatInfo.minGreenBits <= srcFormat.greenBits &&
409 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
410 (formatInfo.minBlueBits <= srcFormat.blueBits &&
411 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
412 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
413 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
414 {
415 *outEffectiveFormat = formatInfo.effectiveFormat;
416 return true;
417 }
418 }
Geoff Lang5d601382014-07-22 15:14:06 -0400419
Jamie Madill76648fe2016-10-05 17:01:41 -0400420 *outEffectiveFormat = GL_NONE;
421 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400422}
423
Jamie Madill76648fe2016-10-05 17:01:41 -0400424bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
425 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400426{
Jamie Madill76648fe2016-10-05 17:01:41 -0400427 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
428 // Effective internal format coresponding to destination internal format and linear source
429 // buffer component sizes.
430 // | Source channel min/max sizes |
431 // Effective Internal Format | N/A | R | G | B | A |
432 // clang-format off
433 constexpr EffectiveInternalFormatInfo list[] = {
434 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
435 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
436 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
437 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
438 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
439 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
440 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
441 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
442 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
443 };
444 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400445
Jamie Madill76648fe2016-10-05 17:01:41 -0400446 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
447}
Geoff Lang5d601382014-07-22 15:14:06 -0400448
Jamie Madill76648fe2016-10-05 17:01:41 -0400449bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
450 const InternalFormat &destFormat,
451 GLenum *outEffectiveFormat)
452{
453 constexpr GLuint umax = UINT_MAX;
454
455 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
456 // Effective internal format coresponding to destination internal format andlinear source buffer
457 // component sizes.
458 // | Source channel min/max sizes |
459 // Effective Internal Format | Dest Format | R | G | B | A |
460 // clang-format off
461 constexpr EffectiveInternalFormatInfo list[] = {
462 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
463 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
464 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
465 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
466 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
467 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
468 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
469 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
470 };
471 // clang-format on
472
473 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
474 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400475}
476
He Yunchaoced53ae2016-11-29 15:00:51 +0800477static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
478 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400479 GLenum *outEffectiveFormat)
480{
Geoff Langca271392017-04-05 12:30:00 -0400481 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400482 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400483 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400484 }
485 else
486 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400487 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400488 }
Geoff Lang5d601382014-07-22 15:14:06 -0400489}
490
Corentin Wallez76287682016-04-25 09:23:38 -0400491static bool EqualOrFirstZero(GLuint first, GLuint second)
492{
493 return first == 0 || first == second;
494}
495
Geoff Langca271392017-04-05 12:30:00 -0400496static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
497 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400498 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400499{
Jamie Madill21b786b2016-11-01 17:41:31 -0400500 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400501 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400502 return false;
503 }
Geoff Lang5d601382014-07-22 15:14:06 -0400504
Jamie Madill21b786b2016-11-01 17:41:31 -0400505 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
506 // must both be signed, unsigned, or fixed point and both source and destinations
507 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
508 // conversion between fixed and floating point.
509
510 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
511 (framebufferFormatInfo.colorEncoding == GL_SRGB))
512 {
513 return false;
514 }
515
516 if (((textureFormatInfo.componentType == GL_INT) !=
517 (framebufferFormatInfo.componentType == GL_INT)) ||
518 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
519 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
520 {
521 return false;
522 }
523
524 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
525 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
526 textureFormatInfo.componentType == GL_FLOAT) &&
527 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
528 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
529 framebufferFormatInfo.componentType == GL_FLOAT))
530 {
531 return false;
532 }
533
534 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
535 // The effective internal format of the source buffer is determined with the following rules
536 // applied in order:
537 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
538 // format then the effective internal format is the source buffer's sized internal format.
539 // * If the source buffer is a texture that was created with an unsized base internal format,
540 // then the effective internal format is the source image array's effective internal
541 // format, as specified by table 3.12, which is determined from the <format> and <type>
542 // that were used when the source image array was specified by TexImage*.
543 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
544 // where Destination Internal Format matches internalformat and where the [source channel
545 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
546 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
547 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800548 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400549 if (readBufferHandle != 0)
550 {
551 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
552 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400553 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400554 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400555 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400556 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400557 else
Geoff Lang5d601382014-07-22 15:14:06 -0400558 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400559 // Renderbuffers cannot be created with an unsized internal format, so this must be an
560 // unsized-format texture. We can use the same table we use when creating textures to
561 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400562 sourceEffectiveFormat =
563 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400564 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400565 }
566 else
567 {
568 // The effective internal format must be derived from the source framebuffer's channel
569 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
570 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400571 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400572 GLenum effectiveFormat;
573 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
574 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400575 {
Geoff Langca271392017-04-05 12:30:00 -0400576 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400577 }
578 else
579 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400580 return false;
581 }
582 }
583 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
584 {
585 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400586 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400587 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
588 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
589 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
590 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
591 {
Geoff Langca271392017-04-05 12:30:00 -0400592 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400593 }
594 else
595 {
596 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400597 }
598 }
599 else
600 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400601 UNREACHABLE();
602 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400603 }
Geoff Lang5d601382014-07-22 15:14:06 -0400604 }
605
Geoff Langca271392017-04-05 12:30:00 -0400606 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400607 {
608 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
609 // sized, component sizes of the source and destination formats must exactly match if the
610 // destination format exists.
611 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
612 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
613 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
614 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
615 {
616 return false;
617 }
618 }
619
620 return true; // A conversion function exists, and no rule in the specification has precluded
621 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400622}
623
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500624bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
625 GLenum target,
626 GLint level,
627 GLenum internalformat,
628 bool isSubImage,
629 GLint xoffset,
630 GLint yoffset,
631 GLint zoffset,
632 GLint x,
633 GLint y,
634 GLsizei width,
635 GLsizei height,
636 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400637{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400638 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400639 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400640 xoffset, yoffset, zoffset, x, y, width, height, border,
641 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400642 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400643 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400644 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400645 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400646
Jamie Madill51f40ec2016-06-15 14:06:00 -0400647 const auto &state = context->getGLState();
648 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
649 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400650
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400651 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400652 {
Jamie Madill437fa652016-05-03 15:13:24 -0400653 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400654 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400655 }
656
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400657 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400658 {
Jamie Madill437fa652016-05-03 15:13:24 -0400659 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400660 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400661 }
662
Jamie Madill0c8abca2016-07-22 20:21:26 -0400663 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664
665 if (isSubImage)
666 {
Geoff Langca271392017-04-05 12:30:00 -0400667 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500668 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400669 {
Jamie Madill437fa652016-05-03 15:13:24 -0400670 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400671 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400672 }
673 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400674 else
675 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400676 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400677 const InternalFormat &framebufferFormat = *source->getFormat().info;
678 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400679 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400680 {
Jamie Madill437fa652016-05-03 15:13:24 -0400681 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400682 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400683 }
684 }
685
Geoff Lang784a8fd2013-09-24 12:33:16 -0400686 // If width or height is zero, it is a no-op. Return false without setting an error.
687 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688}
689
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500690bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
691 GLenum target,
692 GLint level,
693 GLenum internalformat,
694 bool isSubImage,
695 GLint xoffset,
696 GLint yoffset,
697 GLint zoffset,
698 GLint x,
699 GLint y,
700 GLsizei width,
701 GLsizei height,
702 GLint border)
703{
704 if (!ValidTexture2DDestinationTarget(context, target))
705 {
Jamie Madill437fa652016-05-03 15:13:24 -0400706 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500707 return false;
708 }
709
710 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
711 xoffset, yoffset, zoffset, x, y, width, height,
712 border);
713}
714
715bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
716 GLenum target,
717 GLint level,
718 GLenum internalformat,
719 bool isSubImage,
720 GLint xoffset,
721 GLint yoffset,
722 GLint zoffset,
723 GLint x,
724 GLint y,
725 GLsizei width,
726 GLsizei height,
727 GLint border)
728{
729 if (!ValidTexture3DDestinationTarget(context, target))
730 {
Jamie Madill437fa652016-05-03 15:13:24 -0400731 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500732 return false;
733 }
734
735 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
736 xoffset, yoffset, zoffset, x, y, width, height,
737 border);
738}
739
740bool ValidateES3TexStorageParametersBase(Context *context,
741 GLenum target,
742 GLsizei levels,
743 GLenum internalformat,
744 GLsizei width,
745 GLsizei height,
746 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747{
748 if (width < 1 || height < 1 || depth < 1 || levels < 1)
749 {
Jamie Madill437fa652016-05-03 15:13:24 -0400750 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400751 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 }
753
Geoff Langb92c1332015-09-04 12:54:55 -0400754 GLsizei maxDim = std::max(width, height);
755 if (target != GL_TEXTURE_2D_ARRAY)
756 {
757 maxDim = std::max(maxDim, depth);
758 }
759
760 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 {
Jamie Madill437fa652016-05-03 15:13:24 -0400762 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400763 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 }
765
Geoff Langaae65a42014-05-26 12:43:44 -0400766 const gl::Caps &caps = context->getCaps();
767
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 switch (target)
769 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800770 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 {
Geoff Langaae65a42014-05-26 12:43:44 -0400772 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
773 static_cast<GLuint>(height) > caps.max2DTextureSize)
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_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 if (width != height)
784 {
Jamie Madill437fa652016-05-03 15:13:24 -0400785 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400786 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 }
788
Geoff Langaae65a42014-05-26 12:43:44 -0400789 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 {
Jamie Madill437fa652016-05-03 15:13:24 -0400791 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400792 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793 }
794 }
795 break;
796
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 {
Geoff Langaae65a42014-05-26 12:43:44 -0400799 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
800 static_cast<GLuint>(height) > caps.max3DTextureSize ||
801 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 {
Jamie Madill437fa652016-05-03 15:13:24 -0400803 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400804 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805 }
806 }
807 break;
808
He Yunchaoced53ae2016-11-29 15:00:51 +0800809 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400810 {
Geoff Langaae65a42014-05-26 12:43:44 -0400811 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
812 static_cast<GLuint>(height) > caps.max2DTextureSize ||
813 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 {
Jamie Madill437fa652016-05-03 15:13:24 -0400815 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400816 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400817 }
818 }
819 break;
820
He Yunchaoced53ae2016-11-29 15:00:51 +0800821 default:
822 UNREACHABLE();
823 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 }
825
Geoff Lang691e58c2014-12-19 17:03:25 -0500826 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 if (!texture || texture->id() == 0)
828 {
Jamie Madill437fa652016-05-03 15:13:24 -0400829 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400830 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 }
832
Geoff Lang69cce582015-09-17 13:20:36 -0400833 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 {
Jamie Madill437fa652016-05-03 15:13:24 -0400835 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 }
838
Geoff Langca271392017-04-05 12:30:00 -0400839 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400840 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 {
Jamie Madill437fa652016-05-03 15:13:24 -0400842 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
845
Geoff Langca271392017-04-05 12:30:00 -0400846 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851
852 return true;
853}
854
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500855bool ValidateES3TexStorage2DParameters(Context *context,
856 GLenum target,
857 GLsizei levels,
858 GLenum internalformat,
859 GLsizei width,
860 GLsizei height,
861 GLsizei depth)
862{
863 if (!ValidTexture2DTarget(context, target))
864 {
Jamie Madill437fa652016-05-03 15:13:24 -0400865 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500866 return false;
867 }
868
869 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
870 height, depth);
871}
872
873bool ValidateES3TexStorage3DParameters(Context *context,
874 GLenum target,
875 GLsizei levels,
876 GLenum internalformat,
877 GLsizei width,
878 GLsizei height,
879 GLsizei depth)
880{
881 if (!ValidTexture3DTarget(context, target))
882 {
Jamie Madill437fa652016-05-03 15:13:24 -0400883 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500884 return false;
885 }
886
887 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
888 height, depth);
889}
890
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500891bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
892{
Martin Radev1be913c2016-07-11 17:59:16 +0300893 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500894 {
Jamie Madill437fa652016-05-03 15:13:24 -0400895 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500896 return false;
897 }
898
899 return ValidateBeginQueryBase(context, target, id);
900}
901
902bool ValidateEndQuery(gl::Context *context, GLenum target)
903{
Martin Radev1be913c2016-07-11 17:59:16 +0300904 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500905 {
Jamie Madill437fa652016-05-03 15:13:24 -0400906 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500907 return false;
908 }
909
910 return ValidateEndQueryBase(context, target);
911}
912
913bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
914{
Martin Radev1be913c2016-07-11 17:59:16 +0300915 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500916 {
Jamie Madill437fa652016-05-03 15:13:24 -0400917 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500918 return false;
919 }
920
Geoff Lang2186c382016-10-14 10:54:54 -0400921 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500922}
923
924bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
925{
Martin Radev1be913c2016-07-11 17:59:16 +0300926 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500929 return false;
930 }
931
Geoff Lang2186c382016-10-14 10:54:54 -0400932 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500933}
934
He Yunchaoced53ae2016-11-29 15:00:51 +0800935bool ValidateFramebufferTextureLayer(Context *context,
936 GLenum target,
937 GLenum attachment,
938 GLuint texture,
939 GLint level,
940 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400941{
Martin Radev1be913c2016-07-11 17:59:16 +0300942 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400945 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400946 }
947
Jamie Madill55ec3b12014-07-03 10:38:57 -0400948 if (layer < 0)
949 {
Jamie Madill437fa652016-05-03 15:13:24 -0400950 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400951 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400952 }
953
954 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
955 {
956 return false;
957 }
958
959 const gl::Caps &caps = context->getCaps();
960 if (texture != 0)
961 {
962 gl::Texture *tex = context->getTexture(texture);
963 ASSERT(tex);
964
965 switch (tex->getTarget())
966 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400968 {
969 if (level > gl::log2(caps.max2DTextureSize))
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.maxArrayTextureLayers)
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 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400984 {
985 if (level > gl::log2(caps.max3DTextureSize))
986 {
Jamie Madill437fa652016-05-03 15:13:24 -0400987 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400988 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400989 }
990
991 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
992 {
Jamie Madill437fa652016-05-03 15:13:24 -0400993 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400994 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400995 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400996 }
997 break;
998
He Yunchaoced53ae2016-11-29 15:00:51 +0800999 default:
1000 context->handleError(Error(GL_INVALID_OPERATION));
1001 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001002 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001003
Jamie Madilla3944d42016-07-22 22:13:26 -04001004 const auto &format = tex->getFormat(tex->getTarget(), level);
1005 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001006 {
Jamie Madill437fa652016-05-03 15:13:24 -04001007 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001008 return false;
1009 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001010 }
1011
1012 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001013}
1014
He Yunchaoced53ae2016-11-29 15:00:51 +08001015bool ValidateInvalidateFramebuffer(Context *context,
1016 GLenum target,
1017 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001018 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019{
Martin Radev1be913c2016-07-11 17:59:16 +03001020 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001021 {
Jamie Madill437fa652016-05-03 15:13:24 -04001022 context->handleError(
1023 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001024 return false;
1025 }
1026
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 bool defaultFramebuffer = false;
1028
1029 switch (target)
1030 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001031 case GL_DRAW_FRAMEBUFFER:
1032 case GL_FRAMEBUFFER:
1033 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1034 break;
1035 case GL_READ_FRAMEBUFFER:
1036 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1037 break;
1038 default:
1039 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 }
1042
He Yunchaoced53ae2016-11-29 15:00:51 +08001043 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1044 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045}
1046
Jamie Madillc29968b2016-01-20 11:17:23 -05001047bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001048{
Martin Radev1be913c2016-07-11 17:59:16 +03001049 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001052 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001053 }
1054
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001055 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001056 {
Jamie Madill437fa652016-05-03 15:13:24 -04001057 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001058 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001059 }
1060
1061 return true;
1062}
1063
Olli Etuaho71dfb362016-03-10 14:04:27 +02001064bool ValidateDrawRangeElements(Context *context,
1065 GLenum mode,
1066 GLuint start,
1067 GLuint end,
1068 GLsizei count,
1069 GLenum type,
1070 const GLvoid *indices,
1071 IndexRange *indexRange)
1072{
Martin Radev1be913c2016-07-11 17:59:16 +03001073 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001074 {
Jamie Madill437fa652016-05-03 15:13:24 -04001075 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001076 return false;
1077 }
1078
1079 if (end < start)
1080 {
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001082 return false;
1083 }
1084
1085 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1086 {
1087 return false;
1088 }
1089
1090 if (indexRange->end > end || indexRange->start < start)
1091 {
1092 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001093 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001094 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1095 return false;
1096 }
1097 return true;
1098}
1099
He Yunchaoced53ae2016-11-29 15:00:51 +08001100bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001101{
Martin Radev1be913c2016-07-11 17:59:16 +03001102 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001103 {
Jamie Madill437fa652016-05-03 15:13:24 -04001104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001105 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001106 }
1107
Jamie Madill78f41802014-08-25 15:47:55 -04001108 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001109}
1110
Jamie Madillb885e572015-02-03 16:16:04 -05001111bool ValidateReadBuffer(Context *context, GLenum src)
1112{
Martin Radev1be913c2016-07-11 17:59:16 +03001113 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001114 {
Jamie Madill437fa652016-05-03 15:13:24 -04001115 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001116 return false;
1117 }
1118
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001119 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001120
1121 if (readFBO == nullptr)
1122 {
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001124 return false;
1125 }
1126
1127 if (src == GL_NONE)
1128 {
1129 return true;
1130 }
1131
Olli Etuaho84c9f592016-03-09 14:37:25 +02001132 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001133 {
Jamie Madill437fa652016-05-03 15:13:24 -04001134 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001135 return false;
1136 }
1137
1138 if (readFBO->id() == 0)
1139 {
1140 if (src != GL_BACK)
1141 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001142 const char *errorMsg =
1143 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001144 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001145 return false;
1146 }
1147 }
1148 else
1149 {
1150 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1151
1152 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1153 {
1154 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001156 return false;
1157 }
1158 }
1159
1160 return true;
1161}
1162
Jamie Madill86af3d22015-07-21 15:14:07 -04001163bool ValidateCompressedTexImage3D(Context *context,
1164 GLenum target,
1165 GLint level,
1166 GLenum internalformat,
1167 GLsizei width,
1168 GLsizei height,
1169 GLsizei depth,
1170 GLint border,
1171 GLsizei imageSize,
1172 const GLvoid *data)
1173{
Martin Radev1be913c2016-07-11 17:59:16 +03001174 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001175 {
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001177 return false;
1178 }
1179
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001180 if (!ValidTextureTarget(context, target))
1181 {
1182 context->handleError(Error(GL_INVALID_ENUM));
1183 return false;
1184 }
1185
Jamie Madille2e406c2016-06-02 13:04:10 -04001186 // Validate image size
1187 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1188 {
1189 context->handleError(Error(GL_INVALID_VALUE));
1190 return false;
1191 }
1192
Geoff Langca271392017-04-05 12:30:00 -04001193 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001194 if (!formatInfo.compressed)
1195 {
1196 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1197 return false;
1198 }
1199
Jamie Madill513558d2016-06-02 13:04:11 -04001200 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001201 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001202 if (blockSizeOrErr.isError())
1203 {
Jamie Madill513558d2016-06-02 13:04:11 -04001204 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001205 return false;
1206 }
1207 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001210 return false;
1211 }
1212
1213 // 3D texture target validation
1214 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1215 {
Jamie Madill437fa652016-05-03 15:13:24 -04001216 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001217 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1218 return false;
1219 }
1220
1221 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001222 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001223 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1224 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001225 {
1226 return false;
1227 }
1228
1229 return true;
1230}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001231
Corentin Wallezb2931602017-04-11 15:58:57 -04001232bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1233 GLenum target,
1234 GLint level,
1235 GLenum internalformat,
1236 GLsizei width,
1237 GLsizei height,
1238 GLsizei depth,
1239 GLint border,
1240 GLsizei imageSize,
1241 GLsizei dataSize,
1242 const GLvoid *data)
1243{
1244 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1245 {
1246 return false;
1247 }
1248
1249 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1250 depth, border, imageSize, data);
1251}
1252
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253bool ValidateBindVertexArray(Context *context, GLuint array)
1254{
Martin Radev1be913c2016-07-11 17:59:16 +03001255 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001256 {
Jamie Madill437fa652016-05-03 15:13:24 -04001257 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001258 return false;
1259 }
1260
1261 return ValidateBindVertexArrayBase(context, array);
1262}
1263
Austin Kinrossbc781f32015-10-26 09:27:38 -07001264bool ValidateIsVertexArray(Context *context)
1265{
Martin Radev1be913c2016-07-11 17:59:16 +03001266 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001267 {
Jamie Madill437fa652016-05-03 15:13:24 -04001268 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001269 return false;
1270 }
1271
1272 return true;
1273}
Geoff Langc5629752015-12-07 16:29:04 -05001274
Jiajia Qin6eafb042016-12-27 17:04:07 +08001275static bool ValidateBindBufferCommon(Context *context,
1276 GLenum target,
1277 GLuint index,
1278 GLuint buffer,
1279 GLintptr offset,
1280 GLsizeiptr size)
1281{
1282 if (context->getClientMajorVersion() < 3)
1283 {
1284 context->handleError(Error(GL_INVALID_OPERATION));
1285 return false;
1286 }
1287
1288 if (buffer != 0 && offset < 0)
1289 {
1290 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1291 return false;
1292 }
1293
1294 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1295 !context->isBufferGenerated(buffer))
1296 {
1297 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1298 return false;
1299 }
1300
1301 const Caps &caps = context->getCaps();
1302 switch (target)
1303 {
1304 case GL_TRANSFORM_FEEDBACK_BUFFER:
1305 {
1306 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1307 {
1308 context->handleError(Error(GL_INVALID_VALUE,
1309 "index is greater than or equal to the number of "
1310 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1311 return false;
1312 }
1313 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1314 {
1315 context->handleError(
1316 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1317 return false;
1318 }
1319
1320 TransformFeedback *curTransformFeedback =
1321 context->getGLState().getCurrentTransformFeedback();
1322 if (curTransformFeedback && curTransformFeedback->isActive())
1323 {
1324 context->handleError(Error(GL_INVALID_OPERATION,
1325 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1326 "feedback is currently active."));
1327 return false;
1328 }
1329 break;
1330 }
1331 case GL_UNIFORM_BUFFER:
1332 {
1333 if (index >= caps.maxUniformBufferBindings)
1334 {
1335 context->handleError(Error(GL_INVALID_VALUE,
1336 "index is greater than or equal to the number of "
1337 "UNIFORM_BUFFER indexed binding points."));
1338 return false;
1339 }
1340
1341 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1342 {
1343 context->handleError(
1344 Error(GL_INVALID_VALUE,
1345 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1346 return false;
1347 }
1348 break;
1349 }
1350 case GL_ATOMIC_COUNTER_BUFFER:
1351 {
1352 if (context->getClientVersion() < ES_3_1)
1353 {
Yunchao He61afff12017-03-14 15:34:03 +08001354 context->handleError(Error(
1355 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001356 return false;
1357 }
1358 if (index >= caps.maxAtomicCounterBufferBindings)
1359 {
1360 context->handleError(Error(GL_INVALID_VALUE,
1361 "index is greater than or equal to the number of "
1362 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1363 return false;
1364 }
1365 if (buffer != 0 && (offset % 4) != 0)
1366 {
1367 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1368 return false;
1369 }
1370 break;
1371 }
1372 case GL_SHADER_STORAGE_BUFFER:
1373 {
1374 if (context->getClientVersion() < ES_3_1)
1375 {
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001376 context->handleError(
1377 Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
1378 return false;
1379 }
1380 if (index >= caps.maxShaderStorageBufferBindings)
1381 {
1382 context->handleError(Error(GL_INVALID_VALUE,
1383 "index is greater than or equal to the number of "
1384 "SHADER_STORAGE_BUFFER indexed binding points."));
1385 return false;
1386 }
1387 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1388 {
Yunchao He61afff12017-03-14 15:34:03 +08001389 context->handleError(Error(
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001390 GL_INVALID_VALUE,
1391 "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001392 return false;
1393 }
1394 break;
1395 }
1396 default:
1397 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1398 return false;
1399 }
1400
1401 return true;
1402}
1403
1404bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1405{
1406 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1407}
1408
1409bool ValidateBindBufferRange(Context *context,
1410 GLenum target,
1411 GLuint index,
1412 GLuint buffer,
1413 GLintptr offset,
1414 GLsizeiptr size)
1415{
1416 if (buffer != 0 && size <= 0)
1417 {
1418 context->handleError(
1419 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1420 return false;
1421 }
1422 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1423}
1424
Geoff Langc5629752015-12-07 16:29:04 -05001425bool ValidateProgramBinary(Context *context,
1426 GLuint program,
1427 GLenum binaryFormat,
1428 const void *binary,
1429 GLint length)
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 ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1438}
1439
1440bool ValidateGetProgramBinary(Context *context,
1441 GLuint program,
1442 GLsizei bufSize,
1443 GLsizei *length,
1444 GLenum *binaryFormat,
1445 void *binary)
1446{
Martin Radev1be913c2016-07-11 17:59:16 +03001447 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001448 {
Jamie Madill437fa652016-05-03 15:13:24 -04001449 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001450 return false;
1451 }
1452
1453 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1454}
1455
Olli Etuahof0fee072016-03-30 15:11:58 +03001456bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001457{
Martin Radev1be913c2016-07-11 17:59:16 +03001458 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001459 {
Jamie Madill437fa652016-05-03 15:13:24 -04001460 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001461 return false;
1462 }
1463
1464 if (GetValidProgram(context, program) == nullptr)
1465 {
1466 return false;
1467 }
1468
1469 switch (pname)
1470 {
1471 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001472 if (value != GL_FALSE && value != GL_TRUE)
1473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001475 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1476 return false;
1477 }
Geoff Langc5629752015-12-07 16:29:04 -05001478 break;
1479
Yunchao He61afff12017-03-14 15:34:03 +08001480 case GL_PROGRAM_SEPARABLE:
1481 if (context->getClientVersion() < ES_3_1)
1482 {
1483 context->handleError(
1484 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1485 return false;
1486 }
1487
1488 if (value != GL_FALSE && value != GL_TRUE)
1489 {
1490 context->handleError(Error(
1491 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1492 return false;
1493 }
1494 break;
1495
Geoff Langc5629752015-12-07 16:29:04 -05001496 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001497 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001498 return false;
1499 }
1500
1501 return true;
1502}
Jamie Madillc29968b2016-01-20 11:17:23 -05001503
1504bool ValidateBlitFramebuffer(Context *context,
1505 GLint srcX0,
1506 GLint srcY0,
1507 GLint srcX1,
1508 GLint srcY1,
1509 GLint dstX0,
1510 GLint dstY0,
1511 GLint dstX1,
1512 GLint dstY1,
1513 GLbitfield mask,
1514 GLenum filter)
1515{
Martin Radev1be913c2016-07-11 17:59:16 +03001516 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001517 {
Jamie Madill437fa652016-05-03 15:13:24 -04001518 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001519 return false;
1520 }
1521
1522 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1523 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524}
Jamie Madillc29968b2016-01-20 11:17:23 -05001525
1526bool ValidateClearBufferiv(ValidationContext *context,
1527 GLenum buffer,
1528 GLint drawbuffer,
1529 const GLint *value)
1530{
1531 switch (buffer)
1532 {
1533 case GL_COLOR:
1534 if (drawbuffer < 0 ||
1535 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001538 return false;
1539 }
Geoff Lang76e65652017-03-27 14:58:02 -04001540 if (context->getExtensions().webglCompatibility)
1541 {
1542 constexpr GLenum validComponentTypes[] = {GL_INT};
1543 if (ValidateWebGLFramebufferAttachmentClearType(
1544 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1545 {
1546 return false;
1547 }
1548 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001549 break;
1550
1551 case GL_STENCIL:
1552 if (drawbuffer != 0)
1553 {
Jamie Madill437fa652016-05-03 15:13:24 -04001554 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001555 return false;
1556 }
1557 break;
1558
1559 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001560 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
1562 }
1563
1564 return ValidateClearBuffer(context);
1565}
1566
1567bool ValidateClearBufferuiv(ValidationContext *context,
1568 GLenum buffer,
1569 GLint drawbuffer,
1570 const GLuint *value)
1571{
1572 switch (buffer)
1573 {
1574 case GL_COLOR:
1575 if (drawbuffer < 0 ||
1576 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001579 return false;
1580 }
Geoff Lang76e65652017-03-27 14:58:02 -04001581 if (context->getExtensions().webglCompatibility)
1582 {
1583 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1584 if (ValidateWebGLFramebufferAttachmentClearType(
1585 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1586 {
1587 return false;
1588 }
1589 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001590 break;
1591
1592 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001593 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001594 return false;
1595 }
1596
1597 return ValidateClearBuffer(context);
1598}
1599
1600bool ValidateClearBufferfv(ValidationContext *context,
1601 GLenum buffer,
1602 GLint drawbuffer,
1603 const GLfloat *value)
1604{
1605 switch (buffer)
1606 {
1607 case GL_COLOR:
1608 if (drawbuffer < 0 ||
1609 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1610 {
Jamie Madill437fa652016-05-03 15:13:24 -04001611 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001612 return false;
1613 }
Geoff Lang76e65652017-03-27 14:58:02 -04001614 if (context->getExtensions().webglCompatibility)
1615 {
1616 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1617 GL_SIGNED_NORMALIZED};
1618 if (ValidateWebGLFramebufferAttachmentClearType(
1619 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1620 {
1621 return false;
1622 }
1623 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001624 break;
1625
1626 case GL_DEPTH:
1627 if (drawbuffer != 0)
1628 {
Jamie Madill437fa652016-05-03 15:13:24 -04001629 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001630 return false;
1631 }
1632 break;
1633
1634 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001635 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001636 return false;
1637 }
1638
1639 return ValidateClearBuffer(context);
1640}
1641
1642bool ValidateClearBufferfi(ValidationContext *context,
1643 GLenum buffer,
1644 GLint drawbuffer,
1645 GLfloat depth,
1646 GLint stencil)
1647{
1648 switch (buffer)
1649 {
1650 case GL_DEPTH_STENCIL:
1651 if (drawbuffer != 0)
1652 {
Jamie Madill437fa652016-05-03 15:13:24 -04001653 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001654 return false;
1655 }
1656 break;
1657
1658 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001659 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001660 return false;
1661 }
1662
1663 return ValidateClearBuffer(context);
1664}
1665
1666bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1667{
Martin Radev1be913c2016-07-11 17:59:16 +03001668 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001671 return false;
1672 }
1673
1674 return ValidateDrawBuffersBase(context, n, bufs);
1675}
1676
1677bool ValidateCopyTexSubImage3D(Context *context,
1678 GLenum target,
1679 GLint level,
1680 GLint xoffset,
1681 GLint yoffset,
1682 GLint zoffset,
1683 GLint x,
1684 GLint y,
1685 GLsizei width,
1686 GLsizei height)
1687{
Martin Radev1be913c2016-07-11 17:59:16 +03001688 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 return false;
1692 }
1693
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001694 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1695 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001696}
1697
Jamie Madill73a84962016-02-12 09:27:23 -05001698bool ValidateTexImage3D(Context *context,
1699 GLenum target,
1700 GLint level,
1701 GLint internalformat,
1702 GLsizei width,
1703 GLsizei height,
1704 GLsizei depth,
1705 GLint border,
1706 GLenum format,
1707 GLenum type,
1708 const GLvoid *pixels)
1709{
Martin Radev1be913c2016-07-11 17:59:16 +03001710 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001711 {
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001713 return false;
1714 }
1715
1716 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001717 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001718 pixels);
1719}
1720
Geoff Langc52f6f12016-10-14 10:18:00 -04001721bool ValidateTexImage3DRobustANGLE(Context *context,
1722 GLenum target,
1723 GLint level,
1724 GLint internalformat,
1725 GLsizei width,
1726 GLsizei height,
1727 GLsizei depth,
1728 GLint border,
1729 GLenum format,
1730 GLenum type,
1731 GLsizei bufSize,
1732 const GLvoid *pixels)
1733{
1734 if (context->getClientMajorVersion() < 3)
1735 {
1736 context->handleError(Error(GL_INVALID_OPERATION));
1737 return false;
1738 }
1739
1740 if (!ValidateRobustEntryPoint(context, bufSize))
1741 {
1742 return false;
1743 }
1744
1745 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1746 0, 0, width, height, depth, border, format, type,
1747 bufSize, pixels);
1748}
1749
Jamie Madill73a84962016-02-12 09:27:23 -05001750bool ValidateTexSubImage3D(Context *context,
1751 GLenum target,
1752 GLint level,
1753 GLint xoffset,
1754 GLint yoffset,
1755 GLint zoffset,
1756 GLsizei width,
1757 GLsizei height,
1758 GLsizei depth,
1759 GLenum format,
1760 GLenum type,
1761 const GLvoid *pixels)
1762{
Martin Radev1be913c2016-07-11 17:59:16 +03001763 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001766 return false;
1767 }
1768
1769 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1770 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001771 -1, pixels);
1772}
1773
1774bool ValidateTexSubImage3DRobustANGLE(Context *context,
1775 GLenum target,
1776 GLint level,
1777 GLint xoffset,
1778 GLint yoffset,
1779 GLint zoffset,
1780 GLsizei width,
1781 GLsizei height,
1782 GLsizei depth,
1783 GLenum format,
1784 GLenum type,
1785 GLsizei bufSize,
1786 const GLvoid *pixels)
1787{
1788 if (context->getClientMajorVersion() < 3)
1789 {
1790 context->handleError(Error(GL_INVALID_OPERATION));
1791 return false;
1792 }
1793
1794 if (!ValidateRobustEntryPoint(context, bufSize))
1795 {
1796 return false;
1797 }
1798
1799 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1800 yoffset, zoffset, width, height, depth, 0, format, type,
1801 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001802}
1803
1804bool ValidateCompressedTexSubImage3D(Context *context,
1805 GLenum target,
1806 GLint level,
1807 GLint xoffset,
1808 GLint yoffset,
1809 GLint zoffset,
1810 GLsizei width,
1811 GLsizei height,
1812 GLsizei depth,
1813 GLenum format,
1814 GLsizei imageSize,
1815 const GLvoid *data)
1816{
Martin Radev1be913c2016-07-11 17:59:16 +03001817 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001818 {
Jamie Madill437fa652016-05-03 15:13:24 -04001819 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001820 return false;
1821 }
1822
Geoff Langca271392017-04-05 12:30:00 -04001823 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001824 if (!formatInfo.compressed)
1825 {
1826 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1827 return false;
1828 }
1829
Jamie Madill513558d2016-06-02 13:04:11 -04001830 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001831 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001832 if (blockSizeOrErr.isError())
1833 {
1834 context->handleError(blockSizeOrErr.getError());
1835 return false;
1836 }
1837 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001838 {
Jamie Madill437fa652016-05-03 15:13:24 -04001839 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001840 return false;
1841 }
1842
1843 if (!data)
1844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001846 return false;
1847 }
1848
1849 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001850 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001851}
Corentin Wallezb2931602017-04-11 15:58:57 -04001852bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1853 GLenum target,
1854 GLint level,
1855 GLint xoffset,
1856 GLint yoffset,
1857 GLint zoffset,
1858 GLsizei width,
1859 GLsizei height,
1860 GLsizei depth,
1861 GLenum format,
1862 GLsizei imageSize,
1863 GLsizei dataSize,
1864 const GLvoid *data)
1865{
1866 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1867 {
1868 return false;
1869 }
1870
1871 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1872 height, depth, format, imageSize, data);
1873}
Jamie Madill73a84962016-02-12 09:27:23 -05001874
Olli Etuaho41997e72016-03-10 13:38:39 +02001875bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1876{
1877 return ValidateGenOrDeleteES3(context, n);
1878}
1879
1880bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1881{
1882 return ValidateGenOrDeleteES3(context, n);
1883}
1884
1885bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1886{
1887 return ValidateGenOrDeleteCountES3(context, count);
1888}
1889
1890bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1891{
1892 return ValidateGenOrDeleteCountES3(context, count);
1893}
1894
1895bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1896{
1897 return ValidateGenOrDeleteES3(context, n);
1898}
1899
1900bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1901{
1902 if (!ValidateGenOrDeleteES3(context, n))
1903 {
1904 return false;
1905 }
1906 for (GLint i = 0; i < n; ++i)
1907 {
1908 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1909 if (transformFeedback != nullptr && transformFeedback->isActive())
1910 {
1911 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001913 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1914 return false;
1915 }
1916 }
1917 return true;
1918}
1919
1920bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1921{
1922 return ValidateGenOrDeleteES3(context, n);
1923}
1924
1925bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1926{
1927 return ValidateGenOrDeleteES3(context, n);
1928}
1929
1930bool ValidateGenOrDeleteES3(Context *context, GLint n)
1931{
Martin Radev1be913c2016-07-11 17:59:16 +03001932 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001933 {
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001935 return false;
1936 }
1937 return ValidateGenOrDelete(context, n);
1938}
1939
1940bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1941{
Martin Radev1be913c2016-07-11 17:59:16 +03001942 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001945 return false;
1946 }
1947 if (count < 0)
1948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001950 return false;
1951 }
1952 return true;
1953}
1954
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001955bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1956{
Martin Radev1be913c2016-07-11 17:59:16 +03001957 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001958 {
Jamie Madill437fa652016-05-03 15:13:24 -04001959 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001960 return false;
1961 }
1962 switch (primitiveMode)
1963 {
1964 case GL_TRIANGLES:
1965 case GL_LINES:
1966 case GL_POINTS:
1967 break;
1968
1969 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001970 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001971 return false;
1972 }
1973
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001974 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001975 ASSERT(transformFeedback != nullptr);
1976
1977 if (transformFeedback->isActive())
1978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001980 return false;
1981 }
1982 return true;
1983}
1984
Olli Etuaho4f667482016-03-30 15:56:35 +03001985bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1986{
Geoff Lang496c02d2016-10-20 11:38:11 -07001987 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1988}
1989
1990bool ValidateGetBufferPointervRobustANGLE(Context *context,
1991 GLenum target,
1992 GLenum pname,
1993 GLsizei bufSize,
1994 GLsizei *length,
1995 GLvoid **params)
1996{
1997 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001998 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001999 return false;
2000 }
2001
Geoff Lang496c02d2016-10-20 11:38:11 -07002002 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2003 {
2004 return false;
2005 }
2006
2007 if (!ValidateRobustBufferSize(context, bufSize, *length))
2008 {
2009 return false;
2010 }
2011
2012 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002013}
2014
2015bool ValidateUnmapBuffer(Context *context, GLenum target)
2016{
Martin Radev1be913c2016-07-11 17:59:16 +03002017 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002020 return false;
2021 }
2022
2023 return ValidateUnmapBufferBase(context, target);
2024}
2025
2026bool ValidateMapBufferRange(Context *context,
2027 GLenum target,
2028 GLintptr offset,
2029 GLsizeiptr length,
2030 GLbitfield access)
2031{
Martin Radev1be913c2016-07-11 17:59:16 +03002032 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002033 {
Jamie Madill437fa652016-05-03 15:13:24 -04002034 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002035 return false;
2036 }
2037
2038 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2039}
2040
2041bool ValidateFlushMappedBufferRange(Context *context,
2042 GLenum target,
2043 GLintptr offset,
2044 GLsizeiptr length)
2045{
Martin Radev1be913c2016-07-11 17:59:16 +03002046 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002047 {
Jamie Madill437fa652016-05-03 15:13:24 -04002048 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002049 return false;
2050 }
2051
2052 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2053}
2054
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002055bool ValidateIndexedStateQuery(ValidationContext *context,
2056 GLenum pname,
2057 GLuint index,
2058 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002059{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002060 if (length)
2061 {
2062 *length = 0;
2063 }
2064
Martin Radev66fb8202016-07-28 11:45:20 +03002065 GLenum nativeType;
2066 unsigned int numParams;
2067 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2068 {
2069 context->handleError(Error(GL_INVALID_ENUM));
2070 return false;
2071 }
2072
2073 const Caps &caps = context->getCaps();
2074 switch (pname)
2075 {
2076 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2077 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2078 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2079 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2080 {
2081 context->handleError(Error(GL_INVALID_VALUE));
2082 return false;
2083 }
2084 break;
2085
2086 case GL_UNIFORM_BUFFER_START:
2087 case GL_UNIFORM_BUFFER_SIZE:
2088 case GL_UNIFORM_BUFFER_BINDING:
2089 if (index >= caps.maxUniformBufferBindings)
2090 {
2091 context->handleError(Error(GL_INVALID_VALUE));
2092 return false;
2093 }
2094 break;
Shao80957d92017-02-20 21:25:59 +08002095
Martin Radev66fb8202016-07-28 11:45:20 +03002096 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2097 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2098 if (index >= 3u)
2099 {
2100 context->handleError(Error(GL_INVALID_VALUE));
2101 return false;
2102 }
2103 break;
Shao80957d92017-02-20 21:25:59 +08002104
Jiajia Qin6eafb042016-12-27 17:04:07 +08002105 case GL_ATOMIC_COUNTER_BUFFER_START:
2106 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2107 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2108 if (context->getClientVersion() < ES_3_1)
2109 {
2110 context->handleError(
2111 Error(GL_INVALID_ENUM,
2112 "Atomic Counter buffers are not supported in this version of GL"));
2113 return false;
2114 }
2115 if (index >= caps.maxAtomicCounterBufferBindings)
2116 {
2117 context->handleError(
2118 Error(GL_INVALID_VALUE,
2119 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2120 return false;
2121 }
2122 break;
Shao80957d92017-02-20 21:25:59 +08002123
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002124 case GL_SHADER_STORAGE_BUFFER_START:
2125 case GL_SHADER_STORAGE_BUFFER_SIZE:
2126 case GL_SHADER_STORAGE_BUFFER_BINDING:
2127 if (context->getClientVersion() < ES_3_1)
2128 {
2129 context->handleError(
2130 Error(GL_INVALID_ENUM,
2131 "Shader storage buffers are not supported in this version of GL"));
2132 return false;
2133 }
2134 if (index >= caps.maxShaderStorageBufferBindings)
2135 {
2136 context->handleError(
2137 Error(GL_INVALID_VALUE,
2138 "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
2139 return false;
2140 }
2141 break;
2142
Shao80957d92017-02-20 21:25:59 +08002143 case GL_VERTEX_BINDING_BUFFER:
2144 case GL_VERTEX_BINDING_DIVISOR:
2145 case GL_VERTEX_BINDING_OFFSET:
2146 case GL_VERTEX_BINDING_STRIDE:
2147 if (context->getClientVersion() < ES_3_1)
2148 {
2149 context->handleError(
2150 Error(GL_INVALID_ENUM,
2151 "Vertex Attrib Bindings are not supported in this version of GL"));
2152 return false;
2153 }
2154 if (index >= caps.maxVertexAttribBindings)
2155 {
2156 context->handleError(
2157 Error(GL_INVALID_VALUE,
2158 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2159 return false;
2160 }
2161 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002162 default:
2163 context->handleError(Error(GL_INVALID_ENUM));
2164 return false;
2165 }
2166
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002167 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002168 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002169 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002170 }
2171
2172 return true;
2173}
2174
2175bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2176{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002177 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002178 {
2179 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2180 return false;
2181 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002182 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002183}
2184
Geoff Langcf255ea2016-10-20 11:39:09 -07002185bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2186 GLenum target,
2187 GLuint index,
2188 GLsizei bufSize,
2189 GLsizei *length,
2190 GLint *data)
2191{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002192 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002193 {
2194 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2195 return false;
2196 }
2197
2198 if (!ValidateRobustEntryPoint(context, bufSize))
2199 {
2200 return false;
2201 }
2202
2203 if (!ValidateIndexedStateQuery(context, target, index, length))
2204 {
2205 return false;
2206 }
2207
2208 if (!ValidateRobustBufferSize(context, bufSize, *length))
2209 {
2210 return false;
2211 }
2212
2213 return true;
2214}
2215
Martin Radev66fb8202016-07-28 11:45:20 +03002216bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2217{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002218 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002219 {
2220 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2221 return false;
2222 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002223 return ValidateIndexedStateQuery(context, target, index, nullptr);
2224}
2225
2226bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2227 GLenum target,
2228 GLuint index,
2229 GLsizei bufSize,
2230 GLsizei *length,
2231 GLint64 *data)
2232{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002233 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002234 {
2235 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2236 return false;
2237 }
2238
2239 if (!ValidateRobustEntryPoint(context, bufSize))
2240 {
2241 return false;
2242 }
2243
2244 if (!ValidateIndexedStateQuery(context, target, index, length))
2245 {
2246 return false;
2247 }
2248
2249 if (!ValidateRobustBufferSize(context, bufSize, *length))
2250 {
2251 return false;
2252 }
2253
2254 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002255}
2256
Jamie Madillb0817d12016-11-01 15:48:31 -04002257bool ValidateCopyBufferSubData(ValidationContext *context,
2258 GLenum readTarget,
2259 GLenum writeTarget,
2260 GLintptr readOffset,
2261 GLintptr writeOffset,
2262 GLsizeiptr size)
2263{
2264 if (context->getClientMajorVersion() < 3)
2265 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002266 context->handleError(
2267 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002268 return false;
2269 }
2270
2271 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2272 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002273 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002274 return false;
2275 }
2276
2277 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2278 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2279
2280 if (!readBuffer || !writeBuffer)
2281 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002282 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002283 return false;
2284 }
2285
2286 // Verify that readBuffer and writeBuffer are not currently mapped
2287 if (readBuffer->isMapped() || writeBuffer->isMapped())
2288 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002289 context->handleError(
2290 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002291 return false;
2292 }
2293
Jamie Madilld2f0c742016-11-02 10:34:41 -04002294 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2295 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2296 CheckedNumeric<GLintptr> checkedSize(size);
2297
2298 auto checkedReadSum = checkedReadOffset + checkedSize;
2299 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2300
2301 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2302 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2303 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002304 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002305 context->handleError(
2306 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002307 return false;
2308 }
2309
Jamie Madilld2f0c742016-11-02 10:34:41 -04002310 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002311 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002312 context->handleError(
2313 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002314 return false;
2315 }
2316
Jamie Madilld2f0c742016-11-02 10:34:41 -04002317 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2318 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2319 {
2320 context->handleError(
2321 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2322 return false;
2323 }
2324
2325 if (readBuffer == writeBuffer)
2326 {
2327 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2328 if (!checkedOffsetDiff.IsValid())
2329 {
2330 // This shold not be possible.
2331 UNREACHABLE();
2332 context->handleError(
2333 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2334 return false;
2335 }
2336
2337 if (checkedOffsetDiff.ValueOrDie() < size)
2338 {
2339 context->handleError(Error(GL_INVALID_VALUE));
2340 return false;
2341 }
2342 }
2343
Jamie Madillb0817d12016-11-01 15:48:31 -04002344 return true;
2345}
2346
Geoff Langc339c4e2016-11-29 10:37:36 -05002347bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2348{
2349 if (context->getClientMajorVersion() < 3)
2350 {
2351 context->handleError(
2352 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2353 return false;
2354 }
2355
2356 switch (name)
2357 {
2358 case GL_EXTENSIONS:
2359 if (index >= context->getExtensionStringCount())
2360 {
2361 context->handleError(Error(
2362 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2363 return false;
2364 }
2365 break;
2366
2367 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2368 if (!context->getExtensions().requestExtension)
2369 {
2370 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2371 return false;
2372 }
2373 if (index >= context->getRequestableExtensionStringCount())
2374 {
2375 context->handleError(
2376 Error(GL_INVALID_VALUE,
2377 "index must be less than the number of requestable extension strings."));
2378 return false;
2379 }
2380 break;
2381
2382 default:
2383 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2384 return false;
2385 }
2386
2387 return true;
2388}
2389
Jamie Madille8fb6402017-02-14 17:56:40 -05002390bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2391 GLenum target,
2392 GLsizei samples,
2393 GLenum internalformat,
2394 GLsizei width,
2395 GLsizei height)
2396{
2397 if (context->getClientMajorVersion() < 3)
2398 {
2399 context->handleError(Error(GL_INVALID_OPERATION));
2400 return false;
2401 }
2402
2403 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2404 height))
2405 {
2406 return false;
2407 }
2408
2409 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2410 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002411 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002412 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2413 samples > 0)
2414 {
2415 context->handleError(Error(GL_INVALID_OPERATION));
2416 return false;
2417 }
2418
2419 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2420 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2421 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2422 {
2423 context->handleError(
2424 Error(GL_INVALID_OPERATION,
2425 "Samples must not be greater than maximum supported value for the format."));
2426 return false;
2427 }
2428
2429 return true;
2430}
2431
Geoff Langaa086d62017-03-23 16:47:21 -04002432bool ValidateVertexAttribIPointer(ValidationContext *context,
2433 GLuint index,
2434 GLint size,
2435 GLenum type,
2436 GLsizei stride,
2437 const GLvoid *pointer)
2438{
2439 if (context->getClientMajorVersion() < 3)
2440 {
Geoff Langaa086d62017-03-23 16:47:21 -04002441 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002442 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002443 return false;
2444 }
2445
Shao80957d92017-02-20 21:25:59 +08002446 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002447 {
Geoff Langaa086d62017-03-23 16:47:21 -04002448 return false;
2449 }
2450
Geoff Langaa086d62017-03-23 16:47:21 -04002451 if (stride < 0)
2452 {
Shao80957d92017-02-20 21:25:59 +08002453 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002454 return false;
2455 }
2456
Shao80957d92017-02-20 21:25:59 +08002457 const Caps &caps = context->getCaps();
2458 if (context->getClientVersion() >= ES_3_1)
2459 {
2460 if (stride > caps.maxVertexAttribStride)
2461 {
2462 context->handleError(
2463 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2464 return false;
2465 }
2466
2467 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2468 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2469 // validation should be inherited.
2470 if (index >= caps.maxVertexAttribBindings)
2471 {
2472 context->handleError(
2473 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2474 return false;
2475 }
2476 }
2477
Geoff Langaa086d62017-03-23 16:47:21 -04002478 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2479 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2480 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2481 // and the pointer argument is not NULL.
2482 if (context->getGLState().getVertexArrayId() != 0 &&
2483 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2484 {
2485 context->handleError(
2486 Error(GL_INVALID_OPERATION,
2487 "Client data cannot be used with a non-default vertex array object."));
2488 return false;
2489 }
2490
Geoff Lang2d62ab72017-03-23 16:54:40 -04002491 if (context->getExtensions().webglCompatibility)
2492 {
2493 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2494 {
2495 return false;
2496 }
2497 }
2498
Geoff Langaa086d62017-03-23 16:47:21 -04002499 return true;
2500}
2501
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002502bool ValidateGetSynciv(Context *context,
2503 GLsync sync,
2504 GLenum pname,
2505 GLsizei bufSize,
2506 GLsizei *length,
2507 GLint *values)
2508{
2509 if (context->getClientMajorVersion() < 3)
2510 {
2511 context->handleError(
2512 Error(GL_INVALID_OPERATION, "GetSynciv requires OpenGL ES 3.0 or higher."));
2513 return false;
2514 }
2515
2516 if (bufSize < 0)
2517 {
2518 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
2519 return false;
2520 }
2521
2522 FenceSync *fenceSync = context->getFenceSync(sync);
2523 if (!fenceSync)
2524 {
2525 context->handleError(Error(GL_INVALID_VALUE, "Invalid sync object."));
2526 return false;
2527 }
2528
2529 switch (pname)
2530 {
2531 case GL_OBJECT_TYPE:
2532 case GL_SYNC_CONDITION:
2533 case GL_SYNC_FLAGS:
2534 case GL_SYNC_STATUS:
2535 break;
2536
2537 default:
2538 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
2539 return false;
2540 }
2541
2542 return true;
2543}
2544
Jamie Madillc29968b2016-01-20 11:17:23 -05002545} // namespace gl