blob: 87627a777773a8a018e482dd982eca846fe2d950 [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 Langc51642b2016-11-14 16:18:26 -0500171 if (isSubImage && actualInternalFormat == GL_NONE)
172 {
173 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
174 return false;
175 }
176
Geoff Lang5d601382014-07-22 15:14:06 -0400177 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400178 if (isCompressed)
179 {
tmartino7c102692015-10-02 16:43:40 -0400180 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400181 {
Jamie Madill437fa652016-05-03 15:13:24 -0400182 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400183 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400184 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400185 }
186
tmartino7c102692015-10-02 16:43:40 -0400187 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400188 {
Jamie Madill437fa652016-05-03 15:13:24 -0400189 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400191 }
192
Geoff Langeb66a6e2016-10-31 13:06:12 -0400193 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400194 {
Jamie Madill437fa652016-05-03 15:13:24 -0400195 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400196 return false;
197 }
198
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400199 if (target == GL_TEXTURE_3D)
200 {
Jamie Madill437fa652016-05-03 15:13:24 -0400201 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400202 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400203 }
204 }
205 else
206 {
Geoff Langbaadf232014-08-04 13:58:02 -0400207 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400208 {
Geoff Lang5d601382014-07-22 15:14:06 -0400209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400210 }
211
212 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
213 {
Jamie Madill437fa652016-05-03 15:13:24 -0400214 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400215 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400216 }
217 }
218
219 // Validate sub image parameters
220 if (isSubImage)
221 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500222 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 {
Jamie Madill437fa652016-05-03 15:13:24 -0400224 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400225 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400226 }
227
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400228 if (width == 0 || height == 0 || depth == 0)
229 {
230 return false;
231 }
232
233 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
234 {
Jamie Madill437fa652016-05-03 15:13:24 -0400235 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400237 }
238
239 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
240 std::numeric_limits<GLsizei>::max() - yoffset < height ||
241 std::numeric_limits<GLsizei>::max() - zoffset < depth)
242 {
Jamie Madill437fa652016-05-03 15:13:24 -0400243 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400244 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400245 }
246
Geoff Langa9be0dc2014-12-17 12:34:40 -0500247 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
248 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
249 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400250 {
Jamie Madill437fa652016-05-03 15:13:24 -0400251 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400252 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253 }
254 }
255
Geoff Langff5b2d52016-09-07 11:32:23 -0400256 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
257 imageSize))
258 {
259 return false;
260 }
261
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400262 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700263 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400264 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400265 {
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400266 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
267 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400268 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400269 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400270 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400271 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
272
Geoff Langff5b2d52016-09-07 11:32:23 -0400273 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400274 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400275 context->handleError(
276 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400277 return false;
278 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400279 }
280
Jamie Madill7a5f7382014-03-05 15:01:24 -0500281 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700282 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500283 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400284 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400285 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500286 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400287 }
288
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400289 return true;
290}
291
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500292bool ValidateES3TexImage2DParameters(Context *context,
293 GLenum target,
294 GLint level,
295 GLenum internalformat,
296 bool isCompressed,
297 bool isSubImage,
298 GLint xoffset,
299 GLint yoffset,
300 GLint zoffset,
301 GLsizei width,
302 GLsizei height,
303 GLsizei depth,
304 GLint border,
305 GLenum format,
306 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400307 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500308 const GLvoid *pixels)
309{
310 if (!ValidTexture2DDestinationTarget(context, target))
311 {
Jamie Madill437fa652016-05-03 15:13:24 -0400312 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500313 return false;
314 }
315
316 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
317 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400318 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500319}
320
321bool ValidateES3TexImage3DParameters(Context *context,
322 GLenum target,
323 GLint level,
324 GLenum internalformat,
325 bool isCompressed,
326 bool isSubImage,
327 GLint xoffset,
328 GLint yoffset,
329 GLint zoffset,
330 GLsizei width,
331 GLsizei height,
332 GLsizei depth,
333 GLint border,
334 GLenum format,
335 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400336 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500337 const GLvoid *pixels)
338{
339 if (!ValidTexture3DDestinationTarget(context, target))
340 {
Jamie Madill437fa652016-05-03 15:13:24 -0400341 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500342 return false;
343 }
344
345 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
346 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400347 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500348}
349
Geoff Lang5d601382014-07-22 15:14:06 -0400350struct EffectiveInternalFormatInfo
351{
Jamie Madill76648fe2016-10-05 17:01:41 -0400352 GLenum effectiveFormat;
353 GLenum destFormat;
354 GLuint minRedBits;
355 GLuint maxRedBits;
356 GLuint minGreenBits;
357 GLuint maxGreenBits;
358 GLuint minBlueBits;
359 GLuint maxBlueBits;
360 GLuint minAlphaBits;
361 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400362};
363
Jamie Madill76648fe2016-10-05 17:01:41 -0400364static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
365 GLenum targetFormat,
366 const EffectiveInternalFormatInfo *list,
367 size_t size,
368 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400369{
Jamie Madill76648fe2016-10-05 17:01:41 -0400370 for (size_t curFormat = 0; curFormat < size; ++curFormat)
371 {
372 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
373 if ((formatInfo.destFormat == targetFormat) &&
374 (formatInfo.minRedBits <= srcFormat.redBits &&
375 formatInfo.maxRedBits >= srcFormat.redBits) &&
376 (formatInfo.minGreenBits <= srcFormat.greenBits &&
377 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
378 (formatInfo.minBlueBits <= srcFormat.blueBits &&
379 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
380 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
381 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
382 {
383 *outEffectiveFormat = formatInfo.effectiveFormat;
384 return true;
385 }
386 }
Geoff Lang5d601382014-07-22 15:14:06 -0400387
Jamie Madill76648fe2016-10-05 17:01:41 -0400388 *outEffectiveFormat = GL_NONE;
389 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400390}
391
Jamie Madill76648fe2016-10-05 17:01:41 -0400392bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
393 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400394{
Jamie Madill76648fe2016-10-05 17:01:41 -0400395 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
396 // Effective internal format coresponding to destination internal format and linear source
397 // buffer component sizes.
398 // | Source channel min/max sizes |
399 // Effective Internal Format | N/A | R | G | B | A |
400 // clang-format off
401 constexpr EffectiveInternalFormatInfo list[] = {
402 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
403 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
404 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
405 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
406 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
407 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
408 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
409 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
410 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
411 };
412 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400413
Jamie Madill76648fe2016-10-05 17:01:41 -0400414 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
415}
Geoff Lang5d601382014-07-22 15:14:06 -0400416
Jamie Madill76648fe2016-10-05 17:01:41 -0400417bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
418 const InternalFormat &destFormat,
419 GLenum *outEffectiveFormat)
420{
421 constexpr GLuint umax = UINT_MAX;
422
423 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
424 // Effective internal format coresponding to destination internal format andlinear source buffer
425 // component sizes.
426 // | Source channel min/max sizes |
427 // Effective Internal Format | Dest Format | R | G | B | A |
428 // clang-format off
429 constexpr EffectiveInternalFormatInfo list[] = {
430 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
431 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
432 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
433 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
434 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
435 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
436 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
437 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
438 };
439 // clang-format on
440
441 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
442 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400443}
444
445static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
446 GLenum *outEffectiveFormat)
447{
Geoff Lang5d601382014-07-22 15:14:06 -0400448 if (destFormat.pixelBytes > 0)
449 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400450 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400451 }
452 else
453 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400454 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400455 }
Geoff Lang5d601382014-07-22 15:14:06 -0400456}
457
Corentin Wallez76287682016-04-25 09:23:38 -0400458static bool EqualOrFirstZero(GLuint first, GLuint second)
459{
460 return first == 0 || first == second;
461}
462
Jamie Madill0c8abca2016-07-22 20:21:26 -0400463static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
464 const Format &framebufferFormat,
465 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400466{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400467 const auto &textureFormatInfo = *textureFormat.info;
468 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400469
Jamie Madill21b786b2016-11-01 17:41:31 -0400470 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400471 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400472 return false;
473 }
Geoff Lang5d601382014-07-22 15:14:06 -0400474
Jamie Madill21b786b2016-11-01 17:41:31 -0400475 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
476 // must both be signed, unsigned, or fixed point and both source and destinations
477 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
478 // conversion between fixed and floating point.
479
480 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
481 (framebufferFormatInfo.colorEncoding == GL_SRGB))
482 {
483 return false;
484 }
485
486 if (((textureFormatInfo.componentType == GL_INT) !=
487 (framebufferFormatInfo.componentType == GL_INT)) ||
488 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
489 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
490 {
491 return false;
492 }
493
494 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
495 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
496 textureFormatInfo.componentType == GL_FLOAT) &&
497 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
498 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
499 framebufferFormatInfo.componentType == GL_FLOAT))
500 {
501 return false;
502 }
503
504 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
505 // The effective internal format of the source buffer is determined with the following rules
506 // applied in order:
507 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
508 // format then the effective internal format is the source buffer's sized internal format.
509 // * If the source buffer is a texture that was created with an unsized base internal format,
510 // then the effective internal format is the source image array's effective internal
511 // format, as specified by table 3.12, which is determined from the <format> and <type>
512 // that were used when the source image array was specified by TexImage*.
513 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
514 // where Destination Internal Format matches internalformat and where the [source channel
515 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
516 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
517 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
518 const InternalFormat *sourceEffectiveFormat = NULL;
519 if (readBufferHandle != 0)
520 {
521 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
522 // renderbuffer
523 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400524 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400525 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400526 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400527 else
Geoff Lang5d601382014-07-22 15:14:06 -0400528 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400529 // Renderbuffers cannot be created with an unsized internal format, so this must be an
530 // unsized-format texture. We can use the same table we use when creating textures to
531 // get its effective sized format.
532 GLenum sizedInternalFormat =
533 GetSizedInternalFormat(framebufferFormatInfo.format, framebufferFormatInfo.type);
534 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400535 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400536 }
537 else
538 {
539 // The effective internal format must be derived from the source framebuffer's channel
540 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
541 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400542 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400543 GLenum effectiveFormat;
544 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
545 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400546 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400547 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400548 }
549 else
550 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400551 return false;
552 }
553 }
554 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
555 {
556 // SRGB buffers can only be copied to sized format destinations according to table 3.18
557 if (textureFormat.sized &&
558 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
559 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
560 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
561 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
562 {
563 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
564 }
565 else
566 {
567 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400568 }
569 }
570 else
571 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400572 UNREACHABLE();
573 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400574 }
Geoff Lang5d601382014-07-22 15:14:06 -0400575 }
576
Jamie Madill21b786b2016-11-01 17:41:31 -0400577 if (textureFormat.sized)
578 {
579 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
580 // sized, component sizes of the source and destination formats must exactly match if the
581 // destination format exists.
582 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
583 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
584 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
585 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
586 {
587 return false;
588 }
589 }
590
591 return true; // A conversion function exists, and no rule in the specification has precluded
592 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400593}
594
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500595bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
596 GLenum target,
597 GLint level,
598 GLenum internalformat,
599 bool isSubImage,
600 GLint xoffset,
601 GLint yoffset,
602 GLint zoffset,
603 GLint x,
604 GLint y,
605 GLsizei width,
606 GLsizei height,
607 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400608{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400609 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400610 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400611 xoffset, yoffset, zoffset, x, y, width, height, border,
612 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400613 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400614 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400615 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400616 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400617
Jamie Madill51f40ec2016-06-15 14:06:00 -0400618 const auto &state = context->getGLState();
619 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
620 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400621
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700622 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400623 {
Jamie Madill437fa652016-05-03 15:13:24 -0400624 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400625 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400626 }
627
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700628 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400629 {
Jamie Madill437fa652016-05-03 15:13:24 -0400630 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400631 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400632 }
633
Jamie Madill0c8abca2016-07-22 20:21:26 -0400634 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400635
636 if (isSubImage)
637 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400638 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500639 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400640 {
Jamie Madill437fa652016-05-03 15:13:24 -0400641 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400642 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400643 }
644 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400645 else
646 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400647 // Use format/type from the source FBO. (Might not be perfect for all cases?)
648 const auto framebufferFormat = source->getFormat();
649 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
650 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400651 {
Jamie Madill437fa652016-05-03 15:13:24 -0400652 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400653 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400654 }
655 }
656
Geoff Lang784a8fd2013-09-24 12:33:16 -0400657 // If width or height is zero, it is a no-op. Return false without setting an error.
658 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400659}
660
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500661bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
662 GLenum target,
663 GLint level,
664 GLenum internalformat,
665 bool isSubImage,
666 GLint xoffset,
667 GLint yoffset,
668 GLint zoffset,
669 GLint x,
670 GLint y,
671 GLsizei width,
672 GLsizei height,
673 GLint border)
674{
675 if (!ValidTexture2DDestinationTarget(context, target))
676 {
Jamie Madill437fa652016-05-03 15:13:24 -0400677 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500678 return false;
679 }
680
681 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
682 xoffset, yoffset, zoffset, x, y, width, height,
683 border);
684}
685
686bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
687 GLenum target,
688 GLint level,
689 GLenum internalformat,
690 bool isSubImage,
691 GLint xoffset,
692 GLint yoffset,
693 GLint zoffset,
694 GLint x,
695 GLint y,
696 GLsizei width,
697 GLsizei height,
698 GLint border)
699{
700 if (!ValidTexture3DDestinationTarget(context, target))
701 {
Jamie Madill437fa652016-05-03 15:13:24 -0400702 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500703 return false;
704 }
705
706 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
707 xoffset, yoffset, zoffset, x, y, width, height,
708 border);
709}
710
711bool ValidateES3TexStorageParametersBase(Context *context,
712 GLenum target,
713 GLsizei levels,
714 GLenum internalformat,
715 GLsizei width,
716 GLsizei height,
717 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400718{
719 if (width < 1 || height < 1 || depth < 1 || levels < 1)
720 {
Jamie Madill437fa652016-05-03 15:13:24 -0400721 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400722 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 }
724
Geoff Langb92c1332015-09-04 12:54:55 -0400725 GLsizei maxDim = std::max(width, height);
726 if (target != GL_TEXTURE_2D_ARRAY)
727 {
728 maxDim = std::max(maxDim, depth);
729 }
730
731 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400732 {
Jamie Madill437fa652016-05-03 15:13:24 -0400733 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400734 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400735 }
736
Geoff Langaae65a42014-05-26 12:43:44 -0400737 const gl::Caps &caps = context->getCaps();
738
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 switch (target)
740 {
741 case GL_TEXTURE_2D:
742 {
Geoff Langaae65a42014-05-26 12:43:44 -0400743 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
744 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 {
Jamie Madill437fa652016-05-03 15:13:24 -0400746 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400747 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400748 }
749 }
750 break;
751
Geoff Lang01c21d22013-09-24 11:52:16 -0400752 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754 if (width != height)
755 {
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
Geoff Langaae65a42014-05-26 12:43:44 -0400760 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 {
Jamie Madill437fa652016-05-03 15:13:24 -0400762 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400763 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 }
765 }
766 break;
767
768 case GL_TEXTURE_3D:
769 {
Geoff Langaae65a42014-05-26 12:43:44 -0400770 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
771 static_cast<GLuint>(height) > caps.max3DTextureSize ||
772 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400773 {
Jamie Madill437fa652016-05-03 15:13:24 -0400774 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400775 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 }
777 }
778 break;
779
780 case GL_TEXTURE_2D_ARRAY:
781 {
Geoff Langaae65a42014-05-26 12:43:44 -0400782 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
783 static_cast<GLuint>(height) > caps.max2DTextureSize ||
784 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 {
Jamie Madill437fa652016-05-03 15:13:24 -0400786 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400787 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 }
789 }
790 break;
791
792 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500793 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -0400794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796
Geoff Lang691e58c2014-12-19 17:03:25 -0500797 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 if (!texture || texture->id() == 0)
799 {
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 Lang69cce582015-09-17 13:20:36 -0400804 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805 {
Jamie Madill437fa652016-05-03 15:13:24 -0400806 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400807 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808 }
809
Geoff Lang5d601382014-07-22 15:14:06 -0400810 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400811 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
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
Geoff Lang5d601382014-07-22 15:14:06 -0400817 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 {
Jamie Madill437fa652016-05-03 15:13:24 -0400819 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 }
822
823 return true;
824}
825
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500826bool ValidateES3TexStorage2DParameters(Context *context,
827 GLenum target,
828 GLsizei levels,
829 GLenum internalformat,
830 GLsizei width,
831 GLsizei height,
832 GLsizei depth)
833{
834 if (!ValidTexture2DTarget(context, target))
835 {
Jamie Madill437fa652016-05-03 15:13:24 -0400836 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500837 return false;
838 }
839
840 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
841 height, depth);
842}
843
844bool ValidateES3TexStorage3DParameters(Context *context,
845 GLenum target,
846 GLsizei levels,
847 GLenum internalformat,
848 GLsizei width,
849 GLsizei height,
850 GLsizei depth)
851{
852 if (!ValidTexture3DTarget(context, target))
853 {
Jamie Madill437fa652016-05-03 15:13:24 -0400854 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500855 return false;
856 }
857
858 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
859 height, depth);
860}
861
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500862bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
863{
Martin Radev1be913c2016-07-11 17:59:16 +0300864 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500865 {
Jamie Madill437fa652016-05-03 15:13:24 -0400866 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500867 return false;
868 }
869
870 return ValidateBeginQueryBase(context, target, id);
871}
872
873bool ValidateEndQuery(gl::Context *context, GLenum target)
874{
Martin Radev1be913c2016-07-11 17:59:16 +0300875 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500876 {
Jamie Madill437fa652016-05-03 15:13:24 -0400877 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500878 return false;
879 }
880
881 return ValidateEndQueryBase(context, target);
882}
883
884bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
885{
Martin Radev1be913c2016-07-11 17:59:16 +0300886 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500887 {
Jamie Madill437fa652016-05-03 15:13:24 -0400888 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500889 return false;
890 }
891
Geoff Lang2186c382016-10-14 10:54:54 -0400892 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500893}
894
895bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
896{
Martin Radev1be913c2016-07-11 17:59:16 +0300897 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500898 {
Jamie Madill437fa652016-05-03 15:13:24 -0400899 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500900 return false;
901 }
902
Geoff Lang2186c382016-10-14 10:54:54 -0400903 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500904}
905
Geoff Langb1196682014-07-23 13:47:29 -0400906bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -0400907 GLuint texture, GLint level, GLint layer)
908{
Martin Radev1be913c2016-07-11 17:59:16 +0300909 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400910 {
Jamie Madill437fa652016-05-03 15:13:24 -0400911 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400912 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400913 }
914
Jamie Madill55ec3b12014-07-03 10:38:57 -0400915 if (layer < 0)
916 {
Jamie Madill437fa652016-05-03 15:13:24 -0400917 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400918 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400919 }
920
921 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
922 {
923 return false;
924 }
925
926 const gl::Caps &caps = context->getCaps();
927 if (texture != 0)
928 {
929 gl::Texture *tex = context->getTexture(texture);
930 ASSERT(tex);
931
932 switch (tex->getTarget())
933 {
934 case GL_TEXTURE_2D_ARRAY:
935 {
936 if (level > gl::log2(caps.max2DTextureSize))
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 }
941
942 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400945 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400946 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400947 }
948 break;
949
950 case GL_TEXTURE_3D:
951 {
952 if (level > gl::log2(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 }
957
958 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
959 {
Jamie Madill437fa652016-05-03 15:13:24 -0400960 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400961 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400962 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400963 }
964 break;
965
966 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400967 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400968 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400969 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500970
Jamie Madilla3944d42016-07-22 22:13:26 -0400971 const auto &format = tex->getFormat(tex->getTarget(), level);
972 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500973 {
Jamie Madill437fa652016-05-03 15:13:24 -0400974 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500975 return false;
976 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400977 }
978
979 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -0400980}
981
Corentin Walleze0902642014-11-04 12:32:15 -0800982bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
983 GLenum internalformat, GLsizei width, GLsizei height)
984{
985 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
986 {
987 return false;
988 }
989
990 //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.
991 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
992 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
993 {
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -0800995 return false;
996 }
997
998 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
999 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1000 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1001 {
Jamie Madill437fa652016-05-03 15:13:24 -04001002 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001003 Error(GL_INVALID_OPERATION,
1004 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001005 return false;
1006 }
1007
1008 return true;
1009}
1010
Austin Kinross08332632015-05-05 13:35:47 -07001011bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1012 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013{
Martin Radev1be913c2016-07-11 17:59:16 +03001014 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001015 {
Jamie Madill437fa652016-05-03 15:13:24 -04001016 context->handleError(
1017 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001018 return false;
1019 }
1020
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 bool defaultFramebuffer = false;
1022
1023 switch (target)
1024 {
1025 case GL_DRAW_FRAMEBUFFER:
1026 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001027 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1028 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001030 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1031 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001033 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001034 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 }
1036
Austin Kinross08332632015-05-05 13:35:47 -07001037 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038}
1039
Jamie Madillc29968b2016-01-20 11:17:23 -05001040bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001041{
Martin Radev1be913c2016-07-11 17:59:16 +03001042 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001043 {
Jamie Madill437fa652016-05-03 15:13:24 -04001044 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001045 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001046 }
1047
Jamie Madill51f40ec2016-06-15 14:06:00 -04001048 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1049 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001052 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001053 }
1054
1055 return true;
1056}
1057
Olli Etuaho71dfb362016-03-10 14:04:27 +02001058bool ValidateDrawRangeElements(Context *context,
1059 GLenum mode,
1060 GLuint start,
1061 GLuint end,
1062 GLsizei count,
1063 GLenum type,
1064 const GLvoid *indices,
1065 IndexRange *indexRange)
1066{
Martin Radev1be913c2016-07-11 17:59:16 +03001067 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001068 {
Jamie Madill437fa652016-05-03 15:13:24 -04001069 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001070 return false;
1071 }
1072
1073 if (end < start)
1074 {
Jamie Madill437fa652016-05-03 15:13:24 -04001075 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001076 return false;
1077 }
1078
1079 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1080 {
1081 return false;
1082 }
1083
1084 if (indexRange->end > end || indexRange->start < start)
1085 {
1086 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001087 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001088 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1089 return false;
1090 }
1091 return true;
1092}
1093
Geoff Langb1196682014-07-23 13:47:29 -04001094bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001095{
Martin Radev1be913c2016-07-11 17:59:16 +03001096 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001097 {
Jamie Madill437fa652016-05-03 15:13:24 -04001098 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001099 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001100 }
1101
Jamie Madill78f41802014-08-25 15:47:55 -04001102 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001103}
1104
Jamie Madillb885e572015-02-03 16:16:04 -05001105bool ValidateReadBuffer(Context *context, GLenum src)
1106{
Martin Radev1be913c2016-07-11 17:59:16 +03001107 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001108 {
Jamie Madill437fa652016-05-03 15:13:24 -04001109 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001110 return false;
1111 }
1112
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001113 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001114
1115 if (readFBO == nullptr)
1116 {
Jamie Madill437fa652016-05-03 15:13:24 -04001117 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001118 return false;
1119 }
1120
1121 if (src == GL_NONE)
1122 {
1123 return true;
1124 }
1125
Olli Etuaho84c9f592016-03-09 14:37:25 +02001126 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001127 {
Jamie Madill437fa652016-05-03 15:13:24 -04001128 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001129 return false;
1130 }
1131
1132 if (readFBO->id() == 0)
1133 {
1134 if (src != GL_BACK)
1135 {
1136 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001137 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001138 return false;
1139 }
1140 }
1141 else
1142 {
1143 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1144
1145 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1146 {
1147 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001148 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001149 return false;
1150 }
1151 }
1152
1153 return true;
1154}
1155
Jamie Madill86af3d22015-07-21 15:14:07 -04001156bool ValidateCompressedTexImage3D(Context *context,
1157 GLenum target,
1158 GLint level,
1159 GLenum internalformat,
1160 GLsizei width,
1161 GLsizei height,
1162 GLsizei depth,
1163 GLint border,
1164 GLsizei imageSize,
1165 const GLvoid *data)
1166{
Martin Radev1be913c2016-07-11 17:59:16 +03001167 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001168 {
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001170 return false;
1171 }
1172
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001173 if (!ValidTextureTarget(context, target))
1174 {
1175 context->handleError(Error(GL_INVALID_ENUM));
1176 return false;
1177 }
1178
Jamie Madille2e406c2016-06-02 13:04:10 -04001179 // Validate image size
1180 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1181 {
1182 context->handleError(Error(GL_INVALID_VALUE));
1183 return false;
1184 }
1185
Jamie Madill86af3d22015-07-21 15:14:07 -04001186 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001187 if (!formatInfo.compressed)
1188 {
1189 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1190 return false;
1191 }
1192
Jamie Madill513558d2016-06-02 13:04:11 -04001193 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001194 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001195 if (blockSizeOrErr.isError())
1196 {
Jamie Madill513558d2016-06-02 13:04:11 -04001197 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001198 return false;
1199 }
1200 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001201 {
Jamie Madill437fa652016-05-03 15:13:24 -04001202 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001203 return false;
1204 }
1205
1206 // 3D texture target validation
1207 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001210 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1211 return false;
1212 }
1213
1214 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001215 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001216 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1217 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001218 {
1219 return false;
1220 }
1221
1222 return true;
1223}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001224
1225bool ValidateBindVertexArray(Context *context, GLuint array)
1226{
Martin Radev1be913c2016-07-11 17:59:16 +03001227 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001228 {
Jamie Madill437fa652016-05-03 15:13:24 -04001229 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001230 return false;
1231 }
1232
1233 return ValidateBindVertexArrayBase(context, array);
1234}
1235
Austin Kinrossbc781f32015-10-26 09:27:38 -07001236bool ValidateIsVertexArray(Context *context)
1237{
Martin Radev1be913c2016-07-11 17:59:16 +03001238 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001239 {
Jamie Madill437fa652016-05-03 15:13:24 -04001240 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001241 return false;
1242 }
1243
1244 return true;
1245}
Geoff Langc5629752015-12-07 16:29:04 -05001246
1247bool ValidateProgramBinary(Context *context,
1248 GLuint program,
1249 GLenum binaryFormat,
1250 const void *binary,
1251 GLint length)
1252{
Martin Radev1be913c2016-07-11 17:59:16 +03001253 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001254 {
Jamie Madill437fa652016-05-03 15:13:24 -04001255 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001256 return false;
1257 }
1258
1259 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1260}
1261
1262bool ValidateGetProgramBinary(Context *context,
1263 GLuint program,
1264 GLsizei bufSize,
1265 GLsizei *length,
1266 GLenum *binaryFormat,
1267 void *binary)
1268{
Martin Radev1be913c2016-07-11 17:59:16 +03001269 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001270 {
Jamie Madill437fa652016-05-03 15:13:24 -04001271 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001272 return false;
1273 }
1274
1275 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1276}
1277
Olli Etuahof0fee072016-03-30 15:11:58 +03001278bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001279{
Martin Radev1be913c2016-07-11 17:59:16 +03001280 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001281 {
Jamie Madill437fa652016-05-03 15:13:24 -04001282 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001283 return false;
1284 }
1285
1286 if (GetValidProgram(context, program) == nullptr)
1287 {
1288 return false;
1289 }
1290
1291 switch (pname)
1292 {
1293 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001294 if (value != GL_FALSE && value != GL_TRUE)
1295 {
Jamie Madill437fa652016-05-03 15:13:24 -04001296 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001297 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1298 return false;
1299 }
Geoff Langc5629752015-12-07 16:29:04 -05001300 break;
1301
1302 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001303 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001304 return false;
1305 }
1306
1307 return true;
1308}
Jamie Madillc29968b2016-01-20 11:17:23 -05001309
1310bool ValidateBlitFramebuffer(Context *context,
1311 GLint srcX0,
1312 GLint srcY0,
1313 GLint srcX1,
1314 GLint srcY1,
1315 GLint dstX0,
1316 GLint dstY0,
1317 GLint dstX1,
1318 GLint dstY1,
1319 GLbitfield mask,
1320 GLenum filter)
1321{
Martin Radev1be913c2016-07-11 17:59:16 +03001322 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001323 {
Jamie Madill437fa652016-05-03 15:13:24 -04001324 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001325 return false;
1326 }
1327
1328 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1329 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330}
Jamie Madillc29968b2016-01-20 11:17:23 -05001331
1332bool ValidateClearBufferiv(ValidationContext *context,
1333 GLenum buffer,
1334 GLint drawbuffer,
1335 const GLint *value)
1336{
1337 switch (buffer)
1338 {
1339 case GL_COLOR:
1340 if (drawbuffer < 0 ||
1341 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1342 {
Jamie Madill437fa652016-05-03 15:13:24 -04001343 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001344 return false;
1345 }
1346 break;
1347
1348 case GL_STENCIL:
1349 if (drawbuffer != 0)
1350 {
Jamie Madill437fa652016-05-03 15:13:24 -04001351 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001352 return false;
1353 }
1354 break;
1355
1356 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001357 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001358 return false;
1359 }
1360
1361 return ValidateClearBuffer(context);
1362}
1363
1364bool ValidateClearBufferuiv(ValidationContext *context,
1365 GLenum buffer,
1366 GLint drawbuffer,
1367 const GLuint *value)
1368{
1369 switch (buffer)
1370 {
1371 case GL_COLOR:
1372 if (drawbuffer < 0 ||
1373 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1374 {
Jamie Madill437fa652016-05-03 15:13:24 -04001375 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001376 return false;
1377 }
1378 break;
1379
1380 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001382 return false;
1383 }
1384
1385 return ValidateClearBuffer(context);
1386}
1387
1388bool ValidateClearBufferfv(ValidationContext *context,
1389 GLenum buffer,
1390 GLint drawbuffer,
1391 const GLfloat *value)
1392{
1393 switch (buffer)
1394 {
1395 case GL_COLOR:
1396 if (drawbuffer < 0 ||
1397 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001400 return false;
1401 }
1402 break;
1403
1404 case GL_DEPTH:
1405 if (drawbuffer != 0)
1406 {
Jamie Madill437fa652016-05-03 15:13:24 -04001407 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001408 return false;
1409 }
1410 break;
1411
1412 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001414 return false;
1415 }
1416
1417 return ValidateClearBuffer(context);
1418}
1419
1420bool ValidateClearBufferfi(ValidationContext *context,
1421 GLenum buffer,
1422 GLint drawbuffer,
1423 GLfloat depth,
1424 GLint stencil)
1425{
1426 switch (buffer)
1427 {
1428 case GL_DEPTH_STENCIL:
1429 if (drawbuffer != 0)
1430 {
Jamie Madill437fa652016-05-03 15:13:24 -04001431 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001432 return false;
1433 }
1434 break;
1435
1436 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001437 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001438 return false;
1439 }
1440
1441 return ValidateClearBuffer(context);
1442}
1443
1444bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1445{
Martin Radev1be913c2016-07-11 17:59:16 +03001446 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001449 return false;
1450 }
1451
1452 return ValidateDrawBuffersBase(context, n, bufs);
1453}
1454
1455bool ValidateCopyTexSubImage3D(Context *context,
1456 GLenum target,
1457 GLint level,
1458 GLint xoffset,
1459 GLint yoffset,
1460 GLint zoffset,
1461 GLint x,
1462 GLint y,
1463 GLsizei width,
1464 GLsizei height)
1465{
Martin Radev1be913c2016-07-11 17:59:16 +03001466 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001467 {
Jamie Madill437fa652016-05-03 15:13:24 -04001468 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001469 return false;
1470 }
1471
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001472 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1473 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001474}
1475
Jamie Madill73a84962016-02-12 09:27:23 -05001476bool ValidateTexImage3D(Context *context,
1477 GLenum target,
1478 GLint level,
1479 GLint internalformat,
1480 GLsizei width,
1481 GLsizei height,
1482 GLsizei depth,
1483 GLint border,
1484 GLenum format,
1485 GLenum type,
1486 const GLvoid *pixels)
1487{
Martin Radev1be913c2016-07-11 17:59:16 +03001488 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001489 {
Jamie Madill437fa652016-05-03 15:13:24 -04001490 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001491 return false;
1492 }
1493
1494 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001495 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001496 pixels);
1497}
1498
Geoff Langc52f6f12016-10-14 10:18:00 -04001499bool ValidateTexImage3DRobustANGLE(Context *context,
1500 GLenum target,
1501 GLint level,
1502 GLint internalformat,
1503 GLsizei width,
1504 GLsizei height,
1505 GLsizei depth,
1506 GLint border,
1507 GLenum format,
1508 GLenum type,
1509 GLsizei bufSize,
1510 const GLvoid *pixels)
1511{
1512 if (context->getClientMajorVersion() < 3)
1513 {
1514 context->handleError(Error(GL_INVALID_OPERATION));
1515 return false;
1516 }
1517
1518 if (!ValidateRobustEntryPoint(context, bufSize))
1519 {
1520 return false;
1521 }
1522
1523 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1524 0, 0, width, height, depth, border, format, type,
1525 bufSize, pixels);
1526}
1527
Jamie Madill73a84962016-02-12 09:27:23 -05001528bool ValidateTexSubImage3D(Context *context,
1529 GLenum target,
1530 GLint level,
1531 GLint xoffset,
1532 GLint yoffset,
1533 GLint zoffset,
1534 GLsizei width,
1535 GLsizei height,
1536 GLsizei depth,
1537 GLenum format,
1538 GLenum type,
1539 const GLvoid *pixels)
1540{
Martin Radev1be913c2016-07-11 17:59:16 +03001541 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001542 {
Jamie Madill437fa652016-05-03 15:13:24 -04001543 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001544 return false;
1545 }
1546
1547 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1548 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001549 -1, pixels);
1550}
1551
1552bool ValidateTexSubImage3DRobustANGLE(Context *context,
1553 GLenum target,
1554 GLint level,
1555 GLint xoffset,
1556 GLint yoffset,
1557 GLint zoffset,
1558 GLsizei width,
1559 GLsizei height,
1560 GLsizei depth,
1561 GLenum format,
1562 GLenum type,
1563 GLsizei bufSize,
1564 const GLvoid *pixels)
1565{
1566 if (context->getClientMajorVersion() < 3)
1567 {
1568 context->handleError(Error(GL_INVALID_OPERATION));
1569 return false;
1570 }
1571
1572 if (!ValidateRobustEntryPoint(context, bufSize))
1573 {
1574 return false;
1575 }
1576
1577 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1578 yoffset, zoffset, width, height, depth, 0, format, type,
1579 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001580}
1581
1582bool ValidateCompressedTexSubImage3D(Context *context,
1583 GLenum target,
1584 GLint level,
1585 GLint xoffset,
1586 GLint yoffset,
1587 GLint zoffset,
1588 GLsizei width,
1589 GLsizei height,
1590 GLsizei depth,
1591 GLenum format,
1592 GLsizei imageSize,
1593 const GLvoid *data)
1594{
Martin Radev1be913c2016-07-11 17:59:16 +03001595 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001596 {
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001598 return false;
1599 }
1600
1601 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001602 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001603 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001604 if (blockSizeOrErr.isError())
1605 {
1606 context->handleError(blockSizeOrErr.getError());
1607 return false;
1608 }
1609 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001610 {
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 if (!data)
1616 {
Jamie Madill437fa652016-05-03 15:13:24 -04001617 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001618 return false;
1619 }
1620
1621 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001622 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001623}
1624
Olli Etuaho41997e72016-03-10 13:38:39 +02001625bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1626{
1627 return ValidateGenOrDeleteES3(context, n);
1628}
1629
1630bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1631{
1632 return ValidateGenOrDeleteES3(context, n);
1633}
1634
1635bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1636{
1637 return ValidateGenOrDeleteCountES3(context, count);
1638}
1639
1640bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1641{
1642 return ValidateGenOrDeleteCountES3(context, count);
1643}
1644
1645bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1646{
1647 return ValidateGenOrDeleteES3(context, n);
1648}
1649
1650bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1651{
1652 if (!ValidateGenOrDeleteES3(context, n))
1653 {
1654 return false;
1655 }
1656 for (GLint i = 0; i < n; ++i)
1657 {
1658 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1659 if (transformFeedback != nullptr && transformFeedback->isActive())
1660 {
1661 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001663 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1664 return false;
1665 }
1666 }
1667 return true;
1668}
1669
1670bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1671{
1672 return ValidateGenOrDeleteES3(context, n);
1673}
1674
1675bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1676{
1677 return ValidateGenOrDeleteES3(context, n);
1678}
1679
1680bool ValidateGenOrDeleteES3(Context *context, GLint n)
1681{
Martin Radev1be913c2016-07-11 17:59:16 +03001682 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001683 {
Jamie Madill437fa652016-05-03 15:13:24 -04001684 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001685 return false;
1686 }
1687 return ValidateGenOrDelete(context, n);
1688}
1689
1690bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1691{
Martin Radev1be913c2016-07-11 17:59:16 +03001692 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001693 {
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001695 return false;
1696 }
1697 if (count < 0)
1698 {
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001700 return false;
1701 }
1702 return true;
1703}
1704
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001705bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1706{
Martin Radev1be913c2016-07-11 17:59:16 +03001707 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001708 {
Jamie Madill437fa652016-05-03 15:13:24 -04001709 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001710 return false;
1711 }
1712 switch (primitiveMode)
1713 {
1714 case GL_TRIANGLES:
1715 case GL_LINES:
1716 case GL_POINTS:
1717 break;
1718
1719 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001720 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001721 return false;
1722 }
1723
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001724 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001725 ASSERT(transformFeedback != nullptr);
1726
1727 if (transformFeedback->isActive())
1728 {
Jamie Madill437fa652016-05-03 15:13:24 -04001729 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001730 return false;
1731 }
1732 return true;
1733}
1734
Olli Etuaho4f667482016-03-30 15:56:35 +03001735bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1736{
Geoff Lang496c02d2016-10-20 11:38:11 -07001737 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1738}
1739
1740bool ValidateGetBufferPointervRobustANGLE(Context *context,
1741 GLenum target,
1742 GLenum pname,
1743 GLsizei bufSize,
1744 GLsizei *length,
1745 GLvoid **params)
1746{
1747 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001748 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001749 return false;
1750 }
1751
Geoff Lang496c02d2016-10-20 11:38:11 -07001752 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1753 {
1754 return false;
1755 }
1756
1757 if (!ValidateRobustBufferSize(context, bufSize, *length))
1758 {
1759 return false;
1760 }
1761
1762 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001763}
1764
1765bool ValidateUnmapBuffer(Context *context, GLenum target)
1766{
Martin Radev1be913c2016-07-11 17:59:16 +03001767 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001768 {
Jamie Madill437fa652016-05-03 15:13:24 -04001769 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001770 return false;
1771 }
1772
1773 return ValidateUnmapBufferBase(context, target);
1774}
1775
1776bool ValidateMapBufferRange(Context *context,
1777 GLenum target,
1778 GLintptr offset,
1779 GLsizeiptr length,
1780 GLbitfield access)
1781{
Martin Radev1be913c2016-07-11 17:59:16 +03001782 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001783 {
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001785 return false;
1786 }
1787
1788 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1789}
1790
1791bool ValidateFlushMappedBufferRange(Context *context,
1792 GLenum target,
1793 GLintptr offset,
1794 GLsizeiptr length)
1795{
Martin Radev1be913c2016-07-11 17:59:16 +03001796 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001799 return false;
1800 }
1801
1802 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1803}
1804
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001805bool ValidateIndexedStateQuery(ValidationContext *context,
1806 GLenum pname,
1807 GLuint index,
1808 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001809{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001810 if (length)
1811 {
1812 *length = 0;
1813 }
1814
Martin Radev66fb8202016-07-28 11:45:20 +03001815 GLenum nativeType;
1816 unsigned int numParams;
1817 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1818 {
1819 context->handleError(Error(GL_INVALID_ENUM));
1820 return false;
1821 }
1822
1823 const Caps &caps = context->getCaps();
1824 switch (pname)
1825 {
1826 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1827 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1828 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1829 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1830 {
1831 context->handleError(Error(GL_INVALID_VALUE));
1832 return false;
1833 }
1834 break;
1835
1836 case GL_UNIFORM_BUFFER_START:
1837 case GL_UNIFORM_BUFFER_SIZE:
1838 case GL_UNIFORM_BUFFER_BINDING:
1839 if (index >= caps.maxUniformBufferBindings)
1840 {
1841 context->handleError(Error(GL_INVALID_VALUE));
1842 return false;
1843 }
1844 break;
1845 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1846 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1847 if (index >= 3u)
1848 {
1849 context->handleError(Error(GL_INVALID_VALUE));
1850 return false;
1851 }
1852 break;
1853 default:
1854 context->handleError(Error(GL_INVALID_ENUM));
1855 return false;
1856 }
1857
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001858 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001859 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001860 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001861 }
1862
1863 return true;
1864}
1865
1866bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1867{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001868 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001869 {
1870 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1871 return false;
1872 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001873 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001874}
1875
Geoff Langcf255ea2016-10-20 11:39:09 -07001876bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
1877 GLenum target,
1878 GLuint index,
1879 GLsizei bufSize,
1880 GLsizei *length,
1881 GLint *data)
1882{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001883 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07001884 {
1885 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1886 return false;
1887 }
1888
1889 if (!ValidateRobustEntryPoint(context, bufSize))
1890 {
1891 return false;
1892 }
1893
1894 if (!ValidateIndexedStateQuery(context, target, index, length))
1895 {
1896 return false;
1897 }
1898
1899 if (!ValidateRobustBufferSize(context, bufSize, *length))
1900 {
1901 return false;
1902 }
1903
1904 return true;
1905}
1906
Martin Radev66fb8202016-07-28 11:45:20 +03001907bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1908{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001909 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001910 {
1911 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1912 return false;
1913 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001914 return ValidateIndexedStateQuery(context, target, index, nullptr);
1915}
1916
1917bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1918 GLenum target,
1919 GLuint index,
1920 GLsizei bufSize,
1921 GLsizei *length,
1922 GLint64 *data)
1923{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001924 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001925 {
1926 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1927 return false;
1928 }
1929
1930 if (!ValidateRobustEntryPoint(context, bufSize))
1931 {
1932 return false;
1933 }
1934
1935 if (!ValidateIndexedStateQuery(context, target, index, length))
1936 {
1937 return false;
1938 }
1939
1940 if (!ValidateRobustBufferSize(context, bufSize, *length))
1941 {
1942 return false;
1943 }
1944
1945 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001946}
1947
Jamie Madillb0817d12016-11-01 15:48:31 -04001948bool ValidateCopyBufferSubData(ValidationContext *context,
1949 GLenum readTarget,
1950 GLenum writeTarget,
1951 GLintptr readOffset,
1952 GLintptr writeOffset,
1953 GLsizeiptr size)
1954{
1955 if (context->getClientMajorVersion() < 3)
1956 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001957 context->handleError(
1958 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001959 return false;
1960 }
1961
1962 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
1963 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001964 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001965 return false;
1966 }
1967
1968 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
1969 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
1970
1971 if (!readBuffer || !writeBuffer)
1972 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001973 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001974 return false;
1975 }
1976
1977 // Verify that readBuffer and writeBuffer are not currently mapped
1978 if (readBuffer->isMapped() || writeBuffer->isMapped())
1979 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001980 context->handleError(
1981 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001982 return false;
1983 }
1984
Jamie Madilld2f0c742016-11-02 10:34:41 -04001985 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
1986 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
1987 CheckedNumeric<GLintptr> checkedSize(size);
1988
1989 auto checkedReadSum = checkedReadOffset + checkedSize;
1990 auto checkedWriteSum = checkedWriteOffset + checkedSize;
1991
1992 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
1993 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
1994 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04001995 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001996 context->handleError(
1997 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04001998 return false;
1999 }
2000
Jamie Madilld2f0c742016-11-02 10:34:41 -04002001 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002002 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002003 context->handleError(
2004 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002005 return false;
2006 }
2007
Jamie Madilld2f0c742016-11-02 10:34:41 -04002008 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2009 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2010 {
2011 context->handleError(
2012 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2013 return false;
2014 }
2015
2016 if (readBuffer == writeBuffer)
2017 {
2018 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2019 if (!checkedOffsetDiff.IsValid())
2020 {
2021 // This shold not be possible.
2022 UNREACHABLE();
2023 context->handleError(
2024 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2025 return false;
2026 }
2027
2028 if (checkedOffsetDiff.ValueOrDie() < size)
2029 {
2030 context->handleError(Error(GL_INVALID_VALUE));
2031 return false;
2032 }
2033 }
2034
Jamie Madillb0817d12016-11-01 15:48:31 -04002035 return true;
2036}
2037
Jamie Madillc29968b2016-01-20 11:17:23 -05002038} // namespace gl