blob: 3b3a56897c70e22988b4bd7ab0f30c8b66c6f84b [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
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);
Geoff Langeb66a6e2016-10-31 13:06:12 -040034 if (!formatInfo.textureSupport(context->getClientVersion(), 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
Geoff Langeb66a6e2016-10-31 13:06:12 -0400187 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400188 {
Jamie Madill437fa652016-05-03 15:13:24 -0400189 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400190 return false;
191 }
192
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400193 if (target == GL_TEXTURE_3D)
194 {
Jamie Madill437fa652016-05-03 15:13:24 -0400195 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400196 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400197 }
198 }
199 else
200 {
Geoff Langbaadf232014-08-04 13:58:02 -0400201 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400202 {
Geoff Lang5d601382014-07-22 15:14:06 -0400203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400204 }
205
206 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
207 {
Jamie Madill437fa652016-05-03 15:13:24 -0400208 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400210 }
211 }
212
213 // Validate sub image parameters
214 if (isSubImage)
215 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500216 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400217 {
Jamie Madill437fa652016-05-03 15:13:24 -0400218 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400219 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 }
221
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 if (width == 0 || height == 0 || depth == 0)
223 {
224 return false;
225 }
226
227 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
228 {
Jamie Madill437fa652016-05-03 15:13:24 -0400229 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400231 }
232
233 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
234 std::numeric_limits<GLsizei>::max() - yoffset < height ||
235 std::numeric_limits<GLsizei>::max() - zoffset < depth)
236 {
Jamie Madill437fa652016-05-03 15:13:24 -0400237 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400238 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400239 }
240
Geoff Langa9be0dc2014-12-17 12:34:40 -0500241 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
242 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
243 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400244 {
Jamie Madill437fa652016-05-03 15:13:24 -0400245 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400246 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400247 }
248 }
249
Geoff Langff5b2d52016-09-07 11:32:23 -0400250 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
251 imageSize))
252 {
253 return false;
254 }
255
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400256 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700257 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400258 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400259 {
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400260 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
261 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400262 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400263 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400264 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400265 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
266
Geoff Langff5b2d52016-09-07 11:32:23 -0400267 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400268 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400269 context->handleError(
270 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400271 return false;
272 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400273 }
274
Jamie Madill7a5f7382014-03-05 15:01:24 -0500275 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700276 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500277 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400278 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400279 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500280 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400281 }
282
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400283 return true;
284}
285
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500286bool ValidateES3TexImage2DParameters(Context *context,
287 GLenum target,
288 GLint level,
289 GLenum internalformat,
290 bool isCompressed,
291 bool isSubImage,
292 GLint xoffset,
293 GLint yoffset,
294 GLint zoffset,
295 GLsizei width,
296 GLsizei height,
297 GLsizei depth,
298 GLint border,
299 GLenum format,
300 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400301 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500302 const GLvoid *pixels)
303{
304 if (!ValidTexture2DDestinationTarget(context, target))
305 {
Jamie Madill437fa652016-05-03 15:13:24 -0400306 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500307 return false;
308 }
309
310 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
311 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400312 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500313}
314
315bool ValidateES3TexImage3DParameters(Context *context,
316 GLenum target,
317 GLint level,
318 GLenum internalformat,
319 bool isCompressed,
320 bool isSubImage,
321 GLint xoffset,
322 GLint yoffset,
323 GLint zoffset,
324 GLsizei width,
325 GLsizei height,
326 GLsizei depth,
327 GLint border,
328 GLenum format,
329 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400330 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500331 const GLvoid *pixels)
332{
333 if (!ValidTexture3DDestinationTarget(context, target))
334 {
Jamie Madill437fa652016-05-03 15:13:24 -0400335 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500336 return false;
337 }
338
339 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
340 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400341 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500342}
343
Geoff Lang5d601382014-07-22 15:14:06 -0400344struct EffectiveInternalFormatInfo
345{
Jamie Madill76648fe2016-10-05 17:01:41 -0400346 GLenum effectiveFormat;
347 GLenum destFormat;
348 GLuint minRedBits;
349 GLuint maxRedBits;
350 GLuint minGreenBits;
351 GLuint maxGreenBits;
352 GLuint minBlueBits;
353 GLuint maxBlueBits;
354 GLuint minAlphaBits;
355 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400356};
357
Jamie Madill76648fe2016-10-05 17:01:41 -0400358static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
359 GLenum targetFormat,
360 const EffectiveInternalFormatInfo *list,
361 size_t size,
362 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400363{
Jamie Madill76648fe2016-10-05 17:01:41 -0400364 for (size_t curFormat = 0; curFormat < size; ++curFormat)
365 {
366 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
367 if ((formatInfo.destFormat == targetFormat) &&
368 (formatInfo.minRedBits <= srcFormat.redBits &&
369 formatInfo.maxRedBits >= srcFormat.redBits) &&
370 (formatInfo.minGreenBits <= srcFormat.greenBits &&
371 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
372 (formatInfo.minBlueBits <= srcFormat.blueBits &&
373 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
374 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
375 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
376 {
377 *outEffectiveFormat = formatInfo.effectiveFormat;
378 return true;
379 }
380 }
Geoff Lang5d601382014-07-22 15:14:06 -0400381
Jamie Madill76648fe2016-10-05 17:01:41 -0400382 *outEffectiveFormat = GL_NONE;
383 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400384}
385
Jamie Madill76648fe2016-10-05 17:01:41 -0400386bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
387 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400388{
Jamie Madill76648fe2016-10-05 17:01:41 -0400389 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
390 // Effective internal format coresponding to destination internal format and linear source
391 // buffer component sizes.
392 // | Source channel min/max sizes |
393 // Effective Internal Format | N/A | R | G | B | A |
394 // clang-format off
395 constexpr EffectiveInternalFormatInfo list[] = {
396 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
397 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
398 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
399 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
400 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
401 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
402 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
403 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
404 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
405 };
406 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400407
Jamie Madill76648fe2016-10-05 17:01:41 -0400408 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
409}
Geoff Lang5d601382014-07-22 15:14:06 -0400410
Jamie Madill76648fe2016-10-05 17:01:41 -0400411bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
412 const InternalFormat &destFormat,
413 GLenum *outEffectiveFormat)
414{
415 constexpr GLuint umax = UINT_MAX;
416
417 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
418 // Effective internal format coresponding to destination internal format andlinear source buffer
419 // component sizes.
420 // | Source channel min/max sizes |
421 // Effective Internal Format | Dest Format | R | G | B | A |
422 // clang-format off
423 constexpr EffectiveInternalFormatInfo list[] = {
424 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
425 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
426 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
427 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
428 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
429 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
430 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
431 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
432 };
433 // clang-format on
434
435 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
436 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400437}
438
439static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
440 GLenum *outEffectiveFormat)
441{
Geoff Lang5d601382014-07-22 15:14:06 -0400442 if (destFormat.pixelBytes > 0)
443 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400444 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400445 }
446 else
447 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400448 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400449 }
Geoff Lang5d601382014-07-22 15:14:06 -0400450}
451
Corentin Wallez76287682016-04-25 09:23:38 -0400452static bool EqualOrFirstZero(GLuint first, GLuint second)
453{
454 return first == 0 || first == second;
455}
456
Jamie Madill0c8abca2016-07-22 20:21:26 -0400457static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
458 const Format &framebufferFormat,
459 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400460{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400461 const auto &textureFormatInfo = *textureFormat.info;
462 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400463
Jamie Madill21b786b2016-11-01 17:41:31 -0400464 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400465 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400466 return false;
467 }
Geoff Lang5d601382014-07-22 15:14:06 -0400468
Jamie Madill21b786b2016-11-01 17:41:31 -0400469 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
470 // must both be signed, unsigned, or fixed point and both source and destinations
471 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
472 // conversion between fixed and floating point.
473
474 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
475 (framebufferFormatInfo.colorEncoding == GL_SRGB))
476 {
477 return false;
478 }
479
480 if (((textureFormatInfo.componentType == GL_INT) !=
481 (framebufferFormatInfo.componentType == GL_INT)) ||
482 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
483 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
484 {
485 return false;
486 }
487
488 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
489 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
490 textureFormatInfo.componentType == GL_FLOAT) &&
491 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
492 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
493 framebufferFormatInfo.componentType == GL_FLOAT))
494 {
495 return false;
496 }
497
498 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
499 // The effective internal format of the source buffer is determined with the following rules
500 // applied in order:
501 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
502 // format then the effective internal format is the source buffer's sized internal format.
503 // * If the source buffer is a texture that was created with an unsized base internal format,
504 // then the effective internal format is the source image array's effective internal
505 // format, as specified by table 3.12, which is determined from the <format> and <type>
506 // that were used when the source image array was specified by TexImage*.
507 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
508 // where Destination Internal Format matches internalformat and where the [source channel
509 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
510 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
511 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
512 const InternalFormat *sourceEffectiveFormat = NULL;
513 if (readBufferHandle != 0)
514 {
515 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
516 // renderbuffer
517 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400518 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400519 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400520 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400521 else
Geoff Lang5d601382014-07-22 15:14:06 -0400522 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400523 // Renderbuffers cannot be created with an unsized internal format, so this must be an
524 // unsized-format texture. We can use the same table we use when creating textures to
525 // get its effective sized format.
526 GLenum sizedInternalFormat =
527 GetSizedInternalFormat(framebufferFormatInfo.format, framebufferFormatInfo.type);
528 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400529 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400530 }
531 else
532 {
533 // The effective internal format must be derived from the source framebuffer's channel
534 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
535 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400536 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400537 GLenum effectiveFormat;
538 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
539 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400540 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400541 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400542 }
543 else
544 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400545 return false;
546 }
547 }
548 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
549 {
550 // SRGB buffers can only be copied to sized format destinations according to table 3.18
551 if (textureFormat.sized &&
552 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
553 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
554 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
555 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
556 {
557 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
558 }
559 else
560 {
561 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400562 }
563 }
564 else
565 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400566 UNREACHABLE();
567 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400568 }
Geoff Lang5d601382014-07-22 15:14:06 -0400569 }
570
Jamie Madill21b786b2016-11-01 17:41:31 -0400571 if (textureFormat.sized)
572 {
573 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
574 // sized, component sizes of the source and destination formats must exactly match if the
575 // destination format exists.
576 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
577 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
578 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
579 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
580 {
581 return false;
582 }
583 }
584
585 return true; // A conversion function exists, and no rule in the specification has precluded
586 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400587}
588
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500589bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
590 GLenum target,
591 GLint level,
592 GLenum internalformat,
593 bool isSubImage,
594 GLint xoffset,
595 GLint yoffset,
596 GLint zoffset,
597 GLint x,
598 GLint y,
599 GLsizei width,
600 GLsizei height,
601 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400602{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400603 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400604 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400605 xoffset, yoffset, zoffset, x, y, width, height, border,
606 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400607 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400608 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400609 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400610 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400611
Jamie Madill51f40ec2016-06-15 14:06:00 -0400612 const auto &state = context->getGLState();
613 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
614 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400615
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700616 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400617 {
Jamie Madill437fa652016-05-03 15:13:24 -0400618 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400619 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400620 }
621
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700622 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400623 {
Jamie Madill437fa652016-05-03 15:13:24 -0400624 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400625 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400626 }
627
Jamie Madill0c8abca2016-07-22 20:21:26 -0400628 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400629
630 if (isSubImage)
631 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400632 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500633 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400634 {
Jamie Madill437fa652016-05-03 15:13:24 -0400635 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400637 }
638 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400639 else
640 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400641 // Use format/type from the source FBO. (Might not be perfect for all cases?)
642 const auto framebufferFormat = source->getFormat();
643 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
644 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400645 {
Jamie Madill437fa652016-05-03 15:13:24 -0400646 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400647 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400648 }
649 }
650
Geoff Lang784a8fd2013-09-24 12:33:16 -0400651 // If width or height is zero, it is a no-op. Return false without setting an error.
652 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400653}
654
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500655bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
656 GLenum target,
657 GLint level,
658 GLenum internalformat,
659 bool isSubImage,
660 GLint xoffset,
661 GLint yoffset,
662 GLint zoffset,
663 GLint x,
664 GLint y,
665 GLsizei width,
666 GLsizei height,
667 GLint border)
668{
669 if (!ValidTexture2DDestinationTarget(context, target))
670 {
Jamie Madill437fa652016-05-03 15:13:24 -0400671 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500672 return false;
673 }
674
675 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
676 xoffset, yoffset, zoffset, x, y, width, height,
677 border);
678}
679
680bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
681 GLenum target,
682 GLint level,
683 GLenum internalformat,
684 bool isSubImage,
685 GLint xoffset,
686 GLint yoffset,
687 GLint zoffset,
688 GLint x,
689 GLint y,
690 GLsizei width,
691 GLsizei height,
692 GLint border)
693{
694 if (!ValidTexture3DDestinationTarget(context, target))
695 {
Jamie Madill437fa652016-05-03 15:13:24 -0400696 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500697 return false;
698 }
699
700 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
701 xoffset, yoffset, zoffset, x, y, width, height,
702 border);
703}
704
705bool ValidateES3TexStorageParametersBase(Context *context,
706 GLenum target,
707 GLsizei levels,
708 GLenum internalformat,
709 GLsizei width,
710 GLsizei height,
711 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712{
713 if (width < 1 || height < 1 || depth < 1 || levels < 1)
714 {
Jamie Madill437fa652016-05-03 15:13:24 -0400715 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400716 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400717 }
718
Geoff Langb92c1332015-09-04 12:54:55 -0400719 GLsizei maxDim = std::max(width, height);
720 if (target != GL_TEXTURE_2D_ARRAY)
721 {
722 maxDim = std::max(maxDim, depth);
723 }
724
725 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400726 {
Jamie Madill437fa652016-05-03 15:13:24 -0400727 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400728 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400729 }
730
Geoff Langaae65a42014-05-26 12:43:44 -0400731 const gl::Caps &caps = context->getCaps();
732
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 switch (target)
734 {
735 case GL_TEXTURE_2D:
736 {
Geoff Langaae65a42014-05-26 12:43:44 -0400737 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
738 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 {
Jamie Madill437fa652016-05-03 15:13:24 -0400740 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400741 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742 }
743 }
744 break;
745
Geoff Lang01c21d22013-09-24 11:52:16 -0400746 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400748 if (width != height)
749 {
Jamie Madill437fa652016-05-03 15:13:24 -0400750 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400751 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 }
753
Geoff Langaae65a42014-05-26 12:43:44 -0400754 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 {
Jamie Madill437fa652016-05-03 15:13:24 -0400756 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400757 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400758 }
759 }
760 break;
761
762 case GL_TEXTURE_3D:
763 {
Geoff Langaae65a42014-05-26 12:43:44 -0400764 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
765 static_cast<GLuint>(height) > caps.max3DTextureSize ||
766 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 {
Jamie Madill437fa652016-05-03 15:13:24 -0400768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400769 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770 }
771 }
772 break;
773
774 case GL_TEXTURE_2D_ARRAY:
775 {
Geoff Langaae65a42014-05-26 12:43:44 -0400776 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
777 static_cast<GLuint>(height) > caps.max2DTextureSize ||
778 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 {
Jamie Madill437fa652016-05-03 15:13:24 -0400780 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400781 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 }
783 }
784 break;
785
786 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500787 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -0400788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 }
790
Geoff Lang691e58c2014-12-19 17:03:25 -0500791 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 if (!texture || texture->id() == 0)
793 {
Jamie Madill437fa652016-05-03 15:13:24 -0400794 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797
Geoff Lang69cce582015-09-17 13:20:36 -0400798 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400799 {
Jamie Madill437fa652016-05-03 15:13:24 -0400800 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 }
803
Geoff Lang5d601382014-07-22 15:14:06 -0400804 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400805 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 {
Jamie Madill437fa652016-05-03 15:13:24 -0400807 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400808 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 }
810
Geoff Lang5d601382014-07-22 15:14:06 -0400811 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 {
Jamie Madill437fa652016-05-03 15:13:24 -0400813 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 }
816
817 return true;
818}
819
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500820bool ValidateES3TexStorage2DParameters(Context *context,
821 GLenum target,
822 GLsizei levels,
823 GLenum internalformat,
824 GLsizei width,
825 GLsizei height,
826 GLsizei depth)
827{
828 if (!ValidTexture2DTarget(context, target))
829 {
Jamie Madill437fa652016-05-03 15:13:24 -0400830 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500831 return false;
832 }
833
834 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
835 height, depth);
836}
837
838bool ValidateES3TexStorage3DParameters(Context *context,
839 GLenum target,
840 GLsizei levels,
841 GLenum internalformat,
842 GLsizei width,
843 GLsizei height,
844 GLsizei depth)
845{
846 if (!ValidTexture3DTarget(context, target))
847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500849 return false;
850 }
851
852 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
853 height, depth);
854}
855
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500856bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
857{
Martin Radev1be913c2016-07-11 17:59:16 +0300858 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500859 {
Jamie Madill437fa652016-05-03 15:13:24 -0400860 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500861 return false;
862 }
863
864 return ValidateBeginQueryBase(context, target, id);
865}
866
867bool ValidateEndQuery(gl::Context *context, GLenum target)
868{
Martin Radev1be913c2016-07-11 17:59:16 +0300869 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500870 {
Jamie Madill437fa652016-05-03 15:13:24 -0400871 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500872 return false;
873 }
874
875 return ValidateEndQueryBase(context, target);
876}
877
878bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
879{
Martin Radev1be913c2016-07-11 17:59:16 +0300880 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500881 {
Jamie Madill437fa652016-05-03 15:13:24 -0400882 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500883 return false;
884 }
885
Geoff Lang2186c382016-10-14 10:54:54 -0400886 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500887}
888
889bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
890{
Martin Radev1be913c2016-07-11 17:59:16 +0300891 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500892 {
Jamie Madill437fa652016-05-03 15:13:24 -0400893 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500894 return false;
895 }
896
Geoff Lang2186c382016-10-14 10:54:54 -0400897 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500898}
899
Geoff Langb1196682014-07-23 13:47:29 -0400900bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -0400901 GLuint texture, GLint level, GLint layer)
902{
Martin Radev1be913c2016-07-11 17:59:16 +0300903 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400904 {
Jamie Madill437fa652016-05-03 15:13:24 -0400905 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400906 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400907 }
908
Jamie Madill55ec3b12014-07-03 10:38:57 -0400909 if (layer < 0)
910 {
Jamie Madill437fa652016-05-03 15:13:24 -0400911 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400912 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400913 }
914
915 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
916 {
917 return false;
918 }
919
920 const gl::Caps &caps = context->getCaps();
921 if (texture != 0)
922 {
923 gl::Texture *tex = context->getTexture(texture);
924 ASSERT(tex);
925
926 switch (tex->getTarget())
927 {
928 case GL_TEXTURE_2D_ARRAY:
929 {
930 if (level > gl::log2(caps.max2DTextureSize))
931 {
Jamie Madill437fa652016-05-03 15:13:24 -0400932 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400933 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400934 }
935
936 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
937 {
Jamie Madill437fa652016-05-03 15:13:24 -0400938 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400939 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400940 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400941 }
942 break;
943
944 case GL_TEXTURE_3D:
945 {
946 if (level > gl::log2(caps.max3DTextureSize))
947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400950 }
951
952 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400956 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400957 }
958 break;
959
960 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400963 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500964
Jamie Madilla3944d42016-07-22 22:13:26 -0400965 const auto &format = tex->getFormat(tex->getTarget(), level);
966 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500967 {
Jamie Madill437fa652016-05-03 15:13:24 -0400968 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500969 return false;
970 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400971 }
972
973 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -0400974}
975
Corentin Walleze0902642014-11-04 12:32:15 -0800976bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
977 GLenum internalformat, GLsizei width, GLsizei height)
978{
979 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
980 {
981 return false;
982 }
983
984 //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.
985 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
986 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
987 {
Jamie Madill437fa652016-05-03 15:13:24 -0400988 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -0800989 return false;
990 }
991
992 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
993 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
994 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
995 {
Jamie Madill437fa652016-05-03 15:13:24 -0400996 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +0200997 Error(GL_INVALID_OPERATION,
998 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -0800999 return false;
1000 }
1001
1002 return true;
1003}
1004
Austin Kinross08332632015-05-05 13:35:47 -07001005bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1006 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007{
Martin Radev1be913c2016-07-11 17:59:16 +03001008 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001009 {
Jamie Madill437fa652016-05-03 15:13:24 -04001010 context->handleError(
1011 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001012 return false;
1013 }
1014
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 bool defaultFramebuffer = false;
1016
1017 switch (target)
1018 {
1019 case GL_DRAW_FRAMEBUFFER:
1020 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001021 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1022 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001024 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1025 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001027 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001028 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 }
1030
Austin Kinross08332632015-05-05 13:35:47 -07001031 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032}
1033
Jamie Madillc29968b2016-01-20 11:17:23 -05001034bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001035{
Martin Radev1be913c2016-07-11 17:59:16 +03001036 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001040 }
1041
Jamie Madill51f40ec2016-06-15 14:06:00 -04001042 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1043 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001044 {
Jamie Madill437fa652016-05-03 15:13:24 -04001045 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001046 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001047 }
1048
1049 return true;
1050}
1051
Olli Etuaho71dfb362016-03-10 14:04:27 +02001052bool ValidateDrawRangeElements(Context *context,
1053 GLenum mode,
1054 GLuint start,
1055 GLuint end,
1056 GLsizei count,
1057 GLenum type,
1058 const GLvoid *indices,
1059 IndexRange *indexRange)
1060{
Martin Radev1be913c2016-07-11 17:59:16 +03001061 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001062 {
Jamie Madill437fa652016-05-03 15:13:24 -04001063 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001064 return false;
1065 }
1066
1067 if (end < start)
1068 {
Jamie Madill437fa652016-05-03 15:13:24 -04001069 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001070 return false;
1071 }
1072
1073 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1074 {
1075 return false;
1076 }
1077
1078 if (indexRange->end > end || indexRange->start < start)
1079 {
1080 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001082 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1083 return false;
1084 }
1085 return true;
1086}
1087
Geoff Langb1196682014-07-23 13:47:29 -04001088bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001089{
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001091 {
Jamie Madill437fa652016-05-03 15:13:24 -04001092 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001093 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001094 }
1095
Jamie Madill78f41802014-08-25 15:47:55 -04001096 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001097}
1098
Jamie Madillb885e572015-02-03 16:16:04 -05001099bool ValidateReadBuffer(Context *context, GLenum src)
1100{
Martin Radev1be913c2016-07-11 17:59:16 +03001101 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001102 {
Jamie Madill437fa652016-05-03 15:13:24 -04001103 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001104 return false;
1105 }
1106
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001107 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001108
1109 if (readFBO == nullptr)
1110 {
Jamie Madill437fa652016-05-03 15:13:24 -04001111 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001112 return false;
1113 }
1114
1115 if (src == GL_NONE)
1116 {
1117 return true;
1118 }
1119
Olli Etuaho84c9f592016-03-09 14:37:25 +02001120 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001121 {
Jamie Madill437fa652016-05-03 15:13:24 -04001122 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001123 return false;
1124 }
1125
1126 if (readFBO->id() == 0)
1127 {
1128 if (src != GL_BACK)
1129 {
1130 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001131 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001132 return false;
1133 }
1134 }
1135 else
1136 {
1137 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1138
1139 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1140 {
1141 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001142 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001143 return false;
1144 }
1145 }
1146
1147 return true;
1148}
1149
Jamie Madill86af3d22015-07-21 15:14:07 -04001150bool ValidateCompressedTexImage3D(Context *context,
1151 GLenum target,
1152 GLint level,
1153 GLenum internalformat,
1154 GLsizei width,
1155 GLsizei height,
1156 GLsizei depth,
1157 GLint border,
1158 GLsizei imageSize,
1159 const GLvoid *data)
1160{
Martin Radev1be913c2016-07-11 17:59:16 +03001161 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001162 {
Jamie Madill437fa652016-05-03 15:13:24 -04001163 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001164 return false;
1165 }
1166
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001167 if (!ValidTextureTarget(context, target))
1168 {
1169 context->handleError(Error(GL_INVALID_ENUM));
1170 return false;
1171 }
1172
Jamie Madille2e406c2016-06-02 13:04:10 -04001173 // Validate image size
1174 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1175 {
1176 context->handleError(Error(GL_INVALID_VALUE));
1177 return false;
1178 }
1179
Jamie Madill86af3d22015-07-21 15:14:07 -04001180 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001181 if (!formatInfo.compressed)
1182 {
1183 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1184 return false;
1185 }
1186
Jamie Madill513558d2016-06-02 13:04:11 -04001187 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001188 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001189 if (blockSizeOrErr.isError())
1190 {
Jamie Madill513558d2016-06-02 13:04:11 -04001191 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001192 return false;
1193 }
1194 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001195 {
Jamie Madill437fa652016-05-03 15:13:24 -04001196 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001197 return false;
1198 }
1199
1200 // 3D texture target validation
1201 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1202 {
Jamie Madill437fa652016-05-03 15:13:24 -04001203 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001204 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1205 return false;
1206 }
1207
1208 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001209 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001210 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1211 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001212 {
1213 return false;
1214 }
1215
1216 return true;
1217}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001218
1219bool ValidateBindVertexArray(Context *context, GLuint array)
1220{
Martin Radev1be913c2016-07-11 17:59:16 +03001221 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001222 {
Jamie Madill437fa652016-05-03 15:13:24 -04001223 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001224 return false;
1225 }
1226
1227 return ValidateBindVertexArrayBase(context, array);
1228}
1229
Austin Kinrossbc781f32015-10-26 09:27:38 -07001230bool ValidateIsVertexArray(Context *context)
1231{
Martin Radev1be913c2016-07-11 17:59:16 +03001232 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001233 {
Jamie Madill437fa652016-05-03 15:13:24 -04001234 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001235 return false;
1236 }
1237
1238 return true;
1239}
Geoff Langc5629752015-12-07 16:29:04 -05001240
1241bool ValidateProgramBinary(Context *context,
1242 GLuint program,
1243 GLenum binaryFormat,
1244 const void *binary,
1245 GLint length)
1246{
Martin Radev1be913c2016-07-11 17:59:16 +03001247 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001248 {
Jamie Madill437fa652016-05-03 15:13:24 -04001249 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001250 return false;
1251 }
1252
1253 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1254}
1255
1256bool ValidateGetProgramBinary(Context *context,
1257 GLuint program,
1258 GLsizei bufSize,
1259 GLsizei *length,
1260 GLenum *binaryFormat,
1261 void *binary)
1262{
Martin Radev1be913c2016-07-11 17:59:16 +03001263 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001264 {
Jamie Madill437fa652016-05-03 15:13:24 -04001265 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001266 return false;
1267 }
1268
1269 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1270}
1271
Olli Etuahof0fee072016-03-30 15:11:58 +03001272bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001273{
Martin Radev1be913c2016-07-11 17:59:16 +03001274 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001275 {
Jamie Madill437fa652016-05-03 15:13:24 -04001276 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001277 return false;
1278 }
1279
1280 if (GetValidProgram(context, program) == nullptr)
1281 {
1282 return false;
1283 }
1284
1285 switch (pname)
1286 {
1287 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001288 if (value != GL_FALSE && value != GL_TRUE)
1289 {
Jamie Madill437fa652016-05-03 15:13:24 -04001290 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001291 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1292 return false;
1293 }
Geoff Langc5629752015-12-07 16:29:04 -05001294 break;
1295
1296 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001297 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001298 return false;
1299 }
1300
1301 return true;
1302}
Jamie Madillc29968b2016-01-20 11:17:23 -05001303
1304bool ValidateBlitFramebuffer(Context *context,
1305 GLint srcX0,
1306 GLint srcY0,
1307 GLint srcX1,
1308 GLint srcY1,
1309 GLint dstX0,
1310 GLint dstY0,
1311 GLint dstX1,
1312 GLint dstY1,
1313 GLbitfield mask,
1314 GLenum filter)
1315{
Martin Radev1be913c2016-07-11 17:59:16 +03001316 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001317 {
Jamie Madill437fa652016-05-03 15:13:24 -04001318 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001319 return false;
1320 }
1321
1322 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1323 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324}
Jamie Madillc29968b2016-01-20 11:17:23 -05001325
1326bool ValidateClearBufferiv(ValidationContext *context,
1327 GLenum buffer,
1328 GLint drawbuffer,
1329 const GLint *value)
1330{
1331 switch (buffer)
1332 {
1333 case GL_COLOR:
1334 if (drawbuffer < 0 ||
1335 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001338 return false;
1339 }
1340 break;
1341
1342 case GL_STENCIL:
1343 if (drawbuffer != 0)
1344 {
Jamie Madill437fa652016-05-03 15:13:24 -04001345 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001346 return false;
1347 }
1348 break;
1349
1350 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001351 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001352 return false;
1353 }
1354
1355 return ValidateClearBuffer(context);
1356}
1357
1358bool ValidateClearBufferuiv(ValidationContext *context,
1359 GLenum buffer,
1360 GLint drawbuffer,
1361 const GLuint *value)
1362{
1363 switch (buffer)
1364 {
1365 case GL_COLOR:
1366 if (drawbuffer < 0 ||
1367 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1368 {
Jamie Madill437fa652016-05-03 15:13:24 -04001369 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001370 return false;
1371 }
1372 break;
1373
1374 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001375 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001376 return false;
1377 }
1378
1379 return ValidateClearBuffer(context);
1380}
1381
1382bool ValidateClearBufferfv(ValidationContext *context,
1383 GLenum buffer,
1384 GLint drawbuffer,
1385 const GLfloat *value)
1386{
1387 switch (buffer)
1388 {
1389 case GL_COLOR:
1390 if (drawbuffer < 0 ||
1391 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001394 return false;
1395 }
1396 break;
1397
1398 case GL_DEPTH:
1399 if (drawbuffer != 0)
1400 {
Jamie Madill437fa652016-05-03 15:13:24 -04001401 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001402 return false;
1403 }
1404 break;
1405
1406 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001407 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001408 return false;
1409 }
1410
1411 return ValidateClearBuffer(context);
1412}
1413
1414bool ValidateClearBufferfi(ValidationContext *context,
1415 GLenum buffer,
1416 GLint drawbuffer,
1417 GLfloat depth,
1418 GLint stencil)
1419{
1420 switch (buffer)
1421 {
1422 case GL_DEPTH_STENCIL:
1423 if (drawbuffer != 0)
1424 {
Jamie Madill437fa652016-05-03 15:13:24 -04001425 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001426 return false;
1427 }
1428 break;
1429
1430 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001431 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001432 return false;
1433 }
1434
1435 return ValidateClearBuffer(context);
1436}
1437
1438bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1439{
Martin Radev1be913c2016-07-11 17:59:16 +03001440 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001441 {
Jamie Madill437fa652016-05-03 15:13:24 -04001442 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001443 return false;
1444 }
1445
1446 return ValidateDrawBuffersBase(context, n, bufs);
1447}
1448
1449bool ValidateCopyTexSubImage3D(Context *context,
1450 GLenum target,
1451 GLint level,
1452 GLint xoffset,
1453 GLint yoffset,
1454 GLint zoffset,
1455 GLint x,
1456 GLint y,
1457 GLsizei width,
1458 GLsizei height)
1459{
Martin Radev1be913c2016-07-11 17:59:16 +03001460 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001463 return false;
1464 }
1465
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001466 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1467 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001468}
1469
Jamie Madill73a84962016-02-12 09:27:23 -05001470bool ValidateTexImage3D(Context *context,
1471 GLenum target,
1472 GLint level,
1473 GLint internalformat,
1474 GLsizei width,
1475 GLsizei height,
1476 GLsizei depth,
1477 GLint border,
1478 GLenum format,
1479 GLenum type,
1480 const GLvoid *pixels)
1481{
Martin Radev1be913c2016-07-11 17:59:16 +03001482 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001483 {
Jamie Madill437fa652016-05-03 15:13:24 -04001484 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001485 return false;
1486 }
1487
1488 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001489 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001490 pixels);
1491}
1492
Geoff Langc52f6f12016-10-14 10:18:00 -04001493bool ValidateTexImage3DRobustANGLE(Context *context,
1494 GLenum target,
1495 GLint level,
1496 GLint internalformat,
1497 GLsizei width,
1498 GLsizei height,
1499 GLsizei depth,
1500 GLint border,
1501 GLenum format,
1502 GLenum type,
1503 GLsizei bufSize,
1504 const GLvoid *pixels)
1505{
1506 if (context->getClientMajorVersion() < 3)
1507 {
1508 context->handleError(Error(GL_INVALID_OPERATION));
1509 return false;
1510 }
1511
1512 if (!ValidateRobustEntryPoint(context, bufSize))
1513 {
1514 return false;
1515 }
1516
1517 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1518 0, 0, width, height, depth, border, format, type,
1519 bufSize, pixels);
1520}
1521
Jamie Madill73a84962016-02-12 09:27:23 -05001522bool ValidateTexSubImage3D(Context *context,
1523 GLenum target,
1524 GLint level,
1525 GLint xoffset,
1526 GLint yoffset,
1527 GLint zoffset,
1528 GLsizei width,
1529 GLsizei height,
1530 GLsizei depth,
1531 GLenum format,
1532 GLenum type,
1533 const GLvoid *pixels)
1534{
Martin Radev1be913c2016-07-11 17:59:16 +03001535 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001538 return false;
1539 }
1540
1541 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1542 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001543 -1, pixels);
1544}
1545
1546bool ValidateTexSubImage3DRobustANGLE(Context *context,
1547 GLenum target,
1548 GLint level,
1549 GLint xoffset,
1550 GLint yoffset,
1551 GLint zoffset,
1552 GLsizei width,
1553 GLsizei height,
1554 GLsizei depth,
1555 GLenum format,
1556 GLenum type,
1557 GLsizei bufSize,
1558 const GLvoid *pixels)
1559{
1560 if (context->getClientMajorVersion() < 3)
1561 {
1562 context->handleError(Error(GL_INVALID_OPERATION));
1563 return false;
1564 }
1565
1566 if (!ValidateRobustEntryPoint(context, bufSize))
1567 {
1568 return false;
1569 }
1570
1571 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1572 yoffset, zoffset, width, height, depth, 0, format, type,
1573 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001574}
1575
1576bool ValidateCompressedTexSubImage3D(Context *context,
1577 GLenum target,
1578 GLint level,
1579 GLint xoffset,
1580 GLint yoffset,
1581 GLint zoffset,
1582 GLsizei width,
1583 GLsizei height,
1584 GLsizei depth,
1585 GLenum format,
1586 GLsizei imageSize,
1587 const GLvoid *data)
1588{
Martin Radev1be913c2016-07-11 17:59:16 +03001589 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001592 return false;
1593 }
1594
1595 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001596 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001597 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001598 if (blockSizeOrErr.isError())
1599 {
1600 context->handleError(blockSizeOrErr.getError());
1601 return false;
1602 }
1603 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001604 {
Jamie Madill437fa652016-05-03 15:13:24 -04001605 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001606 return false;
1607 }
1608
1609 if (!data)
1610 {
Jamie Madill437fa652016-05-03 15:13:24 -04001611 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001612 return false;
1613 }
1614
1615 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001616 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001617}
1618
Olli Etuaho41997e72016-03-10 13:38:39 +02001619bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1620{
1621 return ValidateGenOrDeleteES3(context, n);
1622}
1623
1624bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1625{
1626 return ValidateGenOrDeleteES3(context, n);
1627}
1628
1629bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1630{
1631 return ValidateGenOrDeleteCountES3(context, count);
1632}
1633
1634bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1635{
1636 return ValidateGenOrDeleteCountES3(context, count);
1637}
1638
1639bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1640{
1641 return ValidateGenOrDeleteES3(context, n);
1642}
1643
1644bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1645{
1646 if (!ValidateGenOrDeleteES3(context, n))
1647 {
1648 return false;
1649 }
1650 for (GLint i = 0; i < n; ++i)
1651 {
1652 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1653 if (transformFeedback != nullptr && transformFeedback->isActive())
1654 {
1655 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001657 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1658 return false;
1659 }
1660 }
1661 return true;
1662}
1663
1664bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1665{
1666 return ValidateGenOrDeleteES3(context, n);
1667}
1668
1669bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1670{
1671 return ValidateGenOrDeleteES3(context, n);
1672}
1673
1674bool ValidateGenOrDeleteES3(Context *context, GLint n)
1675{
Martin Radev1be913c2016-07-11 17:59:16 +03001676 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001677 {
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001679 return false;
1680 }
1681 return ValidateGenOrDelete(context, n);
1682}
1683
1684bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1685{
Martin Radev1be913c2016-07-11 17:59:16 +03001686 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001687 {
Jamie Madill437fa652016-05-03 15:13:24 -04001688 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001689 return false;
1690 }
1691 if (count < 0)
1692 {
Jamie Madill437fa652016-05-03 15:13:24 -04001693 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001694 return false;
1695 }
1696 return true;
1697}
1698
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001699bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1700{
Martin Radev1be913c2016-07-11 17:59:16 +03001701 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001702 {
Jamie Madill437fa652016-05-03 15:13:24 -04001703 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001704 return false;
1705 }
1706 switch (primitiveMode)
1707 {
1708 case GL_TRIANGLES:
1709 case GL_LINES:
1710 case GL_POINTS:
1711 break;
1712
1713 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001714 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001715 return false;
1716 }
1717
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001718 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001719 ASSERT(transformFeedback != nullptr);
1720
1721 if (transformFeedback->isActive())
1722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001724 return false;
1725 }
1726 return true;
1727}
1728
Olli Etuaho4f667482016-03-30 15:56:35 +03001729bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1730{
Geoff Lang496c02d2016-10-20 11:38:11 -07001731 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1732}
1733
1734bool ValidateGetBufferPointervRobustANGLE(Context *context,
1735 GLenum target,
1736 GLenum pname,
1737 GLsizei bufSize,
1738 GLsizei *length,
1739 GLvoid **params)
1740{
1741 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001742 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001743 return false;
1744 }
1745
Geoff Lang496c02d2016-10-20 11:38:11 -07001746 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1747 {
1748 return false;
1749 }
1750
1751 if (!ValidateRobustBufferSize(context, bufSize, *length))
1752 {
1753 return false;
1754 }
1755
1756 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001757}
1758
1759bool ValidateUnmapBuffer(Context *context, GLenum target)
1760{
Martin Radev1be913c2016-07-11 17:59:16 +03001761 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001762 {
Jamie Madill437fa652016-05-03 15:13:24 -04001763 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001764 return false;
1765 }
1766
1767 return ValidateUnmapBufferBase(context, target);
1768}
1769
1770bool ValidateMapBufferRange(Context *context,
1771 GLenum target,
1772 GLintptr offset,
1773 GLsizeiptr length,
1774 GLbitfield access)
1775{
Martin Radev1be913c2016-07-11 17:59:16 +03001776 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001779 return false;
1780 }
1781
1782 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1783}
1784
1785bool ValidateFlushMappedBufferRange(Context *context,
1786 GLenum target,
1787 GLintptr offset,
1788 GLsizeiptr length)
1789{
Martin Radev1be913c2016-07-11 17:59:16 +03001790 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001793 return false;
1794 }
1795
1796 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1797}
1798
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001799bool ValidateIndexedStateQuery(ValidationContext *context,
1800 GLenum pname,
1801 GLuint index,
1802 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001803{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001804 if (length)
1805 {
1806 *length = 0;
1807 }
1808
Martin Radev66fb8202016-07-28 11:45:20 +03001809 GLenum nativeType;
1810 unsigned int numParams;
1811 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1812 {
1813 context->handleError(Error(GL_INVALID_ENUM));
1814 return false;
1815 }
1816
1817 const Caps &caps = context->getCaps();
1818 switch (pname)
1819 {
1820 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1821 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1822 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1823 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1824 {
1825 context->handleError(Error(GL_INVALID_VALUE));
1826 return false;
1827 }
1828 break;
1829
1830 case GL_UNIFORM_BUFFER_START:
1831 case GL_UNIFORM_BUFFER_SIZE:
1832 case GL_UNIFORM_BUFFER_BINDING:
1833 if (index >= caps.maxUniformBufferBindings)
1834 {
1835 context->handleError(Error(GL_INVALID_VALUE));
1836 return false;
1837 }
1838 break;
1839 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1840 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1841 if (index >= 3u)
1842 {
1843 context->handleError(Error(GL_INVALID_VALUE));
1844 return false;
1845 }
1846 break;
1847 default:
1848 context->handleError(Error(GL_INVALID_ENUM));
1849 return false;
1850 }
1851
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001852 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001853 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001854 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001855 }
1856
1857 return true;
1858}
1859
1860bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1861{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001862 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001863 {
1864 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1865 return false;
1866 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001867 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001868}
1869
Geoff Langcf255ea2016-10-20 11:39:09 -07001870bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
1871 GLenum target,
1872 GLuint index,
1873 GLsizei bufSize,
1874 GLsizei *length,
1875 GLint *data)
1876{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001877 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07001878 {
1879 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1880 return false;
1881 }
1882
1883 if (!ValidateRobustEntryPoint(context, bufSize))
1884 {
1885 return false;
1886 }
1887
1888 if (!ValidateIndexedStateQuery(context, target, index, length))
1889 {
1890 return false;
1891 }
1892
1893 if (!ValidateRobustBufferSize(context, bufSize, *length))
1894 {
1895 return false;
1896 }
1897
1898 return true;
1899}
1900
Martin Radev66fb8202016-07-28 11:45:20 +03001901bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1902{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001903 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001904 {
1905 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1906 return false;
1907 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001908 return ValidateIndexedStateQuery(context, target, index, nullptr);
1909}
1910
1911bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1912 GLenum target,
1913 GLuint index,
1914 GLsizei bufSize,
1915 GLsizei *length,
1916 GLint64 *data)
1917{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001918 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001919 {
1920 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1921 return false;
1922 }
1923
1924 if (!ValidateRobustEntryPoint(context, bufSize))
1925 {
1926 return false;
1927 }
1928
1929 if (!ValidateIndexedStateQuery(context, target, index, length))
1930 {
1931 return false;
1932 }
1933
1934 if (!ValidateRobustBufferSize(context, bufSize, *length))
1935 {
1936 return false;
1937 }
1938
1939 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001940}
1941
Jamie Madillb0817d12016-11-01 15:48:31 -04001942bool ValidateCopyBufferSubData(ValidationContext *context,
1943 GLenum readTarget,
1944 GLenum writeTarget,
1945 GLintptr readOffset,
1946 GLintptr writeOffset,
1947 GLsizeiptr size)
1948{
1949 if (context->getClientMajorVersion() < 3)
1950 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001951 context->handleError(
1952 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001953 return false;
1954 }
1955
1956 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
1957 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001958 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001959 return false;
1960 }
1961
1962 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
1963 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
1964
1965 if (!readBuffer || !writeBuffer)
1966 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001967 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001968 return false;
1969 }
1970
1971 // Verify that readBuffer and writeBuffer are not currently mapped
1972 if (readBuffer->isMapped() || writeBuffer->isMapped())
1973 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001974 context->handleError(
1975 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001976 return false;
1977 }
1978
Jamie Madilld2f0c742016-11-02 10:34:41 -04001979 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
1980 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
1981 CheckedNumeric<GLintptr> checkedSize(size);
1982
1983 auto checkedReadSum = checkedReadOffset + checkedSize;
1984 auto checkedWriteSum = checkedWriteOffset + checkedSize;
1985
1986 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
1987 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
1988 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04001989 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001990 context->handleError(
1991 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04001992 return false;
1993 }
1994
Jamie Madilld2f0c742016-11-02 10:34:41 -04001995 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04001996 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001997 context->handleError(
1998 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001999 return false;
2000 }
2001
Jamie Madilld2f0c742016-11-02 10:34:41 -04002002 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2003 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2004 {
2005 context->handleError(
2006 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2007 return false;
2008 }
2009
2010 if (readBuffer == writeBuffer)
2011 {
2012 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2013 if (!checkedOffsetDiff.IsValid())
2014 {
2015 // This shold not be possible.
2016 UNREACHABLE();
2017 context->handleError(
2018 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2019 return false;
2020 }
2021
2022 if (checkedOffsetDiff.ValueOrDie() < size)
2023 {
2024 context->handleError(Error(GL_INVALID_VALUE));
2025 return false;
2026 }
2027 }
2028
Jamie Madillb0817d12016-11-01 15:48:31 -04002029 return true;
2030}
2031
Jamie Madillc29968b2016-01-20 11:17:23 -05002032} // namespace gl