blob: 5cba4918fec1309efbda2c93a647a4c4738d6311 [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,
28 GLenum internalFormat,
29 GLenum format,
30 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040031{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050032 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
33 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
34 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
35 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -040036 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Langeb66a6e2016-10-31 13:06:12 -040037 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -040038 {
Jamie Madill437fa652016-05-03 15:13:24 -040039 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040040 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040041 }
42
43 // The type and format are valid if any supported internal format has that type and format
Jamie Madill55e98212016-10-05 16:39:13 -040044 if (!ValidES3Format(format) || !ValidES3Type(type))
Geoff Lang5d601382014-07-22 15:14:06 -040045 {
Jamie Madill437fa652016-05-03 15:13:24 -040046 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -040047 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040048 }
49
50 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040051 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040052 {
Jamie Madill437fa652016-05-03 15:13:24 -040053 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -040054 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040055 }
56
57 return true;
58}
59
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050060bool ValidateES3TexImageParametersBase(Context *context,
61 GLenum target,
62 GLint level,
63 GLenum internalformat,
64 bool isCompressed,
65 bool isSubImage,
66 GLint xoffset,
67 GLint yoffset,
68 GLint zoffset,
69 GLsizei width,
70 GLsizei height,
71 GLsizei depth,
72 GLint border,
73 GLenum format,
74 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -040075 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050076 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040077{
78 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -070079 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040083 }
84
Geoff Lange8ebe7f2013-08-05 15:03:13 -040085 // Verify zero border
86 if (border != 0)
87 {
Jamie Madill437fa652016-05-03 15:13:24 -040088 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040090 }
91
Jamie Madill6f38f822014-06-06 17:12:20 -040092 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
93 std::numeric_limits<GLsizei>::max() - xoffset < width ||
94 std::numeric_limits<GLsizei>::max() - yoffset < height ||
95 std::numeric_limits<GLsizei>::max() - zoffset < depth)
96 {
Jamie Madill437fa652016-05-03 15:13:24 -040097 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040098 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040099 }
100
Geoff Langaae65a42014-05-26 12:43:44 -0400101 const gl::Caps &caps = context->getCaps();
102
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400103 switch (target)
104 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800105 case GL_TEXTURE_2D:
106 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
107 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
108 {
109 context->handleError(Error(GL_INVALID_VALUE));
110 return false;
111 }
112 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400113
He Yunchaoced53ae2016-11-29 15:00:51 +0800114 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
115 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
116 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
117 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
118 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
119 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
120 if (!isSubImage && width != height)
121 {
122 context->handleError(Error(GL_INVALID_VALUE));
123 return false;
124 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400125
He Yunchaoced53ae2016-11-29 15:00:51 +0800126 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
127 {
128 context->handleError(Error(GL_INVALID_VALUE));
129 return false;
130 }
131 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400132
He Yunchaoced53ae2016-11-29 15:00:51 +0800133 case GL_TEXTURE_3D:
134 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
135 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
136 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
137 {
138 context->handleError(Error(GL_INVALID_VALUE));
139 return false;
140 }
141 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400142
He Yunchaoced53ae2016-11-29 15:00:51 +0800143 case GL_TEXTURE_2D_ARRAY:
144 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
145 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
146 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
147 {
148 context->handleError(Error(GL_INVALID_VALUE));
149 return false;
150 }
151 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400152
He Yunchaoced53ae2016-11-29 15:00:51 +0800153 default:
154 context->handleError(Error(GL_INVALID_ENUM));
155 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 }
157
He Yunchaoced53ae2016-11-29 15:00:51 +0800158 gl::Texture *texture =
159 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160 if (!texture)
161 {
Jamie Madill437fa652016-05-03 15:13:24 -0400162 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400163 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400164 }
165
Geoff Lang69cce582015-09-17 13:20:36 -0400166 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400167 {
Jamie Madill437fa652016-05-03 15:13:24 -0400168 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400169 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400170 }
171
172 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400173 GLenum actualInternalFormat =
174 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500175 if (isSubImage && actualInternalFormat == GL_NONE)
176 {
177 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
178 return false;
179 }
180
Geoff Lang5d601382014-07-22 15:14:06 -0400181 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 if (isCompressed)
183 {
tmartino7c102692015-10-02 16:43:40 -0400184 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400185 {
Jamie Madill437fa652016-05-03 15:13:24 -0400186 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400187 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400188 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400189 }
190
Geoff Lang44ff5a72017-02-03 15:15:43 -0500191 if (!ValidCompressedImageSize(context, actualInternalFormat, xoffset, yoffset, width,
192 height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400193 {
Jamie Madill437fa652016-05-03 15:13:24 -0400194 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400195 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400196 }
197
Geoff Langeb66a6e2016-10-31 13:06:12 -0400198 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400199 {
Jamie Madill437fa652016-05-03 15:13:24 -0400200 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400201 return false;
202 }
203
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400204 if (target == GL_TEXTURE_3D)
205 {
Jamie Madill437fa652016-05-03 15:13:24 -0400206 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400207 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400208 }
209 }
210 else
211 {
Geoff Langbaadf232014-08-04 13:58:02 -0400212 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400213 {
Geoff Lang5d601382014-07-22 15:14:06 -0400214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400215 }
216
217 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
218 {
Jamie Madill437fa652016-05-03 15:13:24 -0400219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400220 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400221 }
222 }
223
224 // Validate sub image parameters
225 if (isSubImage)
226 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500227 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400228 {
Jamie Madill437fa652016-05-03 15:13:24 -0400229 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400231 }
232
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400233 if (width == 0 || height == 0 || depth == 0)
234 {
235 return false;
236 }
237
238 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
239 {
Jamie Madill437fa652016-05-03 15:13:24 -0400240 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400241 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400242 }
243
244 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
245 std::numeric_limits<GLsizei>::max() - yoffset < height ||
246 std::numeric_limits<GLsizei>::max() - zoffset < depth)
247 {
Jamie Madill437fa652016-05-03 15:13:24 -0400248 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400249 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400250 }
251
Geoff Langa9be0dc2014-12-17 12:34:40 -0500252 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
253 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
254 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 {
Jamie Madill437fa652016-05-03 15:13:24 -0400256 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400257 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258 }
259 }
260
Geoff Langff5b2d52016-09-07 11:32:23 -0400261 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
262 imageSize))
263 {
264 return false;
265 }
266
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400267 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700268 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400269 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400270 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800271 // ...data is not evenly divisible into the number of bytes needed to store in memory a
272 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400273 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400274 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400275 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400276 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400277 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
278
Geoff Langff5b2d52016-09-07 11:32:23 -0400279 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400280 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400281 context->handleError(
282 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400283 return false;
284 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400285 }
286
Jamie Madill7a5f7382014-03-05 15:01:24 -0500287 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700288 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500289 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400290 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400291 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500292 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400293 }
294
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295 return true;
296}
297
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500298bool ValidateES3TexImage2DParameters(Context *context,
299 GLenum target,
300 GLint level,
301 GLenum internalformat,
302 bool isCompressed,
303 bool isSubImage,
304 GLint xoffset,
305 GLint yoffset,
306 GLint zoffset,
307 GLsizei width,
308 GLsizei height,
309 GLsizei depth,
310 GLint border,
311 GLenum format,
312 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400313 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500314 const GLvoid *pixels)
315{
316 if (!ValidTexture2DDestinationTarget(context, target))
317 {
Jamie Madill437fa652016-05-03 15:13:24 -0400318 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500319 return false;
320 }
321
322 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
323 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400324 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500325}
326
327bool ValidateES3TexImage3DParameters(Context *context,
328 GLenum target,
329 GLint level,
330 GLenum internalformat,
331 bool isCompressed,
332 bool isSubImage,
333 GLint xoffset,
334 GLint yoffset,
335 GLint zoffset,
336 GLsizei width,
337 GLsizei height,
338 GLsizei depth,
339 GLint border,
340 GLenum format,
341 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400342 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500343 const GLvoid *pixels)
344{
345 if (!ValidTexture3DDestinationTarget(context, target))
346 {
Jamie Madill437fa652016-05-03 15:13:24 -0400347 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500348 return false;
349 }
350
351 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
352 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400353 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500354}
355
Geoff Lang5d601382014-07-22 15:14:06 -0400356struct EffectiveInternalFormatInfo
357{
Jamie Madill76648fe2016-10-05 17:01:41 -0400358 GLenum effectiveFormat;
359 GLenum destFormat;
360 GLuint minRedBits;
361 GLuint maxRedBits;
362 GLuint minGreenBits;
363 GLuint maxGreenBits;
364 GLuint minBlueBits;
365 GLuint maxBlueBits;
366 GLuint minAlphaBits;
367 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400368};
369
Jamie Madill76648fe2016-10-05 17:01:41 -0400370static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
371 GLenum targetFormat,
372 const EffectiveInternalFormatInfo *list,
373 size_t size,
374 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400375{
Jamie Madill76648fe2016-10-05 17:01:41 -0400376 for (size_t curFormat = 0; curFormat < size; ++curFormat)
377 {
378 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
379 if ((formatInfo.destFormat == targetFormat) &&
380 (formatInfo.minRedBits <= srcFormat.redBits &&
381 formatInfo.maxRedBits >= srcFormat.redBits) &&
382 (formatInfo.minGreenBits <= srcFormat.greenBits &&
383 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
384 (formatInfo.minBlueBits <= srcFormat.blueBits &&
385 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
386 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
387 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
388 {
389 *outEffectiveFormat = formatInfo.effectiveFormat;
390 return true;
391 }
392 }
Geoff Lang5d601382014-07-22 15:14:06 -0400393
Jamie Madill76648fe2016-10-05 17:01:41 -0400394 *outEffectiveFormat = GL_NONE;
395 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400396}
397
Jamie Madill76648fe2016-10-05 17:01:41 -0400398bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
399 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400400{
Jamie Madill76648fe2016-10-05 17:01:41 -0400401 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
402 // Effective internal format coresponding to destination internal format and linear source
403 // buffer component sizes.
404 // | Source channel min/max sizes |
405 // Effective Internal Format | N/A | R | G | B | A |
406 // clang-format off
407 constexpr EffectiveInternalFormatInfo list[] = {
408 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
409 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
410 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
411 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
412 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
413 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
414 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
415 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
416 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
417 };
418 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400419
Jamie Madill76648fe2016-10-05 17:01:41 -0400420 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
421}
Geoff Lang5d601382014-07-22 15:14:06 -0400422
Jamie Madill76648fe2016-10-05 17:01:41 -0400423bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
424 const InternalFormat &destFormat,
425 GLenum *outEffectiveFormat)
426{
427 constexpr GLuint umax = UINT_MAX;
428
429 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
430 // Effective internal format coresponding to destination internal format andlinear source buffer
431 // component sizes.
432 // | Source channel min/max sizes |
433 // Effective Internal Format | Dest Format | R | G | B | A |
434 // clang-format off
435 constexpr EffectiveInternalFormatInfo list[] = {
436 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
437 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
438 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
439 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
440 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
441 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
442 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
443 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
444 };
445 // clang-format on
446
447 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
448 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400449}
450
He Yunchaoced53ae2016-11-29 15:00:51 +0800451static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
452 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400453 GLenum *outEffectiveFormat)
454{
Geoff Lang5d601382014-07-22 15:14:06 -0400455 if (destFormat.pixelBytes > 0)
456 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400457 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400458 }
459 else
460 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400461 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400462 }
Geoff Lang5d601382014-07-22 15:14:06 -0400463}
464
Corentin Wallez76287682016-04-25 09:23:38 -0400465static bool EqualOrFirstZero(GLuint first, GLuint second)
466{
467 return first == 0 || first == second;
468}
469
Jamie Madill0c8abca2016-07-22 20:21:26 -0400470static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
471 const Format &framebufferFormat,
472 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400473{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400474 const auto &textureFormatInfo = *textureFormat.info;
475 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400476
Jamie Madill21b786b2016-11-01 17:41:31 -0400477 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400478 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400479 return false;
480 }
Geoff Lang5d601382014-07-22 15:14:06 -0400481
Jamie Madill21b786b2016-11-01 17:41:31 -0400482 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
483 // must both be signed, unsigned, or fixed point and both source and destinations
484 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
485 // conversion between fixed and floating point.
486
487 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
488 (framebufferFormatInfo.colorEncoding == GL_SRGB))
489 {
490 return false;
491 }
492
493 if (((textureFormatInfo.componentType == GL_INT) !=
494 (framebufferFormatInfo.componentType == GL_INT)) ||
495 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
496 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
497 {
498 return false;
499 }
500
501 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
502 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
503 textureFormatInfo.componentType == GL_FLOAT) &&
504 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
505 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
506 framebufferFormatInfo.componentType == GL_FLOAT))
507 {
508 return false;
509 }
510
511 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
512 // The effective internal format of the source buffer is determined with the following rules
513 // applied in order:
514 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
515 // format then the effective internal format is the source buffer's sized internal format.
516 // * If the source buffer is a texture that was created with an unsized base internal format,
517 // then the effective internal format is the source image array's effective internal
518 // format, as specified by table 3.12, which is determined from the <format> and <type>
519 // that were used when the source image array was specified by TexImage*.
520 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
521 // where Destination Internal Format matches internalformat and where the [source channel
522 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
523 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
524 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
525 const InternalFormat *sourceEffectiveFormat = NULL;
526 if (readBufferHandle != 0)
527 {
528 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
529 // renderbuffer
530 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400531 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400532 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400533 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400534 else
Geoff Lang5d601382014-07-22 15:14:06 -0400535 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400536 // Renderbuffers cannot be created with an unsized internal format, so this must be an
537 // unsized-format texture. We can use the same table we use when creating textures to
538 // get its effective sized format.
539 GLenum sizedInternalFormat =
540 GetSizedInternalFormat(framebufferFormatInfo.format, framebufferFormatInfo.type);
541 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400542 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400543 }
544 else
545 {
546 // The effective internal format must be derived from the source framebuffer's channel
547 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
548 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400549 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400550 GLenum effectiveFormat;
551 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
552 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400553 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400554 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400555 }
556 else
557 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400558 return false;
559 }
560 }
561 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
562 {
563 // SRGB buffers can only be copied to sized format destinations according to table 3.18
564 if (textureFormat.sized &&
565 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
566 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
567 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
568 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
569 {
570 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
571 }
572 else
573 {
574 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400575 }
576 }
577 else
578 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400579 UNREACHABLE();
580 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400581 }
Geoff Lang5d601382014-07-22 15:14:06 -0400582 }
583
Jamie Madill21b786b2016-11-01 17:41:31 -0400584 if (textureFormat.sized)
585 {
586 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
587 // sized, component sizes of the source and destination formats must exactly match if the
588 // destination format exists.
589 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
590 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
591 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
592 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
593 {
594 return false;
595 }
596 }
597
598 return true; // A conversion function exists, and no rule in the specification has precluded
599 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400600}
601
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500602bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
603 GLenum target,
604 GLint level,
605 GLenum internalformat,
606 bool isSubImage,
607 GLint xoffset,
608 GLint yoffset,
609 GLint zoffset,
610 GLint x,
611 GLint y,
612 GLsizei width,
613 GLsizei height,
614 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400615{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400616 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400617 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400618 xoffset, yoffset, zoffset, x, y, width, height, border,
619 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400620 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400621 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400622 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400623 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624
Jamie Madill51f40ec2016-06-15 14:06:00 -0400625 const auto &state = context->getGLState();
626 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
627 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400628
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400629 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400630 {
Jamie Madill437fa652016-05-03 15:13:24 -0400631 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400632 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400633 }
634
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400635 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400636 {
Jamie Madill437fa652016-05-03 15:13:24 -0400637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400638 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400639 }
640
Jamie Madill0c8abca2016-07-22 20:21:26 -0400641 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400642
643 if (isSubImage)
644 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400645 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500646 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400647 {
Jamie Madill437fa652016-05-03 15:13:24 -0400648 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400649 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650 }
651 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400652 else
653 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400654 // Use format/type from the source FBO. (Might not be perfect for all cases?)
655 const auto framebufferFormat = source->getFormat();
656 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
657 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -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;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400661 }
662 }
663
Geoff Lang784a8fd2013-09-24 12:33:16 -0400664 // If width or height is zero, it is a no-op. Return false without setting an error.
665 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400666}
667
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
669 GLenum target,
670 GLint level,
671 GLenum internalformat,
672 bool isSubImage,
673 GLint xoffset,
674 GLint yoffset,
675 GLint zoffset,
676 GLint x,
677 GLint y,
678 GLsizei width,
679 GLsizei height,
680 GLint border)
681{
682 if (!ValidTexture2DDestinationTarget(context, target))
683 {
Jamie Madill437fa652016-05-03 15:13:24 -0400684 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500685 return false;
686 }
687
688 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
689 xoffset, yoffset, zoffset, x, y, width, height,
690 border);
691}
692
693bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
694 GLenum target,
695 GLint level,
696 GLenum internalformat,
697 bool isSubImage,
698 GLint xoffset,
699 GLint yoffset,
700 GLint zoffset,
701 GLint x,
702 GLint y,
703 GLsizei width,
704 GLsizei height,
705 GLint border)
706{
707 if (!ValidTexture3DDestinationTarget(context, target))
708 {
Jamie Madill437fa652016-05-03 15:13:24 -0400709 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500710 return false;
711 }
712
713 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
714 xoffset, yoffset, zoffset, x, y, width, height,
715 border);
716}
717
718bool ValidateES3TexStorageParametersBase(Context *context,
719 GLenum target,
720 GLsizei levels,
721 GLenum internalformat,
722 GLsizei width,
723 GLsizei height,
724 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725{
726 if (width < 1 || height < 1 || depth < 1 || levels < 1)
727 {
Jamie Madill437fa652016-05-03 15:13:24 -0400728 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400729 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400730 }
731
Geoff Langb92c1332015-09-04 12:54:55 -0400732 GLsizei maxDim = std::max(width, height);
733 if (target != GL_TEXTURE_2D_ARRAY)
734 {
735 maxDim = std::max(maxDim, depth);
736 }
737
738 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 {
Jamie Madill437fa652016-05-03 15:13:24 -0400740 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400741 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742 }
743
Geoff Langaae65a42014-05-26 12:43:44 -0400744 const gl::Caps &caps = context->getCaps();
745
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746 switch (target)
747 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800748 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400749 {
Geoff Langaae65a42014-05-26 12:43:44 -0400750 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
751 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 {
Jamie Madill437fa652016-05-03 15:13:24 -0400753 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400754 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 }
756 }
757 break;
758
He Yunchaoced53ae2016-11-29 15:00:51 +0800759 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 if (width != height)
762 {
Jamie Madill437fa652016-05-03 15:13:24 -0400763 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400764 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400765 }
766
Geoff Langaae65a42014-05-26 12:43:44 -0400767 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 {
Jamie Madill437fa652016-05-03 15:13:24 -0400769 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 }
772 }
773 break;
774
He Yunchaoced53ae2016-11-29 15:00:51 +0800775 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 {
Geoff Langaae65a42014-05-26 12:43:44 -0400777 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
778 static_cast<GLuint>(height) > caps.max3DTextureSize ||
779 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 {
Jamie Madill437fa652016-05-03 15:13:24 -0400781 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400782 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 }
784 }
785 break;
786
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 {
Geoff Langaae65a42014-05-26 12:43:44 -0400789 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
790 static_cast<GLuint>(height) > caps.max2DTextureSize ||
791 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 {
Jamie Madill437fa652016-05-03 15:13:24 -0400793 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796 }
797 break;
798
He Yunchaoced53ae2016-11-29 15:00:51 +0800799 default:
800 UNREACHABLE();
801 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 }
803
Geoff Lang691e58c2014-12-19 17:03:25 -0500804 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805 if (!texture || texture->id() == 0)
806 {
Jamie Madill437fa652016-05-03 15:13:24 -0400807 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400808 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 }
810
Geoff Lang69cce582015-09-17 13:20:36 -0400811 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 {
Jamie Madill437fa652016-05-03 15:13:24 -0400813 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 }
816
Geoff Lang5d601382014-07-22 15:14:06 -0400817 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400818 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 {
Jamie Madill437fa652016-05-03 15:13:24 -0400820 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400821 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822 }
823
Geoff Lang5d601382014-07-22 15:14:06 -0400824 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 {
Jamie Madill437fa652016-05-03 15:13:24 -0400826 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 }
829
830 return true;
831}
832
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500833bool ValidateES3TexStorage2DParameters(Context *context,
834 GLenum target,
835 GLsizei levels,
836 GLenum internalformat,
837 GLsizei width,
838 GLsizei height,
839 GLsizei depth)
840{
841 if (!ValidTexture2DTarget(context, target))
842 {
Jamie Madill437fa652016-05-03 15:13:24 -0400843 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500844 return false;
845 }
846
847 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
848 height, depth);
849}
850
851bool ValidateES3TexStorage3DParameters(Context *context,
852 GLenum target,
853 GLsizei levels,
854 GLenum internalformat,
855 GLsizei width,
856 GLsizei height,
857 GLsizei depth)
858{
859 if (!ValidTexture3DTarget(context, target))
860 {
Jamie Madill437fa652016-05-03 15:13:24 -0400861 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500862 return false;
863 }
864
865 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
866 height, depth);
867}
868
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500869bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
870{
Martin Radev1be913c2016-07-11 17:59:16 +0300871 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500872 {
Jamie Madill437fa652016-05-03 15:13:24 -0400873 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500874 return false;
875 }
876
877 return ValidateBeginQueryBase(context, target, id);
878}
879
880bool ValidateEndQuery(gl::Context *context, GLenum target)
881{
Martin Radev1be913c2016-07-11 17:59:16 +0300882 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500883 {
Jamie Madill437fa652016-05-03 15:13:24 -0400884 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500885 return false;
886 }
887
888 return ValidateEndQueryBase(context, target);
889}
890
891bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
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
Geoff Lang2186c382016-10-14 10:54:54 -0400899 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500900}
901
902bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
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
Geoff Lang2186c382016-10-14 10:54:54 -0400910 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500911}
912
He Yunchaoced53ae2016-11-29 15:00:51 +0800913bool ValidateFramebufferTextureLayer(Context *context,
914 GLenum target,
915 GLenum attachment,
916 GLuint texture,
917 GLint level,
918 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400919{
Martin Radev1be913c2016-07-11 17:59:16 +0300920 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400924 }
925
Jamie Madill55ec3b12014-07-03 10:38:57 -0400926 if (layer < 0)
927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400930 }
931
932 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
933 {
934 return false;
935 }
936
937 const gl::Caps &caps = context->getCaps();
938 if (texture != 0)
939 {
940 gl::Texture *tex = context->getTexture(texture);
941 ASSERT(tex);
942
943 switch (tex->getTarget())
944 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800945 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400946 {
947 if (level > gl::log2(caps.max2DTextureSize))
948 {
Jamie Madill437fa652016-05-03 15:13:24 -0400949 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400951 }
952
953 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
954 {
Jamie Madill437fa652016-05-03 15:13:24 -0400955 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400956 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400957 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400958 }
959 break;
960
He Yunchaoced53ae2016-11-29 15:00:51 +0800961 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400962 {
963 if (level > gl::log2(caps.max3DTextureSize))
964 {
Jamie Madill437fa652016-05-03 15:13:24 -0400965 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400966 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400967 }
968
969 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
970 {
Jamie Madill437fa652016-05-03 15:13:24 -0400971 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400972 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400973 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400974 }
975 break;
976
He Yunchaoced53ae2016-11-29 15:00:51 +0800977 default:
978 context->handleError(Error(GL_INVALID_OPERATION));
979 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400980 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500981
Jamie Madilla3944d42016-07-22 22:13:26 -0400982 const auto &format = tex->getFormat(tex->getTarget(), level);
983 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500984 {
Jamie Madill437fa652016-05-03 15:13:24 -0400985 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500986 return false;
987 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400988 }
989
990 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -0400991}
992
He Yunchaoced53ae2016-11-29 15:00:51 +0800993bool ValidateInvalidateFramebuffer(Context *context,
994 GLenum target,
995 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -0700996 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997{
Martin Radev1be913c2016-07-11 17:59:16 +0300998 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -0700999 {
Jamie Madill437fa652016-05-03 15:13:24 -04001000 context->handleError(
1001 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001002 return false;
1003 }
1004
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 bool defaultFramebuffer = false;
1006
1007 switch (target)
1008 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 case GL_DRAW_FRAMEBUFFER:
1010 case GL_FRAMEBUFFER:
1011 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1012 break;
1013 case GL_READ_FRAMEBUFFER:
1014 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1015 break;
1016 default:
1017 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
He Yunchaoced53ae2016-11-29 15:00:51 +08001021 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1022 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023}
1024
Jamie Madillc29968b2016-01-20 11:17:23 -05001025bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001026{
Martin Radev1be913c2016-07-11 17:59:16 +03001027 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001028 {
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001030 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001031 }
1032
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001033 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001034 {
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001036 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001037 }
1038
1039 return true;
1040}
1041
Olli Etuaho71dfb362016-03-10 14:04:27 +02001042bool ValidateDrawRangeElements(Context *context,
1043 GLenum mode,
1044 GLuint start,
1045 GLuint end,
1046 GLsizei count,
1047 GLenum type,
1048 const GLvoid *indices,
1049 IndexRange *indexRange)
1050{
Martin Radev1be913c2016-07-11 17:59:16 +03001051 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001052 {
Jamie Madill437fa652016-05-03 15:13:24 -04001053 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001054 return false;
1055 }
1056
1057 if (end < start)
1058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001060 return false;
1061 }
1062
1063 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1064 {
1065 return false;
1066 }
1067
1068 if (indexRange->end > end || indexRange->start < start)
1069 {
1070 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001071 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001072 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1073 return false;
1074 }
1075 return true;
1076}
1077
He Yunchaoced53ae2016-11-29 15:00:51 +08001078bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001079{
Martin Radev1be913c2016-07-11 17:59:16 +03001080 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001081 {
Jamie Madill437fa652016-05-03 15:13:24 -04001082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001083 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001084 }
1085
Jamie Madill78f41802014-08-25 15:47:55 -04001086 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001087}
1088
Jamie Madillb885e572015-02-03 16:16:04 -05001089bool ValidateReadBuffer(Context *context, GLenum src)
1090{
Martin Radev1be913c2016-07-11 17:59:16 +03001091 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001092 {
Jamie Madill437fa652016-05-03 15:13:24 -04001093 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001094 return false;
1095 }
1096
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001097 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001098
1099 if (readFBO == nullptr)
1100 {
Jamie Madill437fa652016-05-03 15:13:24 -04001101 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001102 return false;
1103 }
1104
1105 if (src == GL_NONE)
1106 {
1107 return true;
1108 }
1109
Olli Etuaho84c9f592016-03-09 14:37:25 +02001110 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001111 {
Jamie Madill437fa652016-05-03 15:13:24 -04001112 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001113 return false;
1114 }
1115
1116 if (readFBO->id() == 0)
1117 {
1118 if (src != GL_BACK)
1119 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 const char *errorMsg =
1121 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001122 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001123 return false;
1124 }
1125 }
1126 else
1127 {
1128 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1129
1130 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1131 {
1132 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001133 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001134 return false;
1135 }
1136 }
1137
1138 return true;
1139}
1140
Jamie Madill86af3d22015-07-21 15:14:07 -04001141bool ValidateCompressedTexImage3D(Context *context,
1142 GLenum target,
1143 GLint level,
1144 GLenum internalformat,
1145 GLsizei width,
1146 GLsizei height,
1147 GLsizei depth,
1148 GLint border,
1149 GLsizei imageSize,
1150 const GLvoid *data)
1151{
Martin Radev1be913c2016-07-11 17:59:16 +03001152 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001153 {
Jamie Madill437fa652016-05-03 15:13:24 -04001154 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001155 return false;
1156 }
1157
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001158 if (!ValidTextureTarget(context, target))
1159 {
1160 context->handleError(Error(GL_INVALID_ENUM));
1161 return false;
1162 }
1163
Jamie Madille2e406c2016-06-02 13:04:10 -04001164 // Validate image size
1165 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1166 {
1167 context->handleError(Error(GL_INVALID_VALUE));
1168 return false;
1169 }
1170
Jamie Madill86af3d22015-07-21 15:14:07 -04001171 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001172 if (!formatInfo.compressed)
1173 {
1174 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1175 return false;
1176 }
1177
Jamie Madill513558d2016-06-02 13:04:11 -04001178 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001179 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001180 if (blockSizeOrErr.isError())
1181 {
Jamie Madill513558d2016-06-02 13:04:11 -04001182 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001183 return false;
1184 }
1185 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001188 return false;
1189 }
1190
1191 // 3D texture target validation
1192 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1193 {
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001195 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1196 return false;
1197 }
1198
1199 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001200 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001201 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1202 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001203 {
1204 return false;
1205 }
1206
1207 return true;
1208}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001209
1210bool ValidateBindVertexArray(Context *context, GLuint array)
1211{
Martin Radev1be913c2016-07-11 17:59:16 +03001212 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001213 {
Jamie Madill437fa652016-05-03 15:13:24 -04001214 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001215 return false;
1216 }
1217
1218 return ValidateBindVertexArrayBase(context, array);
1219}
1220
Austin Kinrossbc781f32015-10-26 09:27:38 -07001221bool ValidateIsVertexArray(Context *context)
1222{
Martin Radev1be913c2016-07-11 17:59:16 +03001223 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001224 {
Jamie Madill437fa652016-05-03 15:13:24 -04001225 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001226 return false;
1227 }
1228
1229 return true;
1230}
Geoff Langc5629752015-12-07 16:29:04 -05001231
Jiajia Qin6eafb042016-12-27 17:04:07 +08001232static bool ValidateBindBufferCommon(Context *context,
1233 GLenum target,
1234 GLuint index,
1235 GLuint buffer,
1236 GLintptr offset,
1237 GLsizeiptr size)
1238{
1239 if (context->getClientMajorVersion() < 3)
1240 {
1241 context->handleError(Error(GL_INVALID_OPERATION));
1242 return false;
1243 }
1244
1245 if (buffer != 0 && offset < 0)
1246 {
1247 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1248 return false;
1249 }
1250
1251 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1252 !context->isBufferGenerated(buffer))
1253 {
1254 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1255 return false;
1256 }
1257
1258 const Caps &caps = context->getCaps();
1259 switch (target)
1260 {
1261 case GL_TRANSFORM_FEEDBACK_BUFFER:
1262 {
1263 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1264 {
1265 context->handleError(Error(GL_INVALID_VALUE,
1266 "index is greater than or equal to the number of "
1267 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1268 return false;
1269 }
1270 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1271 {
1272 context->handleError(
1273 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1274 return false;
1275 }
1276
1277 TransformFeedback *curTransformFeedback =
1278 context->getGLState().getCurrentTransformFeedback();
1279 if (curTransformFeedback && curTransformFeedback->isActive())
1280 {
1281 context->handleError(Error(GL_INVALID_OPERATION,
1282 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1283 "feedback is currently active."));
1284 return false;
1285 }
1286 break;
1287 }
1288 case GL_UNIFORM_BUFFER:
1289 {
1290 if (index >= caps.maxUniformBufferBindings)
1291 {
1292 context->handleError(Error(GL_INVALID_VALUE,
1293 "index is greater than or equal to the number of "
1294 "UNIFORM_BUFFER indexed binding points."));
1295 return false;
1296 }
1297
1298 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1299 {
1300 context->handleError(
1301 Error(GL_INVALID_VALUE,
1302 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1303 return false;
1304 }
1305 break;
1306 }
1307 case GL_ATOMIC_COUNTER_BUFFER:
1308 {
1309 if (context->getClientVersion() < ES_3_1)
1310 {
Yunchao He61afff12017-03-14 15:34:03 +08001311 context->handleError(Error(
1312 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001313 return false;
1314 }
1315 if (index >= caps.maxAtomicCounterBufferBindings)
1316 {
1317 context->handleError(Error(GL_INVALID_VALUE,
1318 "index is greater than or equal to the number of "
1319 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1320 return false;
1321 }
1322 if (buffer != 0 && (offset % 4) != 0)
1323 {
1324 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1325 return false;
1326 }
1327 break;
1328 }
1329 case GL_SHADER_STORAGE_BUFFER:
1330 {
1331 if (context->getClientVersion() < ES_3_1)
1332 {
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001333 context->handleError(
1334 Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
1335 return false;
1336 }
1337 if (index >= caps.maxShaderStorageBufferBindings)
1338 {
1339 context->handleError(Error(GL_INVALID_VALUE,
1340 "index is greater than or equal to the number of "
1341 "SHADER_STORAGE_BUFFER indexed binding points."));
1342 return false;
1343 }
1344 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1345 {
Yunchao He61afff12017-03-14 15:34:03 +08001346 context->handleError(Error(
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001347 GL_INVALID_VALUE,
1348 "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001349 return false;
1350 }
1351 break;
1352 }
1353 default:
1354 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1355 return false;
1356 }
1357
1358 return true;
1359}
1360
1361bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1362{
1363 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1364}
1365
1366bool ValidateBindBufferRange(Context *context,
1367 GLenum target,
1368 GLuint index,
1369 GLuint buffer,
1370 GLintptr offset,
1371 GLsizeiptr size)
1372{
1373 if (buffer != 0 && size <= 0)
1374 {
1375 context->handleError(
1376 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1377 return false;
1378 }
1379 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1380}
1381
Geoff Langc5629752015-12-07 16:29:04 -05001382bool ValidateProgramBinary(Context *context,
1383 GLuint program,
1384 GLenum binaryFormat,
1385 const void *binary,
1386 GLint length)
1387{
Martin Radev1be913c2016-07-11 17:59:16 +03001388 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001391 return false;
1392 }
1393
1394 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1395}
1396
1397bool ValidateGetProgramBinary(Context *context,
1398 GLuint program,
1399 GLsizei bufSize,
1400 GLsizei *length,
1401 GLenum *binaryFormat,
1402 void *binary)
1403{
Martin Radev1be913c2016-07-11 17:59:16 +03001404 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001405 {
Jamie Madill437fa652016-05-03 15:13:24 -04001406 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001407 return false;
1408 }
1409
1410 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1411}
1412
Olli Etuahof0fee072016-03-30 15:11:58 +03001413bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001414{
Martin Radev1be913c2016-07-11 17:59:16 +03001415 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001416 {
Jamie Madill437fa652016-05-03 15:13:24 -04001417 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001418 return false;
1419 }
1420
1421 if (GetValidProgram(context, program) == nullptr)
1422 {
1423 return false;
1424 }
1425
1426 switch (pname)
1427 {
1428 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001429 if (value != GL_FALSE && value != GL_TRUE)
1430 {
Jamie Madill437fa652016-05-03 15:13:24 -04001431 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001432 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1433 return false;
1434 }
Geoff Langc5629752015-12-07 16:29:04 -05001435 break;
1436
Yunchao He61afff12017-03-14 15:34:03 +08001437 case GL_PROGRAM_SEPARABLE:
1438 if (context->getClientVersion() < ES_3_1)
1439 {
1440 context->handleError(
1441 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1442 return false;
1443 }
1444
1445 if (value != GL_FALSE && value != GL_TRUE)
1446 {
1447 context->handleError(Error(
1448 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1449 return false;
1450 }
1451 break;
1452
Geoff Langc5629752015-12-07 16:29:04 -05001453 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001455 return false;
1456 }
1457
1458 return true;
1459}
Jamie Madillc29968b2016-01-20 11:17:23 -05001460
1461bool ValidateBlitFramebuffer(Context *context,
1462 GLint srcX0,
1463 GLint srcY0,
1464 GLint srcX1,
1465 GLint srcY1,
1466 GLint dstX0,
1467 GLint dstY0,
1468 GLint dstX1,
1469 GLint dstY1,
1470 GLbitfield mask,
1471 GLenum filter)
1472{
Martin Radev1be913c2016-07-11 17:59:16 +03001473 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001474 {
Jamie Madill437fa652016-05-03 15:13:24 -04001475 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001476 return false;
1477 }
1478
1479 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1480 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481}
Jamie Madillc29968b2016-01-20 11:17:23 -05001482
1483bool ValidateClearBufferiv(ValidationContext *context,
1484 GLenum buffer,
1485 GLint drawbuffer,
1486 const GLint *value)
1487{
1488 switch (buffer)
1489 {
1490 case GL_COLOR:
1491 if (drawbuffer < 0 ||
1492 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1493 {
Jamie Madill437fa652016-05-03 15:13:24 -04001494 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001495 return false;
1496 }
Geoff Lang76e65652017-03-27 14:58:02 -04001497 if (context->getExtensions().webglCompatibility)
1498 {
1499 constexpr GLenum validComponentTypes[] = {GL_INT};
1500 if (ValidateWebGLFramebufferAttachmentClearType(
1501 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1502 {
1503 return false;
1504 }
1505 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001506 break;
1507
1508 case GL_STENCIL:
1509 if (drawbuffer != 0)
1510 {
Jamie Madill437fa652016-05-03 15:13:24 -04001511 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001512 return false;
1513 }
1514 break;
1515
1516 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001517 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001518 return false;
1519 }
1520
1521 return ValidateClearBuffer(context);
1522}
1523
1524bool ValidateClearBufferuiv(ValidationContext *context,
1525 GLenum buffer,
1526 GLint drawbuffer,
1527 const GLuint *value)
1528{
1529 switch (buffer)
1530 {
1531 case GL_COLOR:
1532 if (drawbuffer < 0 ||
1533 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001536 return false;
1537 }
Geoff Lang76e65652017-03-27 14:58:02 -04001538 if (context->getExtensions().webglCompatibility)
1539 {
1540 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1541 if (ValidateWebGLFramebufferAttachmentClearType(
1542 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1543 {
1544 return false;
1545 }
1546 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001547 break;
1548
1549 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001550 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001551 return false;
1552 }
1553
1554 return ValidateClearBuffer(context);
1555}
1556
1557bool ValidateClearBufferfv(ValidationContext *context,
1558 GLenum buffer,
1559 GLint drawbuffer,
1560 const GLfloat *value)
1561{
1562 switch (buffer)
1563 {
1564 case GL_COLOR:
1565 if (drawbuffer < 0 ||
1566 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1567 {
Jamie Madill437fa652016-05-03 15:13:24 -04001568 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001569 return false;
1570 }
Geoff Lang76e65652017-03-27 14:58:02 -04001571 if (context->getExtensions().webglCompatibility)
1572 {
1573 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1574 GL_SIGNED_NORMALIZED};
1575 if (ValidateWebGLFramebufferAttachmentClearType(
1576 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1577 {
1578 return false;
1579 }
1580 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001581 break;
1582
1583 case GL_DEPTH:
1584 if (drawbuffer != 0)
1585 {
Jamie Madill437fa652016-05-03 15:13:24 -04001586 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001587 return false;
1588 }
1589 break;
1590
1591 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001592 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001593 return false;
1594 }
1595
1596 return ValidateClearBuffer(context);
1597}
1598
1599bool ValidateClearBufferfi(ValidationContext *context,
1600 GLenum buffer,
1601 GLint drawbuffer,
1602 GLfloat depth,
1603 GLint stencil)
1604{
1605 switch (buffer)
1606 {
1607 case GL_DEPTH_STENCIL:
1608 if (drawbuffer != 0)
1609 {
Jamie Madill437fa652016-05-03 15:13:24 -04001610 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 return false;
1612 }
1613 break;
1614
1615 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001617 return false;
1618 }
1619
1620 return ValidateClearBuffer(context);
1621}
1622
1623bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1624{
Martin Radev1be913c2016-07-11 17:59:16 +03001625 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001626 {
Jamie Madill437fa652016-05-03 15:13:24 -04001627 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001628 return false;
1629 }
1630
1631 return ValidateDrawBuffersBase(context, n, bufs);
1632}
1633
1634bool ValidateCopyTexSubImage3D(Context *context,
1635 GLenum target,
1636 GLint level,
1637 GLint xoffset,
1638 GLint yoffset,
1639 GLint zoffset,
1640 GLint x,
1641 GLint y,
1642 GLsizei width,
1643 GLsizei height)
1644{
Martin Radev1be913c2016-07-11 17:59:16 +03001645 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001648 return false;
1649 }
1650
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001651 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1652 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001653}
1654
Jamie Madill73a84962016-02-12 09:27:23 -05001655bool ValidateTexImage3D(Context *context,
1656 GLenum target,
1657 GLint level,
1658 GLint internalformat,
1659 GLsizei width,
1660 GLsizei height,
1661 GLsizei depth,
1662 GLint border,
1663 GLenum format,
1664 GLenum type,
1665 const GLvoid *pixels)
1666{
Martin Radev1be913c2016-07-11 17:59:16 +03001667 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001670 return false;
1671 }
1672
1673 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001674 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001675 pixels);
1676}
1677
Geoff Langc52f6f12016-10-14 10:18:00 -04001678bool ValidateTexImage3DRobustANGLE(Context *context,
1679 GLenum target,
1680 GLint level,
1681 GLint internalformat,
1682 GLsizei width,
1683 GLsizei height,
1684 GLsizei depth,
1685 GLint border,
1686 GLenum format,
1687 GLenum type,
1688 GLsizei bufSize,
1689 const GLvoid *pixels)
1690{
1691 if (context->getClientMajorVersion() < 3)
1692 {
1693 context->handleError(Error(GL_INVALID_OPERATION));
1694 return false;
1695 }
1696
1697 if (!ValidateRobustEntryPoint(context, bufSize))
1698 {
1699 return false;
1700 }
1701
1702 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1703 0, 0, width, height, depth, border, format, type,
1704 bufSize, pixels);
1705}
1706
Jamie Madill73a84962016-02-12 09:27:23 -05001707bool ValidateTexSubImage3D(Context *context,
1708 GLenum target,
1709 GLint level,
1710 GLint xoffset,
1711 GLint yoffset,
1712 GLint zoffset,
1713 GLsizei width,
1714 GLsizei height,
1715 GLsizei depth,
1716 GLenum format,
1717 GLenum type,
1718 const GLvoid *pixels)
1719{
Martin Radev1be913c2016-07-11 17:59:16 +03001720 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001721 {
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001723 return false;
1724 }
1725
1726 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1727 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001728 -1, pixels);
1729}
1730
1731bool ValidateTexSubImage3DRobustANGLE(Context *context,
1732 GLenum target,
1733 GLint level,
1734 GLint xoffset,
1735 GLint yoffset,
1736 GLint zoffset,
1737 GLsizei width,
1738 GLsizei height,
1739 GLsizei depth,
1740 GLenum format,
1741 GLenum type,
1742 GLsizei bufSize,
1743 const GLvoid *pixels)
1744{
1745 if (context->getClientMajorVersion() < 3)
1746 {
1747 context->handleError(Error(GL_INVALID_OPERATION));
1748 return false;
1749 }
1750
1751 if (!ValidateRobustEntryPoint(context, bufSize))
1752 {
1753 return false;
1754 }
1755
1756 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1757 yoffset, zoffset, width, height, depth, 0, format, type,
1758 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001759}
1760
1761bool ValidateCompressedTexSubImage3D(Context *context,
1762 GLenum target,
1763 GLint level,
1764 GLint xoffset,
1765 GLint yoffset,
1766 GLint zoffset,
1767 GLsizei width,
1768 GLsizei height,
1769 GLsizei depth,
1770 GLenum format,
1771 GLsizei imageSize,
1772 const GLvoid *data)
1773{
Martin Radev1be913c2016-07-11 17:59:16 +03001774 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001775 {
Jamie Madill437fa652016-05-03 15:13:24 -04001776 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001777 return false;
1778 }
1779
1780 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001781 if (!formatInfo.compressed)
1782 {
1783 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1784 return false;
1785 }
1786
Jamie Madill513558d2016-06-02 13:04:11 -04001787 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001788 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001789 if (blockSizeOrErr.isError())
1790 {
1791 context->handleError(blockSizeOrErr.getError());
1792 return false;
1793 }
1794 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001797 return false;
1798 }
1799
1800 if (!data)
1801 {
Jamie Madill437fa652016-05-03 15:13:24 -04001802 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001803 return false;
1804 }
1805
1806 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001807 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001808}
1809
Olli Etuaho41997e72016-03-10 13:38:39 +02001810bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1811{
1812 return ValidateGenOrDeleteES3(context, n);
1813}
1814
1815bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1816{
1817 return ValidateGenOrDeleteES3(context, n);
1818}
1819
1820bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1821{
1822 return ValidateGenOrDeleteCountES3(context, count);
1823}
1824
1825bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1826{
1827 return ValidateGenOrDeleteCountES3(context, count);
1828}
1829
1830bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1831{
1832 return ValidateGenOrDeleteES3(context, n);
1833}
1834
1835bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1836{
1837 if (!ValidateGenOrDeleteES3(context, n))
1838 {
1839 return false;
1840 }
1841 for (GLint i = 0; i < n; ++i)
1842 {
1843 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1844 if (transformFeedback != nullptr && transformFeedback->isActive())
1845 {
1846 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001847 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001848 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1849 return false;
1850 }
1851 }
1852 return true;
1853}
1854
1855bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1856{
1857 return ValidateGenOrDeleteES3(context, n);
1858}
1859
1860bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1861{
1862 return ValidateGenOrDeleteES3(context, n);
1863}
1864
1865bool ValidateGenOrDeleteES3(Context *context, GLint n)
1866{
Martin Radev1be913c2016-07-11 17:59:16 +03001867 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001870 return false;
1871 }
1872 return ValidateGenOrDelete(context, n);
1873}
1874
1875bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1876{
Martin Radev1be913c2016-07-11 17:59:16 +03001877 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001880 return false;
1881 }
1882 if (count < 0)
1883 {
Jamie Madill437fa652016-05-03 15:13:24 -04001884 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001885 return false;
1886 }
1887 return true;
1888}
1889
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001890bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1891{
Martin Radev1be913c2016-07-11 17:59:16 +03001892 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001893 {
Jamie Madill437fa652016-05-03 15:13:24 -04001894 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001895 return false;
1896 }
1897 switch (primitiveMode)
1898 {
1899 case GL_TRIANGLES:
1900 case GL_LINES:
1901 case GL_POINTS:
1902 break;
1903
1904 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001906 return false;
1907 }
1908
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001909 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001910 ASSERT(transformFeedback != nullptr);
1911
1912 if (transformFeedback->isActive())
1913 {
Jamie Madill437fa652016-05-03 15:13:24 -04001914 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001915 return false;
1916 }
1917 return true;
1918}
1919
Olli Etuaho4f667482016-03-30 15:56:35 +03001920bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1921{
Geoff Lang496c02d2016-10-20 11:38:11 -07001922 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1923}
1924
1925bool ValidateGetBufferPointervRobustANGLE(Context *context,
1926 GLenum target,
1927 GLenum pname,
1928 GLsizei bufSize,
1929 GLsizei *length,
1930 GLvoid **params)
1931{
1932 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001933 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001934 return false;
1935 }
1936
Geoff Lang496c02d2016-10-20 11:38:11 -07001937 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1938 {
1939 return false;
1940 }
1941
1942 if (!ValidateRobustBufferSize(context, bufSize, *length))
1943 {
1944 return false;
1945 }
1946
1947 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001948}
1949
1950bool ValidateUnmapBuffer(Context *context, GLenum target)
1951{
Martin Radev1be913c2016-07-11 17:59:16 +03001952 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001953 {
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001955 return false;
1956 }
1957
1958 return ValidateUnmapBufferBase(context, target);
1959}
1960
1961bool ValidateMapBufferRange(Context *context,
1962 GLenum target,
1963 GLintptr offset,
1964 GLsizeiptr length,
1965 GLbitfield access)
1966{
Martin Radev1be913c2016-07-11 17:59:16 +03001967 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001968 {
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001970 return false;
1971 }
1972
1973 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1974}
1975
1976bool ValidateFlushMappedBufferRange(Context *context,
1977 GLenum target,
1978 GLintptr offset,
1979 GLsizeiptr length)
1980{
Martin Radev1be913c2016-07-11 17:59:16 +03001981 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001982 {
Jamie Madill437fa652016-05-03 15:13:24 -04001983 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001984 return false;
1985 }
1986
1987 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1988}
1989
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001990bool ValidateIndexedStateQuery(ValidationContext *context,
1991 GLenum pname,
1992 GLuint index,
1993 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001994{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001995 if (length)
1996 {
1997 *length = 0;
1998 }
1999
Martin Radev66fb8202016-07-28 11:45:20 +03002000 GLenum nativeType;
2001 unsigned int numParams;
2002 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2003 {
2004 context->handleError(Error(GL_INVALID_ENUM));
2005 return false;
2006 }
2007
2008 const Caps &caps = context->getCaps();
2009 switch (pname)
2010 {
2011 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2012 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2013 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2014 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2015 {
2016 context->handleError(Error(GL_INVALID_VALUE));
2017 return false;
2018 }
2019 break;
2020
2021 case GL_UNIFORM_BUFFER_START:
2022 case GL_UNIFORM_BUFFER_SIZE:
2023 case GL_UNIFORM_BUFFER_BINDING:
2024 if (index >= caps.maxUniformBufferBindings)
2025 {
2026 context->handleError(Error(GL_INVALID_VALUE));
2027 return false;
2028 }
2029 break;
Shao80957d92017-02-20 21:25:59 +08002030
Martin Radev66fb8202016-07-28 11:45:20 +03002031 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2032 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2033 if (index >= 3u)
2034 {
2035 context->handleError(Error(GL_INVALID_VALUE));
2036 return false;
2037 }
2038 break;
Shao80957d92017-02-20 21:25:59 +08002039
Jiajia Qin6eafb042016-12-27 17:04:07 +08002040 case GL_ATOMIC_COUNTER_BUFFER_START:
2041 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2042 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2043 if (context->getClientVersion() < ES_3_1)
2044 {
2045 context->handleError(
2046 Error(GL_INVALID_ENUM,
2047 "Atomic Counter buffers are not supported in this version of GL"));
2048 return false;
2049 }
2050 if (index >= caps.maxAtomicCounterBufferBindings)
2051 {
2052 context->handleError(
2053 Error(GL_INVALID_VALUE,
2054 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2055 return false;
2056 }
2057 break;
Shao80957d92017-02-20 21:25:59 +08002058
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002059 case GL_SHADER_STORAGE_BUFFER_START:
2060 case GL_SHADER_STORAGE_BUFFER_SIZE:
2061 case GL_SHADER_STORAGE_BUFFER_BINDING:
2062 if (context->getClientVersion() < ES_3_1)
2063 {
2064 context->handleError(
2065 Error(GL_INVALID_ENUM,
2066 "Shader storage buffers are not supported in this version of GL"));
2067 return false;
2068 }
2069 if (index >= caps.maxShaderStorageBufferBindings)
2070 {
2071 context->handleError(
2072 Error(GL_INVALID_VALUE,
2073 "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
2074 return false;
2075 }
2076 break;
2077
Shao80957d92017-02-20 21:25:59 +08002078 case GL_VERTEX_BINDING_BUFFER:
2079 case GL_VERTEX_BINDING_DIVISOR:
2080 case GL_VERTEX_BINDING_OFFSET:
2081 case GL_VERTEX_BINDING_STRIDE:
2082 if (context->getClientVersion() < ES_3_1)
2083 {
2084 context->handleError(
2085 Error(GL_INVALID_ENUM,
2086 "Vertex Attrib Bindings are not supported in this version of GL"));
2087 return false;
2088 }
2089 if (index >= caps.maxVertexAttribBindings)
2090 {
2091 context->handleError(
2092 Error(GL_INVALID_VALUE,
2093 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2094 return false;
2095 }
2096 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002097 default:
2098 context->handleError(Error(GL_INVALID_ENUM));
2099 return false;
2100 }
2101
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002102 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002103 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002104 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002105 }
2106
2107 return true;
2108}
2109
2110bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2111{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002112 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002113 {
2114 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2115 return false;
2116 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002117 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002118}
2119
Geoff Langcf255ea2016-10-20 11:39:09 -07002120bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2121 GLenum target,
2122 GLuint index,
2123 GLsizei bufSize,
2124 GLsizei *length,
2125 GLint *data)
2126{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002127 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002128 {
2129 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2130 return false;
2131 }
2132
2133 if (!ValidateRobustEntryPoint(context, bufSize))
2134 {
2135 return false;
2136 }
2137
2138 if (!ValidateIndexedStateQuery(context, target, index, length))
2139 {
2140 return false;
2141 }
2142
2143 if (!ValidateRobustBufferSize(context, bufSize, *length))
2144 {
2145 return false;
2146 }
2147
2148 return true;
2149}
2150
Martin Radev66fb8202016-07-28 11:45:20 +03002151bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2152{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002153 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002154 {
2155 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2156 return false;
2157 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002158 return ValidateIndexedStateQuery(context, target, index, nullptr);
2159}
2160
2161bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2162 GLenum target,
2163 GLuint index,
2164 GLsizei bufSize,
2165 GLsizei *length,
2166 GLint64 *data)
2167{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002168 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002169 {
2170 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2171 return false;
2172 }
2173
2174 if (!ValidateRobustEntryPoint(context, bufSize))
2175 {
2176 return false;
2177 }
2178
2179 if (!ValidateIndexedStateQuery(context, target, index, length))
2180 {
2181 return false;
2182 }
2183
2184 if (!ValidateRobustBufferSize(context, bufSize, *length))
2185 {
2186 return false;
2187 }
2188
2189 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002190}
2191
Jamie Madillb0817d12016-11-01 15:48:31 -04002192bool ValidateCopyBufferSubData(ValidationContext *context,
2193 GLenum readTarget,
2194 GLenum writeTarget,
2195 GLintptr readOffset,
2196 GLintptr writeOffset,
2197 GLsizeiptr size)
2198{
2199 if (context->getClientMajorVersion() < 3)
2200 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002201 context->handleError(
2202 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002203 return false;
2204 }
2205
2206 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2207 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002208 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002209 return false;
2210 }
2211
2212 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2213 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2214
2215 if (!readBuffer || !writeBuffer)
2216 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002217 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002218 return false;
2219 }
2220
2221 // Verify that readBuffer and writeBuffer are not currently mapped
2222 if (readBuffer->isMapped() || writeBuffer->isMapped())
2223 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002224 context->handleError(
2225 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002226 return false;
2227 }
2228
Jamie Madilld2f0c742016-11-02 10:34:41 -04002229 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2230 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2231 CheckedNumeric<GLintptr> checkedSize(size);
2232
2233 auto checkedReadSum = checkedReadOffset + checkedSize;
2234 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2235
2236 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2237 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2238 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002239 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002240 context->handleError(
2241 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002242 return false;
2243 }
2244
Jamie Madilld2f0c742016-11-02 10:34:41 -04002245 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002246 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002247 context->handleError(
2248 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002249 return false;
2250 }
2251
Jamie Madilld2f0c742016-11-02 10:34:41 -04002252 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2253 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2254 {
2255 context->handleError(
2256 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2257 return false;
2258 }
2259
2260 if (readBuffer == writeBuffer)
2261 {
2262 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2263 if (!checkedOffsetDiff.IsValid())
2264 {
2265 // This shold not be possible.
2266 UNREACHABLE();
2267 context->handleError(
2268 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2269 return false;
2270 }
2271
2272 if (checkedOffsetDiff.ValueOrDie() < size)
2273 {
2274 context->handleError(Error(GL_INVALID_VALUE));
2275 return false;
2276 }
2277 }
2278
Jamie Madillb0817d12016-11-01 15:48:31 -04002279 return true;
2280}
2281
Geoff Langc339c4e2016-11-29 10:37:36 -05002282bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2283{
2284 if (context->getClientMajorVersion() < 3)
2285 {
2286 context->handleError(
2287 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2288 return false;
2289 }
2290
2291 switch (name)
2292 {
2293 case GL_EXTENSIONS:
2294 if (index >= context->getExtensionStringCount())
2295 {
2296 context->handleError(Error(
2297 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2298 return false;
2299 }
2300 break;
2301
2302 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2303 if (!context->getExtensions().requestExtension)
2304 {
2305 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2306 return false;
2307 }
2308 if (index >= context->getRequestableExtensionStringCount())
2309 {
2310 context->handleError(
2311 Error(GL_INVALID_VALUE,
2312 "index must be less than the number of requestable extension strings."));
2313 return false;
2314 }
2315 break;
2316
2317 default:
2318 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2319 return false;
2320 }
2321
2322 return true;
2323}
2324
Jamie Madille8fb6402017-02-14 17:56:40 -05002325bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2326 GLenum target,
2327 GLsizei samples,
2328 GLenum internalformat,
2329 GLsizei width,
2330 GLsizei height)
2331{
2332 if (context->getClientMajorVersion() < 3)
2333 {
2334 context->handleError(Error(GL_INVALID_OPERATION));
2335 return false;
2336 }
2337
2338 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2339 height))
2340 {
2341 return false;
2342 }
2343
2344 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2345 // format if samples is greater than zero.
2346 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2347 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2348 samples > 0)
2349 {
2350 context->handleError(Error(GL_INVALID_OPERATION));
2351 return false;
2352 }
2353
2354 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2355 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2356 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2357 {
2358 context->handleError(
2359 Error(GL_INVALID_OPERATION,
2360 "Samples must not be greater than maximum supported value for the format."));
2361 return false;
2362 }
2363
2364 return true;
2365}
2366
Geoff Langaa086d62017-03-23 16:47:21 -04002367bool ValidateVertexAttribIPointer(ValidationContext *context,
2368 GLuint index,
2369 GLint size,
2370 GLenum type,
2371 GLsizei stride,
2372 const GLvoid *pointer)
2373{
2374 if (context->getClientMajorVersion() < 3)
2375 {
Geoff Langaa086d62017-03-23 16:47:21 -04002376 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002377 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002378 return false;
2379 }
2380
Shao80957d92017-02-20 21:25:59 +08002381 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002382 {
Geoff Langaa086d62017-03-23 16:47:21 -04002383 return false;
2384 }
2385
Geoff Langaa086d62017-03-23 16:47:21 -04002386 if (stride < 0)
2387 {
Shao80957d92017-02-20 21:25:59 +08002388 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002389 return false;
2390 }
2391
Shao80957d92017-02-20 21:25:59 +08002392 const Caps &caps = context->getCaps();
2393 if (context->getClientVersion() >= ES_3_1)
2394 {
2395 if (stride > caps.maxVertexAttribStride)
2396 {
2397 context->handleError(
2398 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2399 return false;
2400 }
2401
2402 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2403 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2404 // validation should be inherited.
2405 if (index >= caps.maxVertexAttribBindings)
2406 {
2407 context->handleError(
2408 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2409 return false;
2410 }
2411 }
2412
Geoff Langaa086d62017-03-23 16:47:21 -04002413 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2414 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2415 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2416 // and the pointer argument is not NULL.
2417 if (context->getGLState().getVertexArrayId() != 0 &&
2418 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2419 {
2420 context->handleError(
2421 Error(GL_INVALID_OPERATION,
2422 "Client data cannot be used with a non-default vertex array object."));
2423 return false;
2424 }
2425
Geoff Lang2d62ab72017-03-23 16:54:40 -04002426 if (context->getExtensions().webglCompatibility)
2427 {
2428 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2429 {
2430 return false;
2431 }
2432 }
2433
Geoff Langaa086d62017-03-23 16:47:21 -04002434 return true;
2435}
2436
Jamie Madillc29968b2016-01-20 11:17:23 -05002437} // namespace gl