blob: 1581b75894e4a444c79a6f42cb1ca393af23061c [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
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.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
Geoff Lang5d601382014-07-22 15:14:06 -040027static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
28{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050029 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
30 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
31 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
32 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -040033 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +030034 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -040035 {
Jamie Madill437fa652016-05-03 15:13:24 -040036 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040037 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040038 }
39
40 // The type and format are valid if any supported internal format has that type and format
Jamie Madill55e98212016-10-05 16:39:13 -040041 if (!ValidES3Format(format) || !ValidES3Type(type))
Geoff Lang5d601382014-07-22 15:14:06 -040042 {
Jamie Madill437fa652016-05-03 15:13:24 -040043 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -040044 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040045 }
46
47 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040048 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040049 {
Jamie Madill437fa652016-05-03 15:13:24 -040050 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -040051 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040052 }
53
54 return true;
55}
56
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050057bool ValidateES3TexImageParametersBase(Context *context,
58 GLenum target,
59 GLint level,
60 GLenum internalformat,
61 bool isCompressed,
62 bool isSubImage,
63 GLint xoffset,
64 GLint yoffset,
65 GLint zoffset,
66 GLsizei width,
67 GLsizei height,
68 GLsizei depth,
69 GLint border,
70 GLenum format,
71 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -040072 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050073 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040074{
75 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -070076 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040077 {
Jamie Madill437fa652016-05-03 15:13:24 -040078 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040079 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040080 }
81
Geoff Lange8ebe7f2013-08-05 15:03:13 -040082 // Verify zero border
83 if (border != 0)
84 {
Jamie Madill437fa652016-05-03 15:13:24 -040085 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040086 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040087 }
88
Jamie Madill6f38f822014-06-06 17:12:20 -040089 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
90 std::numeric_limits<GLsizei>::max() - xoffset < width ||
91 std::numeric_limits<GLsizei>::max() - yoffset < height ||
92 std::numeric_limits<GLsizei>::max() - zoffset < depth)
93 {
Jamie Madill437fa652016-05-03 15:13:24 -040094 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040095 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040096 }
97
Geoff Langaae65a42014-05-26 12:43:44 -040098 const gl::Caps &caps = context->getCaps();
99
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400100 switch (target)
101 {
102 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500103 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
104 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400105 {
Jamie Madill437fa652016-05-03 15:13:24 -0400106 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108 }
109 break;
110
111 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
112 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
113 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
114 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
115 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
116 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500117 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 {
Jamie Madill437fa652016-05-03 15:13:24 -0400119 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500120 return false;
121 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400122
Geoff Langa9be0dc2014-12-17 12:34:40 -0500123 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
124 {
Jamie Madill437fa652016-05-03 15:13:24 -0400125 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 }
128 break;
129
130 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500131 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
132 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
133 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400134 {
Jamie Madill437fa652016-05-03 15:13:24 -0400135 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500136 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400137 }
138 break;
139
Geoff Langa9be0dc2014-12-17 12:34:40 -0500140 case GL_TEXTURE_2D_ARRAY:
141 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
142 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400143 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500144 {
Jamie Madill437fa652016-05-03 15:13:24 -0400145 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500146 return false;
147 }
148 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400149
150 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400151 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400153 }
154
Geoff Lang691e58c2014-12-19 17:03:25 -0500155 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 if (!texture)
157 {
Jamie Madill437fa652016-05-03 15:13:24 -0400158 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400159 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160 }
161
Geoff Lang69cce582015-09-17 13:20:36 -0400162 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400163 {
Jamie Madill437fa652016-05-03 15:13:24 -0400164 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400166 }
167
168 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400169 GLenum actualInternalFormat =
170 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400171 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400172 if (isCompressed)
173 {
tmartino7c102692015-10-02 16:43:40 -0400174 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400175 {
Jamie Madill437fa652016-05-03 15:13:24 -0400176 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400177 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400178 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400179 }
180
tmartino7c102692015-10-02 16:43:40 -0400181 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 {
Jamie Madill437fa652016-05-03 15:13:24 -0400183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400184 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400185 }
186
Martin Radev1be913c2016-07-11 17:59:16 +0300187 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
188 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400189 {
Jamie Madill437fa652016-05-03 15:13:24 -0400190 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400191 return false;
192 }
193
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400194 if (target == GL_TEXTURE_3D)
195 {
Jamie Madill437fa652016-05-03 15:13:24 -0400196 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 }
199 }
200 else
201 {
Geoff Langbaadf232014-08-04 13:58:02 -0400202 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400203 {
Geoff Lang5d601382014-07-22 15:14:06 -0400204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400205 }
206
207 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
208 {
Jamie Madill437fa652016-05-03 15:13:24 -0400209 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400211 }
212 }
213
214 // Validate sub image parameters
215 if (isSubImage)
216 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500217 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400218 {
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
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 if (width == 0 || height == 0 || depth == 0)
224 {
225 return false;
226 }
227
228 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
229 {
Jamie Madill437fa652016-05-03 15:13:24 -0400230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
234 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
235 std::numeric_limits<GLsizei>::max() - yoffset < height ||
236 std::numeric_limits<GLsizei>::max() - zoffset < depth)
237 {
Jamie Madill437fa652016-05-03 15:13:24 -0400238 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400239 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400240 }
241
Geoff Langa9be0dc2014-12-17 12:34:40 -0500242 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
243 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
244 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400245 {
Jamie Madill437fa652016-05-03 15:13:24 -0400246 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400248 }
249 }
250
Geoff Langff5b2d52016-09-07 11:32:23 -0400251 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
252 imageSize))
253 {
254 return false;
255 }
256
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400257 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700258 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400259 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400260 {
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400261 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
262 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400263 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400264 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400265 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400266 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
267
Geoff Langff5b2d52016-09-07 11:32:23 -0400268 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400269 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400270 context->handleError(
271 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400272 return false;
273 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400274 }
275
Jamie Madill7a5f7382014-03-05 15:01:24 -0500276 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700277 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500278 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400279 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400280 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500281 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400282 }
283
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400284 return true;
285}
286
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500287bool ValidateES3TexImage2DParameters(Context *context,
288 GLenum target,
289 GLint level,
290 GLenum internalformat,
291 bool isCompressed,
292 bool isSubImage,
293 GLint xoffset,
294 GLint yoffset,
295 GLint zoffset,
296 GLsizei width,
297 GLsizei height,
298 GLsizei depth,
299 GLint border,
300 GLenum format,
301 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400302 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500303 const GLvoid *pixels)
304{
305 if (!ValidTexture2DDestinationTarget(context, target))
306 {
Jamie Madill437fa652016-05-03 15:13:24 -0400307 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500308 return false;
309 }
310
311 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
312 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400313 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500314}
315
316bool ValidateES3TexImage3DParameters(Context *context,
317 GLenum target,
318 GLint level,
319 GLenum internalformat,
320 bool isCompressed,
321 bool isSubImage,
322 GLint xoffset,
323 GLint yoffset,
324 GLint zoffset,
325 GLsizei width,
326 GLsizei height,
327 GLsizei depth,
328 GLint border,
329 GLenum format,
330 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400331 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500332 const GLvoid *pixels)
333{
334 if (!ValidTexture3DDestinationTarget(context, target))
335 {
Jamie Madill437fa652016-05-03 15:13:24 -0400336 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500337 return false;
338 }
339
340 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
341 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400342 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500343}
344
Geoff Lang5d601382014-07-22 15:14:06 -0400345struct EffectiveInternalFormatInfo
346{
Jamie Madill76648fe2016-10-05 17:01:41 -0400347 GLenum effectiveFormat;
348 GLenum destFormat;
349 GLuint minRedBits;
350 GLuint maxRedBits;
351 GLuint minGreenBits;
352 GLuint maxGreenBits;
353 GLuint minBlueBits;
354 GLuint maxBlueBits;
355 GLuint minAlphaBits;
356 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400357};
358
Jamie Madill76648fe2016-10-05 17:01:41 -0400359static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
360 GLenum targetFormat,
361 const EffectiveInternalFormatInfo *list,
362 size_t size,
363 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400364{
Jamie Madill76648fe2016-10-05 17:01:41 -0400365 for (size_t curFormat = 0; curFormat < size; ++curFormat)
366 {
367 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
368 if ((formatInfo.destFormat == targetFormat) &&
369 (formatInfo.minRedBits <= srcFormat.redBits &&
370 formatInfo.maxRedBits >= srcFormat.redBits) &&
371 (formatInfo.minGreenBits <= srcFormat.greenBits &&
372 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
373 (formatInfo.minBlueBits <= srcFormat.blueBits &&
374 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
375 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
376 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
377 {
378 *outEffectiveFormat = formatInfo.effectiveFormat;
379 return true;
380 }
381 }
Geoff Lang5d601382014-07-22 15:14:06 -0400382
Jamie Madill76648fe2016-10-05 17:01:41 -0400383 *outEffectiveFormat = GL_NONE;
384 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400385}
386
Jamie Madill76648fe2016-10-05 17:01:41 -0400387bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
388 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400389{
Jamie Madill76648fe2016-10-05 17:01:41 -0400390 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
391 // Effective internal format coresponding to destination internal format and linear source
392 // buffer component sizes.
393 // | Source channel min/max sizes |
394 // Effective Internal Format | N/A | R | G | B | A |
395 // clang-format off
396 constexpr EffectiveInternalFormatInfo list[] = {
397 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
398 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
399 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
400 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
401 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
402 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
403 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
404 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
405 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
406 };
407 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400408
Jamie Madill76648fe2016-10-05 17:01:41 -0400409 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
410}
Geoff Lang5d601382014-07-22 15:14:06 -0400411
Jamie Madill76648fe2016-10-05 17:01:41 -0400412bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
413 const InternalFormat &destFormat,
414 GLenum *outEffectiveFormat)
415{
416 constexpr GLuint umax = UINT_MAX;
417
418 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
419 // Effective internal format coresponding to destination internal format andlinear source buffer
420 // component sizes.
421 // | Source channel min/max sizes |
422 // Effective Internal Format | Dest Format | R | G | B | A |
423 // clang-format off
424 constexpr EffectiveInternalFormatInfo list[] = {
425 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
426 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
427 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
428 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
429 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
430 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
431 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
432 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
433 };
434 // clang-format on
435
436 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
437 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400438}
439
440static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
441 GLenum *outEffectiveFormat)
442{
Geoff Lang5d601382014-07-22 15:14:06 -0400443 if (destFormat.pixelBytes > 0)
444 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400445 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400446 }
447 else
448 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400449 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400450 }
Geoff Lang5d601382014-07-22 15:14:06 -0400451}
452
453struct CopyConversion
454{
455 GLenum mTextureFormat;
456 GLenum mFramebufferFormat;
457
458 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
459 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
460
461 bool operator<(const CopyConversion& other) const
462 {
463 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
464 }
465};
466
467typedef std::set<CopyConversion> CopyConversionSet;
468
469static CopyConversionSet BuildValidES3CopyTexImageCombinations()
470{
471 CopyConversionSet set;
472
473 // From ES 3.0.1 spec, table 3.15
474 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
475 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
476 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
477 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
478 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
479 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
480 set.insert(CopyConversion(GL_RED, GL_RED));
481 set.insert(CopyConversion(GL_RED, GL_RG));
482 set.insert(CopyConversion(GL_RED, GL_RGB));
483 set.insert(CopyConversion(GL_RED, GL_RGBA));
484 set.insert(CopyConversion(GL_RG, GL_RG));
485 set.insert(CopyConversion(GL_RG, GL_RGB));
486 set.insert(CopyConversion(GL_RG, GL_RGBA));
487 set.insert(CopyConversion(GL_RGB, GL_RGB));
488 set.insert(CopyConversion(GL_RGB, GL_RGBA));
489 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
490
491 // Necessary for ANGLE back-buffers
492 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
493 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
494 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
495 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
496 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
497 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
498 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400499 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400500
501 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
502 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
503 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
504 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
505 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
506 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
507 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
508 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
509 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
510 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
511
512 return set;
513}
514
Corentin Wallez76287682016-04-25 09:23:38 -0400515static bool EqualOrFirstZero(GLuint first, GLuint second)
516{
517 return first == 0 || first == second;
518}
519
Jamie Madill0c8abca2016-07-22 20:21:26 -0400520static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
521 const Format &framebufferFormat,
522 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400523{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400524 const auto &textureFormatInfo = *textureFormat.info;
525 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400526
527 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400528 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
529 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400530 {
531 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
532 // must both be signed, unsigned, or fixed point and both source and destinations
533 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
534 // conversion between fixed and floating point.
535
Jamie Madill0c8abca2016-07-22 20:21:26 -0400536 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
537 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400538 {
539 return false;
540 }
541
Jamie Madill0c8abca2016-07-22 20:21:26 -0400542 if (((textureFormatInfo.componentType == GL_INT) !=
543 (framebufferFormatInfo.componentType == GL_INT)) ||
544 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
545 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400546 {
547 return false;
548 }
549
Jamie Madill0c8abca2016-07-22 20:21:26 -0400550 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
551 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
552 textureFormatInfo.componentType == GL_FLOAT) &&
553 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
554 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
555 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400556 {
557 return false;
558 }
559
560 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
561 // The effective internal format of the source buffer is determined with the following rules applied in order:
562 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
563 // effective internal format is the source buffer's sized internal format.
564 // * If the source buffer is a texture that was created with an unsized base internal format, then the
565 // effective internal format is the source image array's effective internal format, as specified by table
566 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
567 // specified by TexImage*.
568 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
569 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
570 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
571 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
572 // is SRGB.
573 const InternalFormat *sourceEffectiveFormat = NULL;
574 if (readBufferHandle != 0)
575 {
576 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400577 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400578 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400579 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400580 }
581 else
582 {
583 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
584 // texture. We can use the same table we use when creating textures to get its effective sized format.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400585 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
586 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500587 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400588 }
589 }
590 else
591 {
592 // The effective internal format must be derived from the source framebuffer's channel sizes.
593 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400594 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400595 {
596 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400597 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
598 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400599 {
600 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
601 }
602 else
603 {
604 return false;
605 }
606 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400607 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400608 {
609 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400610 if (textureFormat.sized &&
611 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
612 (framebufferFormatInfo.greenBits >= 1 &&
613 framebufferFormatInfo.greenBits <= 8) &&
614 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
615 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400616 {
617 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
618 }
619 else
620 {
621 return false;
622 }
623 }
624 else
625 {
626 UNREACHABLE();
627 return false;
628 }
629 }
630
Jamie Madill0c8abca2016-07-22 20:21:26 -0400631 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400632 {
Corentin Wallez76287682016-04-25 09:23:38 -0400633 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
634 // format is sized, component sizes of the source and destination formats must exactly
635 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400636 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
637 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
638 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
639 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400640 {
641 return false;
642 }
643 }
644
Geoff Lang5d601382014-07-22 15:14:06 -0400645 return true; // A conversion function exists, and no rule in the specification has precluded conversion
646 // between these formats.
647 }
648
649 return false;
650}
651
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500652bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
653 GLenum target,
654 GLint level,
655 GLenum internalformat,
656 bool isSubImage,
657 GLint xoffset,
658 GLint yoffset,
659 GLint zoffset,
660 GLint x,
661 GLint y,
662 GLsizei width,
663 GLsizei height,
664 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400666 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400667 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400668 xoffset, yoffset, zoffset, x, y, width, height, border,
669 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400670 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400671 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400672 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400673 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400674
Jamie Madill51f40ec2016-06-15 14:06:00 -0400675 const auto &state = context->getGLState();
676 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
677 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400678
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700679 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400680 {
Jamie Madill437fa652016-05-03 15:13:24 -0400681 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400682 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400683 }
684
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700685 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400686 {
Jamie Madill437fa652016-05-03 15:13:24 -0400687 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400688 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400689 }
690
Jamie Madill0c8abca2016-07-22 20:21:26 -0400691 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400692
693 if (isSubImage)
694 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400695 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500696 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400697 {
Jamie Madill437fa652016-05-03 15:13:24 -0400698 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400699 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700 }
701 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400702 else
703 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400704 // Use format/type from the source FBO. (Might not be perfect for all cases?)
705 const auto framebufferFormat = source->getFormat();
706 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
707 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400708 {
Jamie Madill437fa652016-05-03 15:13:24 -0400709 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400710 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400711 }
712 }
713
Geoff Lang784a8fd2013-09-24 12:33:16 -0400714 // If width or height is zero, it is a no-op. Return false without setting an error.
715 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400716}
717
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500718bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
719 GLenum target,
720 GLint level,
721 GLenum internalformat,
722 bool isSubImage,
723 GLint xoffset,
724 GLint yoffset,
725 GLint zoffset,
726 GLint x,
727 GLint y,
728 GLsizei width,
729 GLsizei height,
730 GLint border)
731{
732 if (!ValidTexture2DDestinationTarget(context, target))
733 {
Jamie Madill437fa652016-05-03 15:13:24 -0400734 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500735 return false;
736 }
737
738 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
739 xoffset, yoffset, zoffset, x, y, width, height,
740 border);
741}
742
743bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
744 GLenum target,
745 GLint level,
746 GLenum internalformat,
747 bool isSubImage,
748 GLint xoffset,
749 GLint yoffset,
750 GLint zoffset,
751 GLint x,
752 GLint y,
753 GLsizei width,
754 GLsizei height,
755 GLint border)
756{
757 if (!ValidTexture3DDestinationTarget(context, target))
758 {
Jamie Madill437fa652016-05-03 15:13:24 -0400759 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500760 return false;
761 }
762
763 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
764 xoffset, yoffset, zoffset, x, y, width, height,
765 border);
766}
767
768bool ValidateES3TexStorageParametersBase(Context *context,
769 GLenum target,
770 GLsizei levels,
771 GLenum internalformat,
772 GLsizei width,
773 GLsizei height,
774 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775{
776 if (width < 1 || height < 1 || depth < 1 || levels < 1)
777 {
Jamie Madill437fa652016-05-03 15:13:24 -0400778 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400779 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 }
781
Geoff Langb92c1332015-09-04 12:54:55 -0400782 GLsizei maxDim = std::max(width, height);
783 if (target != GL_TEXTURE_2D_ARRAY)
784 {
785 maxDim = std::max(maxDim, depth);
786 }
787
788 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 {
Jamie Madill437fa652016-05-03 15:13:24 -0400790 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400791 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 }
793
Geoff Langaae65a42014-05-26 12:43:44 -0400794 const gl::Caps &caps = context->getCaps();
795
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 switch (target)
797 {
798 case GL_TEXTURE_2D:
799 {
Geoff Langaae65a42014-05-26 12:43:44 -0400800 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
801 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 {
Jamie Madill437fa652016-05-03 15:13:24 -0400803 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400804 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805 }
806 }
807 break;
808
Geoff Lang01c21d22013-09-24 11:52:16 -0400809 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400810 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 if (width != height)
812 {
Jamie Madill437fa652016-05-03 15:13:24 -0400813 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 }
816
Geoff Langaae65a42014-05-26 12:43:44 -0400817 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 {
Jamie Madill437fa652016-05-03 15:13:24 -0400819 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 }
822 }
823 break;
824
825 case GL_TEXTURE_3D:
826 {
Geoff Langaae65a42014-05-26 12:43:44 -0400827 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
828 static_cast<GLuint>(height) > caps.max3DTextureSize ||
829 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 {
Jamie Madill437fa652016-05-03 15:13:24 -0400831 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400832 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 }
834 }
835 break;
836
837 case GL_TEXTURE_2D_ARRAY:
838 {
Geoff Langaae65a42014-05-26 12:43:44 -0400839 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
840 static_cast<GLuint>(height) > caps.max2DTextureSize ||
841 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 {
Jamie Madill437fa652016-05-03 15:13:24 -0400843 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400844 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400845 }
846 }
847 break;
848
849 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500850 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -0400851 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400852 }
853
Geoff Lang691e58c2014-12-19 17:03:25 -0500854 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 if (!texture || texture->id() == 0)
856 {
Jamie Madill437fa652016-05-03 15:13:24 -0400857 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400858 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 }
860
Geoff Lang69cce582015-09-17 13:20:36 -0400861 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400862 {
Jamie Madill437fa652016-05-03 15:13:24 -0400863 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400864 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 }
866
Geoff Lang5d601382014-07-22 15:14:06 -0400867 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +0300868 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 {
Jamie Madill437fa652016-05-03 15:13:24 -0400870 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400871 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400872 }
873
Geoff Lang5d601382014-07-22 15:14:06 -0400874 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400875 {
Jamie Madill437fa652016-05-03 15:13:24 -0400876 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 }
879
880 return true;
881}
882
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883bool ValidateES3TexStorage2DParameters(Context *context,
884 GLenum target,
885 GLsizei levels,
886 GLenum internalformat,
887 GLsizei width,
888 GLsizei height,
889 GLsizei depth)
890{
891 if (!ValidTexture2DTarget(context, target))
892 {
Jamie Madill437fa652016-05-03 15:13:24 -0400893 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500894 return false;
895 }
896
897 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
898 height, depth);
899}
900
901bool ValidateES3TexStorage3DParameters(Context *context,
902 GLenum target,
903 GLsizei levels,
904 GLenum internalformat,
905 GLsizei width,
906 GLsizei height,
907 GLsizei depth)
908{
909 if (!ValidTexture3DTarget(context, target))
910 {
Jamie Madill437fa652016-05-03 15:13:24 -0400911 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500912 return false;
913 }
914
915 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
916 height, depth);
917}
918
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500919bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
920{
Martin Radev1be913c2016-07-11 17:59:16 +0300921 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500922 {
Jamie Madill437fa652016-05-03 15:13:24 -0400923 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500924 return false;
925 }
926
927 return ValidateBeginQueryBase(context, target, id);
928}
929
930bool ValidateEndQuery(gl::Context *context, GLenum target)
931{
Martin Radev1be913c2016-07-11 17:59:16 +0300932 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500933 {
Jamie Madill437fa652016-05-03 15:13:24 -0400934 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500935 return false;
936 }
937
938 return ValidateEndQueryBase(context, target);
939}
940
941bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
942{
Martin Radev1be913c2016-07-11 17:59:16 +0300943 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500944 {
Jamie Madill437fa652016-05-03 15:13:24 -0400945 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500946 return false;
947 }
948
Geoff Lang2186c382016-10-14 10:54:54 -0400949 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500950}
951
952bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
953{
Martin Radev1be913c2016-07-11 17:59:16 +0300954 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500955 {
Jamie Madill437fa652016-05-03 15:13:24 -0400956 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500957 return false;
958 }
959
Geoff Lang2186c382016-10-14 10:54:54 -0400960 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500961}
962
Geoff Langb1196682014-07-23 13:47:29 -0400963bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -0400964 GLuint texture, GLint level, GLint layer)
965{
Martin Radev1be913c2016-07-11 17:59:16 +0300966 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400967 {
Jamie Madill437fa652016-05-03 15:13:24 -0400968 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400969 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400970 }
971
Jamie Madill55ec3b12014-07-03 10:38:57 -0400972 if (layer < 0)
973 {
Jamie Madill437fa652016-05-03 15:13:24 -0400974 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400975 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400976 }
977
978 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
979 {
980 return false;
981 }
982
983 const gl::Caps &caps = context->getCaps();
984 if (texture != 0)
985 {
986 gl::Texture *tex = context->getTexture(texture);
987 ASSERT(tex);
988
989 switch (tex->getTarget())
990 {
991 case GL_TEXTURE_2D_ARRAY:
992 {
993 if (level > gl::log2(caps.max2DTextureSize))
994 {
Jamie Madill437fa652016-05-03 15:13:24 -0400995 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400996 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400997 }
998
999 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1000 {
Jamie Madill437fa652016-05-03 15:13:24 -04001001 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001002 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001003 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001004 }
1005 break;
1006
1007 case GL_TEXTURE_3D:
1008 {
1009 if (level > gl::log2(caps.max3DTextureSize))
1010 {
Jamie Madill437fa652016-05-03 15:13:24 -04001011 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001013 }
1014
1015 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1016 {
Jamie Madill437fa652016-05-03 15:13:24 -04001017 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001019 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001020 }
1021 break;
1022
1023 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001024 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001026 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001027
Jamie Madilla3944d42016-07-22 22:13:26 -04001028 const auto &format = tex->getFormat(tex->getTarget(), level);
1029 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001030 {
Jamie Madill437fa652016-05-03 15:13:24 -04001031 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001032 return false;
1033 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001034 }
1035
1036 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001037}
1038
Corentin Walleze0902642014-11-04 12:32:15 -08001039bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1040 GLenum internalformat, GLsizei width, GLsizei height)
1041{
1042 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1043 {
1044 return false;
1045 }
1046
1047 //The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer format if samples is greater than zero.
1048 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1049 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001052 return false;
1053 }
1054
1055 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1056 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1057 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001060 Error(GL_INVALID_OPERATION,
1061 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001062 return false;
1063 }
1064
1065 return true;
1066}
1067
Austin Kinross08332632015-05-05 13:35:47 -07001068bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1069 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070{
Martin Radev1be913c2016-07-11 17:59:16 +03001071 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001072 {
Jamie Madill437fa652016-05-03 15:13:24 -04001073 context->handleError(
1074 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001075 return false;
1076 }
1077
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 bool defaultFramebuffer = false;
1079
1080 switch (target)
1081 {
1082 case GL_DRAW_FRAMEBUFFER:
1083 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001084 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1085 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001087 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1088 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001090 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093
Austin Kinross08332632015-05-05 13:35:47 -07001094 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001095}
1096
Jamie Madillc29968b2016-01-20 11:17:23 -05001097bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001098{
Martin Radev1be913c2016-07-11 17:59:16 +03001099 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001100 {
Jamie Madill437fa652016-05-03 15:13:24 -04001101 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001103 }
1104
Jamie Madill51f40ec2016-06-15 14:06:00 -04001105 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1106 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001107 {
Jamie Madill437fa652016-05-03 15:13:24 -04001108 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001110 }
1111
1112 return true;
1113}
1114
Olli Etuaho71dfb362016-03-10 14:04:27 +02001115bool ValidateDrawRangeElements(Context *context,
1116 GLenum mode,
1117 GLuint start,
1118 GLuint end,
1119 GLsizei count,
1120 GLenum type,
1121 const GLvoid *indices,
1122 IndexRange *indexRange)
1123{
Martin Radev1be913c2016-07-11 17:59:16 +03001124 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001125 {
Jamie Madill437fa652016-05-03 15:13:24 -04001126 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001127 return false;
1128 }
1129
1130 if (end < start)
1131 {
Jamie Madill437fa652016-05-03 15:13:24 -04001132 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001133 return false;
1134 }
1135
1136 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1137 {
1138 return false;
1139 }
1140
1141 if (indexRange->end > end || indexRange->start < start)
1142 {
1143 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001144 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001145 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1146 return false;
1147 }
1148 return true;
1149}
1150
Geoff Langb1196682014-07-23 13:47:29 -04001151bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001152{
Martin Radev1be913c2016-07-11 17:59:16 +03001153 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001154 {
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001157 }
1158
Jamie Madill78f41802014-08-25 15:47:55 -04001159 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001160}
1161
Jamie Madillb885e572015-02-03 16:16:04 -05001162bool ValidateReadBuffer(Context *context, GLenum src)
1163{
Martin Radev1be913c2016-07-11 17:59:16 +03001164 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001165 {
Jamie Madill437fa652016-05-03 15:13:24 -04001166 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001167 return false;
1168 }
1169
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001170 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001171
1172 if (readFBO == nullptr)
1173 {
Jamie Madill437fa652016-05-03 15:13:24 -04001174 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001175 return false;
1176 }
1177
1178 if (src == GL_NONE)
1179 {
1180 return true;
1181 }
1182
Olli Etuaho84c9f592016-03-09 14:37:25 +02001183 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001184 {
Jamie Madill437fa652016-05-03 15:13:24 -04001185 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001186 return false;
1187 }
1188
1189 if (readFBO->id() == 0)
1190 {
1191 if (src != GL_BACK)
1192 {
1193 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001195 return false;
1196 }
1197 }
1198 else
1199 {
1200 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1201
1202 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1203 {
1204 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001205 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001206 return false;
1207 }
1208 }
1209
1210 return true;
1211}
1212
Jamie Madill86af3d22015-07-21 15:14:07 -04001213bool ValidateCompressedTexImage3D(Context *context,
1214 GLenum target,
1215 GLint level,
1216 GLenum internalformat,
1217 GLsizei width,
1218 GLsizei height,
1219 GLsizei depth,
1220 GLint border,
1221 GLsizei imageSize,
1222 const GLvoid *data)
1223{
Martin Radev1be913c2016-07-11 17:59:16 +03001224 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001225 {
Jamie Madill437fa652016-05-03 15:13:24 -04001226 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001227 return false;
1228 }
1229
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001230 if (!ValidTextureTarget(context, target))
1231 {
1232 context->handleError(Error(GL_INVALID_ENUM));
1233 return false;
1234 }
1235
Jamie Madille2e406c2016-06-02 13:04:10 -04001236 // Validate image size
1237 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1238 {
1239 context->handleError(Error(GL_INVALID_VALUE));
1240 return false;
1241 }
1242
Jamie Madill86af3d22015-07-21 15:14:07 -04001243 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001244 if (!formatInfo.compressed)
1245 {
1246 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1247 return false;
1248 }
1249
Jamie Madill513558d2016-06-02 13:04:11 -04001250 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001251 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001252 if (blockSizeOrErr.isError())
1253 {
Jamie Madill513558d2016-06-02 13:04:11 -04001254 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001255 return false;
1256 }
1257 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001258 {
Jamie Madill437fa652016-05-03 15:13:24 -04001259 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001260 return false;
1261 }
1262
1263 // 3D texture target validation
1264 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1265 {
Jamie Madill437fa652016-05-03 15:13:24 -04001266 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001267 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1268 return false;
1269 }
1270
1271 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001272 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001273 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1274 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001275 {
1276 return false;
1277 }
1278
1279 return true;
1280}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001281
1282bool ValidateBindVertexArray(Context *context, GLuint array)
1283{
Martin Radev1be913c2016-07-11 17:59:16 +03001284 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001285 {
Jamie Madill437fa652016-05-03 15:13:24 -04001286 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001287 return false;
1288 }
1289
1290 return ValidateBindVertexArrayBase(context, array);
1291}
1292
Austin Kinrossbc781f32015-10-26 09:27:38 -07001293bool ValidateIsVertexArray(Context *context)
1294{
Martin Radev1be913c2016-07-11 17:59:16 +03001295 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001296 {
Jamie Madill437fa652016-05-03 15:13:24 -04001297 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001298 return false;
1299 }
1300
1301 return true;
1302}
Geoff Langc5629752015-12-07 16:29:04 -05001303
1304bool ValidateProgramBinary(Context *context,
1305 GLuint program,
1306 GLenum binaryFormat,
1307 const void *binary,
1308 GLint length)
1309{
Martin Radev1be913c2016-07-11 17:59:16 +03001310 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001311 {
Jamie Madill437fa652016-05-03 15:13:24 -04001312 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001313 return false;
1314 }
1315
1316 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1317}
1318
1319bool ValidateGetProgramBinary(Context *context,
1320 GLuint program,
1321 GLsizei bufSize,
1322 GLsizei *length,
1323 GLenum *binaryFormat,
1324 void *binary)
1325{
Martin Radev1be913c2016-07-11 17:59:16 +03001326 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001327 {
Jamie Madill437fa652016-05-03 15:13:24 -04001328 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001329 return false;
1330 }
1331
1332 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1333}
1334
Olli Etuahof0fee072016-03-30 15:11:58 +03001335bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001336{
Martin Radev1be913c2016-07-11 17:59:16 +03001337 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001338 {
Jamie Madill437fa652016-05-03 15:13:24 -04001339 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001340 return false;
1341 }
1342
1343 if (GetValidProgram(context, program) == nullptr)
1344 {
1345 return false;
1346 }
1347
1348 switch (pname)
1349 {
1350 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001351 if (value != GL_FALSE && value != GL_TRUE)
1352 {
Jamie Madill437fa652016-05-03 15:13:24 -04001353 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001354 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1355 return false;
1356 }
Geoff Langc5629752015-12-07 16:29:04 -05001357 break;
1358
1359 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001360 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001361 return false;
1362 }
1363
1364 return true;
1365}
Jamie Madillc29968b2016-01-20 11:17:23 -05001366
1367bool ValidateBlitFramebuffer(Context *context,
1368 GLint srcX0,
1369 GLint srcY0,
1370 GLint srcX1,
1371 GLint srcY1,
1372 GLint dstX0,
1373 GLint dstY0,
1374 GLint dstX1,
1375 GLint dstY1,
1376 GLbitfield mask,
1377 GLenum filter)
1378{
Martin Radev1be913c2016-07-11 17:59:16 +03001379 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001382 return false;
1383 }
1384
1385 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1386 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387}
Jamie Madillc29968b2016-01-20 11:17:23 -05001388
1389bool ValidateClearBufferiv(ValidationContext *context,
1390 GLenum buffer,
1391 GLint drawbuffer,
1392 const GLint *value)
1393{
1394 switch (buffer)
1395 {
1396 case GL_COLOR:
1397 if (drawbuffer < 0 ||
1398 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1399 {
Jamie Madill437fa652016-05-03 15:13:24 -04001400 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001401 return false;
1402 }
1403 break;
1404
1405 case GL_STENCIL:
1406 if (drawbuffer != 0)
1407 {
Jamie Madill437fa652016-05-03 15:13:24 -04001408 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001409 return false;
1410 }
1411 break;
1412
1413 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001414 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001415 return false;
1416 }
1417
1418 return ValidateClearBuffer(context);
1419}
1420
1421bool ValidateClearBufferuiv(ValidationContext *context,
1422 GLenum buffer,
1423 GLint drawbuffer,
1424 const GLuint *value)
1425{
1426 switch (buffer)
1427 {
1428 case GL_COLOR:
1429 if (drawbuffer < 0 ||
1430 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1431 {
Jamie Madill437fa652016-05-03 15:13:24 -04001432 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001433 return false;
1434 }
1435 break;
1436
1437 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001438 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001439 return false;
1440 }
1441
1442 return ValidateClearBuffer(context);
1443}
1444
1445bool ValidateClearBufferfv(ValidationContext *context,
1446 GLenum buffer,
1447 GLint drawbuffer,
1448 const GLfloat *value)
1449{
1450 switch (buffer)
1451 {
1452 case GL_COLOR:
1453 if (drawbuffer < 0 ||
1454 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1455 {
Jamie Madill437fa652016-05-03 15:13:24 -04001456 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001457 return false;
1458 }
1459 break;
1460
1461 case GL_DEPTH:
1462 if (drawbuffer != 0)
1463 {
Jamie Madill437fa652016-05-03 15:13:24 -04001464 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001465 return false;
1466 }
1467 break;
1468
1469 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001470 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001471 return false;
1472 }
1473
1474 return ValidateClearBuffer(context);
1475}
1476
1477bool ValidateClearBufferfi(ValidationContext *context,
1478 GLenum buffer,
1479 GLint drawbuffer,
1480 GLfloat depth,
1481 GLint stencil)
1482{
1483 switch (buffer)
1484 {
1485 case GL_DEPTH_STENCIL:
1486 if (drawbuffer != 0)
1487 {
Jamie Madill437fa652016-05-03 15:13:24 -04001488 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 return false;
1490 }
1491 break;
1492
1493 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001494 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001495 return false;
1496 }
1497
1498 return ValidateClearBuffer(context);
1499}
1500
1501bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1502{
Martin Radev1be913c2016-07-11 17:59:16 +03001503 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001504 {
Jamie Madill437fa652016-05-03 15:13:24 -04001505 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001506 return false;
1507 }
1508
1509 return ValidateDrawBuffersBase(context, n, bufs);
1510}
1511
1512bool ValidateCopyTexSubImage3D(Context *context,
1513 GLenum target,
1514 GLint level,
1515 GLint xoffset,
1516 GLint yoffset,
1517 GLint zoffset,
1518 GLint x,
1519 GLint y,
1520 GLsizei width,
1521 GLsizei height)
1522{
Martin Radev1be913c2016-07-11 17:59:16 +03001523 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001524 {
Jamie Madill437fa652016-05-03 15:13:24 -04001525 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001526 return false;
1527 }
1528
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001529 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1530 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001531}
1532
Jamie Madill73a84962016-02-12 09:27:23 -05001533bool ValidateTexImage3D(Context *context,
1534 GLenum target,
1535 GLint level,
1536 GLint internalformat,
1537 GLsizei width,
1538 GLsizei height,
1539 GLsizei depth,
1540 GLint border,
1541 GLenum format,
1542 GLenum type,
1543 const GLvoid *pixels)
1544{
Martin Radev1be913c2016-07-11 17:59:16 +03001545 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001546 {
Jamie Madill437fa652016-05-03 15:13:24 -04001547 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001548 return false;
1549 }
1550
1551 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001552 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001553 pixels);
1554}
1555
Geoff Langc52f6f12016-10-14 10:18:00 -04001556bool ValidateTexImage3DRobustANGLE(Context *context,
1557 GLenum target,
1558 GLint level,
1559 GLint internalformat,
1560 GLsizei width,
1561 GLsizei height,
1562 GLsizei depth,
1563 GLint border,
1564 GLenum format,
1565 GLenum type,
1566 GLsizei bufSize,
1567 const GLvoid *pixels)
1568{
1569 if (context->getClientMajorVersion() < 3)
1570 {
1571 context->handleError(Error(GL_INVALID_OPERATION));
1572 return false;
1573 }
1574
1575 if (!ValidateRobustEntryPoint(context, bufSize))
1576 {
1577 return false;
1578 }
1579
1580 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1581 0, 0, width, height, depth, border, format, type,
1582 bufSize, pixels);
1583}
1584
Jamie Madill73a84962016-02-12 09:27:23 -05001585bool ValidateTexSubImage3D(Context *context,
1586 GLenum target,
1587 GLint level,
1588 GLint xoffset,
1589 GLint yoffset,
1590 GLint zoffset,
1591 GLsizei width,
1592 GLsizei height,
1593 GLsizei depth,
1594 GLenum format,
1595 GLenum type,
1596 const GLvoid *pixels)
1597{
Martin Radev1be913c2016-07-11 17:59:16 +03001598 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001599 {
Jamie Madill437fa652016-05-03 15:13:24 -04001600 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001601 return false;
1602 }
1603
1604 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1605 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001606 -1, pixels);
1607}
1608
1609bool ValidateTexSubImage3DRobustANGLE(Context *context,
1610 GLenum target,
1611 GLint level,
1612 GLint xoffset,
1613 GLint yoffset,
1614 GLint zoffset,
1615 GLsizei width,
1616 GLsizei height,
1617 GLsizei depth,
1618 GLenum format,
1619 GLenum type,
1620 GLsizei bufSize,
1621 const GLvoid *pixels)
1622{
1623 if (context->getClientMajorVersion() < 3)
1624 {
1625 context->handleError(Error(GL_INVALID_OPERATION));
1626 return false;
1627 }
1628
1629 if (!ValidateRobustEntryPoint(context, bufSize))
1630 {
1631 return false;
1632 }
1633
1634 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1635 yoffset, zoffset, width, height, depth, 0, format, type,
1636 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001637}
1638
1639bool ValidateCompressedTexSubImage3D(Context *context,
1640 GLenum target,
1641 GLint level,
1642 GLint xoffset,
1643 GLint yoffset,
1644 GLint zoffset,
1645 GLsizei width,
1646 GLsizei height,
1647 GLsizei depth,
1648 GLenum format,
1649 GLsizei imageSize,
1650 const GLvoid *data)
1651{
Martin Radev1be913c2016-07-11 17:59:16 +03001652 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001653 {
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001655 return false;
1656 }
1657
1658 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001659 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001660 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001661 if (blockSizeOrErr.isError())
1662 {
1663 context->handleError(blockSizeOrErr.getError());
1664 return false;
1665 }
1666 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001667 {
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001669 return false;
1670 }
1671
1672 if (!data)
1673 {
Jamie Madill437fa652016-05-03 15:13:24 -04001674 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001675 return false;
1676 }
1677
1678 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001679 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001680}
1681
Olli Etuaho41997e72016-03-10 13:38:39 +02001682bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1683{
1684 return ValidateGenOrDeleteES3(context, n);
1685}
1686
1687bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1688{
1689 return ValidateGenOrDeleteES3(context, n);
1690}
1691
1692bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1693{
1694 return ValidateGenOrDeleteCountES3(context, count);
1695}
1696
1697bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1698{
1699 return ValidateGenOrDeleteCountES3(context, count);
1700}
1701
1702bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1703{
1704 return ValidateGenOrDeleteES3(context, n);
1705}
1706
1707bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1708{
1709 if (!ValidateGenOrDeleteES3(context, n))
1710 {
1711 return false;
1712 }
1713 for (GLint i = 0; i < n; ++i)
1714 {
1715 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1716 if (transformFeedback != nullptr && transformFeedback->isActive())
1717 {
1718 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001719 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001720 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1721 return false;
1722 }
1723 }
1724 return true;
1725}
1726
1727bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1728{
1729 return ValidateGenOrDeleteES3(context, n);
1730}
1731
1732bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1733{
1734 return ValidateGenOrDeleteES3(context, n);
1735}
1736
1737bool ValidateGenOrDeleteES3(Context *context, GLint n)
1738{
Martin Radev1be913c2016-07-11 17:59:16 +03001739 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001742 return false;
1743 }
1744 return ValidateGenOrDelete(context, n);
1745}
1746
1747bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1748{
Martin Radev1be913c2016-07-11 17:59:16 +03001749 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001752 return false;
1753 }
1754 if (count < 0)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001757 return false;
1758 }
1759 return true;
1760}
1761
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001762bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1763{
Martin Radev1be913c2016-07-11 17:59:16 +03001764 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001765 {
Jamie Madill437fa652016-05-03 15:13:24 -04001766 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001767 return false;
1768 }
1769 switch (primitiveMode)
1770 {
1771 case GL_TRIANGLES:
1772 case GL_LINES:
1773 case GL_POINTS:
1774 break;
1775
1776 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001778 return false;
1779 }
1780
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001781 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001782 ASSERT(transformFeedback != nullptr);
1783
1784 if (transformFeedback->isActive())
1785 {
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001787 return false;
1788 }
1789 return true;
1790}
1791
Olli Etuaho4f667482016-03-30 15:56:35 +03001792bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1793{
Geoff Lang496c02d2016-10-20 11:38:11 -07001794 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1795}
1796
1797bool ValidateGetBufferPointervRobustANGLE(Context *context,
1798 GLenum target,
1799 GLenum pname,
1800 GLsizei bufSize,
1801 GLsizei *length,
1802 GLvoid **params)
1803{
1804 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001805 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001806 return false;
1807 }
1808
Geoff Lang496c02d2016-10-20 11:38:11 -07001809 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1810 {
1811 return false;
1812 }
1813
1814 if (!ValidateRobustBufferSize(context, bufSize, *length))
1815 {
1816 return false;
1817 }
1818
1819 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001820}
1821
1822bool ValidateUnmapBuffer(Context *context, GLenum target)
1823{
Martin Radev1be913c2016-07-11 17:59:16 +03001824 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001827 return false;
1828 }
1829
1830 return ValidateUnmapBufferBase(context, target);
1831}
1832
1833bool ValidateMapBufferRange(Context *context,
1834 GLenum target,
1835 GLintptr offset,
1836 GLsizeiptr length,
1837 GLbitfield access)
1838{
Martin Radev1be913c2016-07-11 17:59:16 +03001839 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001840 {
Jamie Madill437fa652016-05-03 15:13:24 -04001841 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001842 return false;
1843 }
1844
1845 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1846}
1847
1848bool ValidateFlushMappedBufferRange(Context *context,
1849 GLenum target,
1850 GLintptr offset,
1851 GLsizeiptr length)
1852{
Martin Radev1be913c2016-07-11 17:59:16 +03001853 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001856 return false;
1857 }
1858
1859 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1860}
1861
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001862bool ValidateIndexedStateQuery(ValidationContext *context,
1863 GLenum pname,
1864 GLuint index,
1865 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001866{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001867 if (length)
1868 {
1869 *length = 0;
1870 }
1871
Martin Radev66fb8202016-07-28 11:45:20 +03001872 GLenum nativeType;
1873 unsigned int numParams;
1874 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1875 {
1876 context->handleError(Error(GL_INVALID_ENUM));
1877 return false;
1878 }
1879
1880 const Caps &caps = context->getCaps();
1881 switch (pname)
1882 {
1883 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1884 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1885 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1886 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1887 {
1888 context->handleError(Error(GL_INVALID_VALUE));
1889 return false;
1890 }
1891 break;
1892
1893 case GL_UNIFORM_BUFFER_START:
1894 case GL_UNIFORM_BUFFER_SIZE:
1895 case GL_UNIFORM_BUFFER_BINDING:
1896 if (index >= caps.maxUniformBufferBindings)
1897 {
1898 context->handleError(Error(GL_INVALID_VALUE));
1899 return false;
1900 }
1901 break;
1902 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1903 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1904 if (index >= 3u)
1905 {
1906 context->handleError(Error(GL_INVALID_VALUE));
1907 return false;
1908 }
1909 break;
1910 default:
1911 context->handleError(Error(GL_INVALID_ENUM));
1912 return false;
1913 }
1914
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001915 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001916 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001917 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001918 }
1919
1920 return true;
1921}
1922
1923bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1924{
1925 if (!context->getGLVersion().isES3OrGreater())
1926 {
1927 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1928 return false;
1929 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001930 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001931}
1932
1933bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1934{
1935 if (!context->getGLVersion().isES3OrGreater())
1936 {
1937 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1938 return false;
1939 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001940 return ValidateIndexedStateQuery(context, target, index, nullptr);
1941}
1942
1943bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1944 GLenum target,
1945 GLuint index,
1946 GLsizei bufSize,
1947 GLsizei *length,
1948 GLint64 *data)
1949{
1950 if (!context->getGLVersion().isES3OrGreater())
1951 {
1952 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1953 return false;
1954 }
1955
1956 if (!ValidateRobustEntryPoint(context, bufSize))
1957 {
1958 return false;
1959 }
1960
1961 if (!ValidateIndexedStateQuery(context, target, index, length))
1962 {
1963 return false;
1964 }
1965
1966 if (!ValidateRobustBufferSize(context, bufSize, *length))
1967 {
1968 return false;
1969 }
1970
1971 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001972}
1973
Jamie Madillc29968b2016-01-20 11:17:23 -05001974} // namespace gl