blob: b090a26d9f1007a098872d49608eada4be2b8cf5 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
Geoff Lang5d601382014-07-22 15:14:06 -040027static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
28{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050029 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
30 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
31 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
32 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -040033 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
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
452struct CopyConversion
453{
454 GLenum mTextureFormat;
455 GLenum mFramebufferFormat;
456
457 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
458 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
459
460 bool operator<(const CopyConversion& other) const
461 {
462 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
463 }
464};
465
466typedef std::set<CopyConversion> CopyConversionSet;
467
468static CopyConversionSet BuildValidES3CopyTexImageCombinations()
469{
470 CopyConversionSet set;
471
472 // From ES 3.0.1 spec, table 3.15
473 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
474 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
475 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
476 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
477 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
478 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
479 set.insert(CopyConversion(GL_RED, GL_RED));
480 set.insert(CopyConversion(GL_RED, GL_RG));
481 set.insert(CopyConversion(GL_RED, GL_RGB));
482 set.insert(CopyConversion(GL_RED, GL_RGBA));
483 set.insert(CopyConversion(GL_RG, GL_RG));
484 set.insert(CopyConversion(GL_RG, GL_RGB));
485 set.insert(CopyConversion(GL_RG, GL_RGBA));
486 set.insert(CopyConversion(GL_RGB, GL_RGB));
487 set.insert(CopyConversion(GL_RGB, GL_RGBA));
488 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
489
490 // Necessary for ANGLE back-buffers
491 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
492 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
493 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
494 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
495 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
496 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
497 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400498 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400499
500 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
501 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
502 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
503 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
504 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
505 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
506 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
507 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
508 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
509 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
510
511 return set;
512}
513
Corentin Wallez76287682016-04-25 09:23:38 -0400514static bool EqualOrFirstZero(GLuint first, GLuint second)
515{
516 return first == 0 || first == second;
517}
518
Jamie Madill0c8abca2016-07-22 20:21:26 -0400519static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
520 const Format &framebufferFormat,
521 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400522{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400523 const auto &textureFormatInfo = *textureFormat.info;
524 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400525
526 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400527 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
528 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400529 {
530 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
531 // must both be signed, unsigned, or fixed point and both source and destinations
532 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
533 // conversion between fixed and floating point.
534
Jamie Madill0c8abca2016-07-22 20:21:26 -0400535 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
536 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400537 {
538 return false;
539 }
540
Jamie Madill0c8abca2016-07-22 20:21:26 -0400541 if (((textureFormatInfo.componentType == GL_INT) !=
542 (framebufferFormatInfo.componentType == GL_INT)) ||
543 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
544 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
Geoff Lang5d601382014-07-22 15:14:06 -0400545 {
546 return false;
547 }
548
Jamie Madill0c8abca2016-07-22 20:21:26 -0400549 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
550 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
551 textureFormatInfo.componentType == GL_FLOAT) &&
552 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
553 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
554 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400555 {
556 return false;
557 }
558
559 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
560 // The effective internal format of the source buffer is determined with the following rules applied in order:
561 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
562 // effective internal format is the source buffer's sized internal format.
563 // * If the source buffer is a texture that was created with an unsized base internal format, then the
564 // effective internal format is the source image array's effective internal format, as specified by table
565 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
566 // specified by TexImage*.
567 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
568 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
569 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
570 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
571 // is SRGB.
572 const InternalFormat *sourceEffectiveFormat = NULL;
573 if (readBufferHandle != 0)
574 {
575 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400576 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400577 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400578 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400579 }
580 else
581 {
582 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
583 // texture. We can use the same table we use when creating textures to get its effective sized format.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400584 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
585 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500586 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400587 }
588 }
589 else
590 {
591 // The effective internal format must be derived from the source framebuffer's channel sizes.
592 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400593 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400594 {
595 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400596 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
597 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400598 {
599 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
600 }
601 else
602 {
603 return false;
604 }
605 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400606 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400607 {
608 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400609 if (textureFormat.sized &&
610 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
611 (framebufferFormatInfo.greenBits >= 1 &&
612 framebufferFormatInfo.greenBits <= 8) &&
613 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
614 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400615 {
616 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
617 }
618 else
619 {
620 return false;
621 }
622 }
623 else
624 {
625 UNREACHABLE();
626 return false;
627 }
628 }
629
Jamie Madill0c8abca2016-07-22 20:21:26 -0400630 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400631 {
Corentin Wallez76287682016-04-25 09:23:38 -0400632 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
633 // format is sized, component sizes of the source and destination formats must exactly
634 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400635 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
636 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
637 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
638 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400639 {
640 return false;
641 }
642 }
643
Geoff Lang5d601382014-07-22 15:14:06 -0400644 return true; // A conversion function exists, and no rule in the specification has precluded conversion
645 // between these formats.
646 }
647
648 return false;
649}
650
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500651bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
652 GLenum target,
653 GLint level,
654 GLenum internalformat,
655 bool isSubImage,
656 GLint xoffset,
657 GLint yoffset,
658 GLint zoffset,
659 GLint x,
660 GLint y,
661 GLsizei width,
662 GLsizei height,
663 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400665 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400666 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400667 xoffset, yoffset, zoffset, x, y, width, height, border,
668 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400669 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400670 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400671 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400672 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400673
Jamie Madill51f40ec2016-06-15 14:06:00 -0400674 const auto &state = context->getGLState();
675 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
676 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400677
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700678 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400679 {
Jamie Madill437fa652016-05-03 15:13:24 -0400680 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400681 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400682 }
683
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700684 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400685 {
Jamie Madill437fa652016-05-03 15:13:24 -0400686 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400687 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400688 }
689
Jamie Madill0c8abca2016-07-22 20:21:26 -0400690 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400691
692 if (isSubImage)
693 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400694 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500695 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696 {
Jamie Madill437fa652016-05-03 15:13:24 -0400697 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400698 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400699 }
700 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400701 else
702 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400703 // Use format/type from the source FBO. (Might not be perfect for all cases?)
704 const auto framebufferFormat = source->getFormat();
705 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
706 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400707 {
Jamie Madill437fa652016-05-03 15:13:24 -0400708 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400709 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400710 }
711 }
712
Geoff Lang784a8fd2013-09-24 12:33:16 -0400713 // If width or height is zero, it is a no-op. Return false without setting an error.
714 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400715}
716
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500717bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
718 GLenum target,
719 GLint level,
720 GLenum internalformat,
721 bool isSubImage,
722 GLint xoffset,
723 GLint yoffset,
724 GLint zoffset,
725 GLint x,
726 GLint y,
727 GLsizei width,
728 GLsizei height,
729 GLint border)
730{
731 if (!ValidTexture2DDestinationTarget(context, target))
732 {
Jamie Madill437fa652016-05-03 15:13:24 -0400733 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500734 return false;
735 }
736
737 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
738 xoffset, yoffset, zoffset, x, y, width, height,
739 border);
740}
741
742bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
743 GLenum target,
744 GLint level,
745 GLenum internalformat,
746 bool isSubImage,
747 GLint xoffset,
748 GLint yoffset,
749 GLint zoffset,
750 GLint x,
751 GLint y,
752 GLsizei width,
753 GLsizei height,
754 GLint border)
755{
756 if (!ValidTexture3DDestinationTarget(context, target))
757 {
Jamie Madill437fa652016-05-03 15:13:24 -0400758 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500759 return false;
760 }
761
762 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
763 xoffset, yoffset, zoffset, x, y, width, height,
764 border);
765}
766
767bool ValidateES3TexStorageParametersBase(Context *context,
768 GLenum target,
769 GLsizei levels,
770 GLenum internalformat,
771 GLsizei width,
772 GLsizei height,
773 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400774{
775 if (width < 1 || height < 1 || depth < 1 || levels < 1)
776 {
Jamie Madill437fa652016-05-03 15:13:24 -0400777 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400778 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 }
780
Geoff Langb92c1332015-09-04 12:54:55 -0400781 GLsizei maxDim = std::max(width, height);
782 if (target != GL_TEXTURE_2D_ARRAY)
783 {
784 maxDim = std::max(maxDim, depth);
785 }
786
787 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 {
Jamie Madill437fa652016-05-03 15:13:24 -0400789 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 }
792
Geoff Langaae65a42014-05-26 12:43:44 -0400793 const gl::Caps &caps = context->getCaps();
794
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 switch (target)
796 {
797 case GL_TEXTURE_2D:
798 {
Geoff Langaae65a42014-05-26 12:43:44 -0400799 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
800 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 {
Jamie Madill437fa652016-05-03 15:13:24 -0400802 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400803 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 }
805 }
806 break;
807
Geoff Lang01c21d22013-09-24 11:52:16 -0400808 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400810 if (width != height)
811 {
Jamie Madill437fa652016-05-03 15:13:24 -0400812 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 }
815
Geoff Langaae65a42014-05-26 12:43:44 -0400816 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400817 {
Jamie Madill437fa652016-05-03 15:13:24 -0400818 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400819 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820 }
821 }
822 break;
823
824 case GL_TEXTURE_3D:
825 {
Geoff Langaae65a42014-05-26 12:43:44 -0400826 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
827 static_cast<GLuint>(height) > caps.max3DTextureSize ||
828 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 {
Jamie Madill437fa652016-05-03 15:13:24 -0400830 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400831 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 }
833 }
834 break;
835
836 case GL_TEXTURE_2D_ARRAY:
837 {
Geoff Langaae65a42014-05-26 12:43:44 -0400838 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
839 static_cast<GLuint>(height) > caps.max2DTextureSize ||
840 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 {
Jamie Madill437fa652016-05-03 15:13:24 -0400842 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
845 }
846 break;
847
848 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500849 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -0400850 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400851 }
852
Geoff Lang691e58c2014-12-19 17:03:25 -0500853 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 if (!texture || texture->id() == 0)
855 {
Jamie Madill437fa652016-05-03 15:13:24 -0400856 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859
Geoff Lang69cce582015-09-17 13:20:36 -0400860 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 {
Jamie Madill437fa652016-05-03 15:13:24 -0400862 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400863 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400864 }
865
Geoff Lang5d601382014-07-22 15:14:06 -0400866 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400867 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868 {
Jamie Madill437fa652016-05-03 15:13:24 -0400869 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400870 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 }
872
Geoff Lang5d601382014-07-22 15:14:06 -0400873 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 {
Jamie Madill437fa652016-05-03 15:13:24 -0400875 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400876 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 }
878
879 return true;
880}
881
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500882bool ValidateES3TexStorage2DParameters(Context *context,
883 GLenum target,
884 GLsizei levels,
885 GLenum internalformat,
886 GLsizei width,
887 GLsizei height,
888 GLsizei depth)
889{
890 if (!ValidTexture2DTarget(context, target))
891 {
Jamie Madill437fa652016-05-03 15:13:24 -0400892 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500893 return false;
894 }
895
896 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
897 height, depth);
898}
899
900bool ValidateES3TexStorage3DParameters(Context *context,
901 GLenum target,
902 GLsizei levels,
903 GLenum internalformat,
904 GLsizei width,
905 GLsizei height,
906 GLsizei depth)
907{
908 if (!ValidTexture3DTarget(context, target))
909 {
Jamie Madill437fa652016-05-03 15:13:24 -0400910 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500911 return false;
912 }
913
914 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
915 height, depth);
916}
917
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500918bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
919{
Martin Radev1be913c2016-07-11 17:59:16 +0300920 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500923 return false;
924 }
925
926 return ValidateBeginQueryBase(context, target, id);
927}
928
929bool ValidateEndQuery(gl::Context *context, GLenum target)
930{
Martin Radev1be913c2016-07-11 17:59:16 +0300931 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500932 {
Jamie Madill437fa652016-05-03 15:13:24 -0400933 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500934 return false;
935 }
936
937 return ValidateEndQueryBase(context, target);
938}
939
940bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
941{
Martin Radev1be913c2016-07-11 17:59:16 +0300942 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500945 return false;
946 }
947
Geoff Lang2186c382016-10-14 10:54:54 -0400948 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500949}
950
951bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
952{
Martin Radev1be913c2016-07-11 17:59:16 +0300953 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500954 {
Jamie Madill437fa652016-05-03 15:13:24 -0400955 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500956 return false;
957 }
958
Geoff Lang2186c382016-10-14 10:54:54 -0400959 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500960}
961
Geoff Langb1196682014-07-23 13:47:29 -0400962bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -0400963 GLuint texture, GLint level, GLint layer)
964{
Martin Radev1be913c2016-07-11 17:59:16 +0300965 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400966 {
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 Madill570f7c82014-07-03 10:38:54 -0400969 }
970
Jamie Madill55ec3b12014-07-03 10:38:57 -0400971 if (layer < 0)
972 {
Jamie Madill437fa652016-05-03 15:13:24 -0400973 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400974 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400975 }
976
977 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
978 {
979 return false;
980 }
981
982 const gl::Caps &caps = context->getCaps();
983 if (texture != 0)
984 {
985 gl::Texture *tex = context->getTexture(texture);
986 ASSERT(tex);
987
988 switch (tex->getTarget())
989 {
990 case GL_TEXTURE_2D_ARRAY:
991 {
992 if (level > gl::log2(caps.max2DTextureSize))
993 {
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400995 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400996 }
997
998 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
999 {
Jamie Madill437fa652016-05-03 15:13:24 -04001000 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001002 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001003 }
1004 break;
1005
1006 case GL_TEXTURE_3D:
1007 {
1008 if (level > gl::log2(caps.max3DTextureSize))
1009 {
Jamie Madill437fa652016-05-03 15:13:24 -04001010 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001011 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001012 }
1013
1014 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1015 {
Jamie Madill437fa652016-05-03 15:13:24 -04001016 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001017 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001018 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001019 }
1020 break;
1021
1022 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001023 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001025 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001026
Jamie Madilla3944d42016-07-22 22:13:26 -04001027 const auto &format = tex->getFormat(tex->getTarget(), level);
1028 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001029 {
Jamie Madill437fa652016-05-03 15:13:24 -04001030 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001031 return false;
1032 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001033 }
1034
1035 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001036}
1037
Corentin Walleze0902642014-11-04 12:32:15 -08001038bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1039 GLenum internalformat, GLsizei width, GLsizei height)
1040{
1041 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1042 {
1043 return false;
1044 }
1045
1046 //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.
1047 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1048 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001051 return false;
1052 }
1053
1054 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1055 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1056 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1057 {
Jamie Madill437fa652016-05-03 15:13:24 -04001058 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001059 Error(GL_INVALID_OPERATION,
1060 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001061 return false;
1062 }
1063
1064 return true;
1065}
1066
Austin Kinross08332632015-05-05 13:35:47 -07001067bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1068 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069{
Martin Radev1be913c2016-07-11 17:59:16 +03001070 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001071 {
Jamie Madill437fa652016-05-03 15:13:24 -04001072 context->handleError(
1073 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001074 return false;
1075 }
1076
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 bool defaultFramebuffer = false;
1078
1079 switch (target)
1080 {
1081 case GL_DRAW_FRAMEBUFFER:
1082 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001083 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1084 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001086 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1087 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001089 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092
Austin Kinross08332632015-05-05 13:35:47 -07001093 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094}
1095
Jamie Madillc29968b2016-01-20 11:17:23 -05001096bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001097{
Martin Radev1be913c2016-07-11 17:59:16 +03001098 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001099 {
Jamie Madill437fa652016-05-03 15:13:24 -04001100 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001101 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001102 }
1103
Jamie Madill51f40ec2016-06-15 14:06:00 -04001104 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1105 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001106 {
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001108 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001109 }
1110
1111 return true;
1112}
1113
Olli Etuaho71dfb362016-03-10 14:04:27 +02001114bool ValidateDrawRangeElements(Context *context,
1115 GLenum mode,
1116 GLuint start,
1117 GLuint end,
1118 GLsizei count,
1119 GLenum type,
1120 const GLvoid *indices,
1121 IndexRange *indexRange)
1122{
Martin Radev1be913c2016-07-11 17:59:16 +03001123 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001124 {
Jamie Madill437fa652016-05-03 15:13:24 -04001125 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001126 return false;
1127 }
1128
1129 if (end < start)
1130 {
Jamie Madill437fa652016-05-03 15:13:24 -04001131 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001132 return false;
1133 }
1134
1135 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1136 {
1137 return false;
1138 }
1139
1140 if (indexRange->end > end || indexRange->start < start)
1141 {
1142 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001143 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001144 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1145 return false;
1146 }
1147 return true;
1148}
1149
Geoff Langb1196682014-07-23 13:47:29 -04001150bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001151{
Martin Radev1be913c2016-07-11 17:59:16 +03001152 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001153 {
Jamie Madill437fa652016-05-03 15:13:24 -04001154 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001156 }
1157
Jamie Madill78f41802014-08-25 15:47:55 -04001158 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001159}
1160
Jamie Madillb885e572015-02-03 16:16:04 -05001161bool ValidateReadBuffer(Context *context, GLenum src)
1162{
Martin Radev1be913c2016-07-11 17:59:16 +03001163 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001164 {
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001166 return false;
1167 }
1168
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001169 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001170
1171 if (readFBO == nullptr)
1172 {
Jamie Madill437fa652016-05-03 15:13:24 -04001173 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001174 return false;
1175 }
1176
1177 if (src == GL_NONE)
1178 {
1179 return true;
1180 }
1181
Olli Etuaho84c9f592016-03-09 14:37:25 +02001182 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001183 {
Jamie Madill437fa652016-05-03 15:13:24 -04001184 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001185 return false;
1186 }
1187
1188 if (readFBO->id() == 0)
1189 {
1190 if (src != GL_BACK)
1191 {
1192 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001193 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001194 return false;
1195 }
1196 }
1197 else
1198 {
1199 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1200
1201 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1202 {
1203 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001204 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001205 return false;
1206 }
1207 }
1208
1209 return true;
1210}
1211
Jamie Madill86af3d22015-07-21 15:14:07 -04001212bool ValidateCompressedTexImage3D(Context *context,
1213 GLenum target,
1214 GLint level,
1215 GLenum internalformat,
1216 GLsizei width,
1217 GLsizei height,
1218 GLsizei depth,
1219 GLint border,
1220 GLsizei imageSize,
1221 const GLvoid *data)
1222{
Martin Radev1be913c2016-07-11 17:59:16 +03001223 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001224 {
Jamie Madill437fa652016-05-03 15:13:24 -04001225 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001226 return false;
1227 }
1228
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001229 if (!ValidTextureTarget(context, target))
1230 {
1231 context->handleError(Error(GL_INVALID_ENUM));
1232 return false;
1233 }
1234
Jamie Madille2e406c2016-06-02 13:04:10 -04001235 // Validate image size
1236 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1237 {
1238 context->handleError(Error(GL_INVALID_VALUE));
1239 return false;
1240 }
1241
Jamie Madill86af3d22015-07-21 15:14:07 -04001242 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001243 if (!formatInfo.compressed)
1244 {
1245 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1246 return false;
1247 }
1248
Jamie Madill513558d2016-06-02 13:04:11 -04001249 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001250 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001251 if (blockSizeOrErr.isError())
1252 {
Jamie Madill513558d2016-06-02 13:04:11 -04001253 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001254 return false;
1255 }
1256 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001257 {
Jamie Madill437fa652016-05-03 15:13:24 -04001258 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001259 return false;
1260 }
1261
1262 // 3D texture target validation
1263 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1264 {
Jamie Madill437fa652016-05-03 15:13:24 -04001265 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001266 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1267 return false;
1268 }
1269
1270 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001271 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001272 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1273 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001274 {
1275 return false;
1276 }
1277
1278 return true;
1279}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001280
1281bool ValidateBindVertexArray(Context *context, GLuint array)
1282{
Martin Radev1be913c2016-07-11 17:59:16 +03001283 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001284 {
Jamie Madill437fa652016-05-03 15:13:24 -04001285 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001286 return false;
1287 }
1288
1289 return ValidateBindVertexArrayBase(context, array);
1290}
1291
Austin Kinrossbc781f32015-10-26 09:27:38 -07001292bool ValidateIsVertexArray(Context *context)
1293{
Martin Radev1be913c2016-07-11 17:59:16 +03001294 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001295 {
Jamie Madill437fa652016-05-03 15:13:24 -04001296 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001297 return false;
1298 }
1299
1300 return true;
1301}
Geoff Langc5629752015-12-07 16:29:04 -05001302
1303bool ValidateProgramBinary(Context *context,
1304 GLuint program,
1305 GLenum binaryFormat,
1306 const void *binary,
1307 GLint length)
1308{
Martin Radev1be913c2016-07-11 17:59:16 +03001309 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001310 {
Jamie Madill437fa652016-05-03 15:13:24 -04001311 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001312 return false;
1313 }
1314
1315 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1316}
1317
1318bool ValidateGetProgramBinary(Context *context,
1319 GLuint program,
1320 GLsizei bufSize,
1321 GLsizei *length,
1322 GLenum *binaryFormat,
1323 void *binary)
1324{
Martin Radev1be913c2016-07-11 17:59:16 +03001325 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001326 {
Jamie Madill437fa652016-05-03 15:13:24 -04001327 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001328 return false;
1329 }
1330
1331 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1332}
1333
Olli Etuahof0fee072016-03-30 15:11:58 +03001334bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001335{
Martin Radev1be913c2016-07-11 17:59:16 +03001336 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001337 {
Jamie Madill437fa652016-05-03 15:13:24 -04001338 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001339 return false;
1340 }
1341
1342 if (GetValidProgram(context, program) == nullptr)
1343 {
1344 return false;
1345 }
1346
1347 switch (pname)
1348 {
1349 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001350 if (value != GL_FALSE && value != GL_TRUE)
1351 {
Jamie Madill437fa652016-05-03 15:13:24 -04001352 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001353 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1354 return false;
1355 }
Geoff Langc5629752015-12-07 16:29:04 -05001356 break;
1357
1358 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001359 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001360 return false;
1361 }
1362
1363 return true;
1364}
Jamie Madillc29968b2016-01-20 11:17:23 -05001365
1366bool ValidateBlitFramebuffer(Context *context,
1367 GLint srcX0,
1368 GLint srcY0,
1369 GLint srcX1,
1370 GLint srcY1,
1371 GLint dstX0,
1372 GLint dstY0,
1373 GLint dstX1,
1374 GLint dstY1,
1375 GLbitfield mask,
1376 GLenum filter)
1377{
Martin Radev1be913c2016-07-11 17:59:16 +03001378 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001379 {
Jamie Madill437fa652016-05-03 15:13:24 -04001380 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001381 return false;
1382 }
1383
1384 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1385 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386}
Jamie Madillc29968b2016-01-20 11:17:23 -05001387
1388bool ValidateClearBufferiv(ValidationContext *context,
1389 GLenum buffer,
1390 GLint drawbuffer,
1391 const GLint *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_STENCIL:
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 ValidateClearBufferuiv(ValidationContext *context,
1421 GLenum buffer,
1422 GLint drawbuffer,
1423 const GLuint *value)
1424{
1425 switch (buffer)
1426 {
1427 case GL_COLOR:
1428 if (drawbuffer < 0 ||
1429 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
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 ValidateClearBufferfv(ValidationContext *context,
1445 GLenum buffer,
1446 GLint drawbuffer,
1447 const GLfloat *value)
1448{
1449 switch (buffer)
1450 {
1451 case GL_COLOR:
1452 if (drawbuffer < 0 ||
1453 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001456 return false;
1457 }
1458 break;
1459
1460 case GL_DEPTH:
1461 if (drawbuffer != 0)
1462 {
Jamie Madill437fa652016-05-03 15:13:24 -04001463 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001464 return false;
1465 }
1466 break;
1467
1468 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001469 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001470 return false;
1471 }
1472
1473 return ValidateClearBuffer(context);
1474}
1475
1476bool ValidateClearBufferfi(ValidationContext *context,
1477 GLenum buffer,
1478 GLint drawbuffer,
1479 GLfloat depth,
1480 GLint stencil)
1481{
1482 switch (buffer)
1483 {
1484 case GL_DEPTH_STENCIL:
1485 if (drawbuffer != 0)
1486 {
Jamie Madill437fa652016-05-03 15:13:24 -04001487 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 return false;
1489 }
1490 break;
1491
1492 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001493 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return false;
1495 }
1496
1497 return ValidateClearBuffer(context);
1498}
1499
1500bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1501{
Martin Radev1be913c2016-07-11 17:59:16 +03001502 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001503 {
Jamie Madill437fa652016-05-03 15:13:24 -04001504 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001505 return false;
1506 }
1507
1508 return ValidateDrawBuffersBase(context, n, bufs);
1509}
1510
1511bool ValidateCopyTexSubImage3D(Context *context,
1512 GLenum target,
1513 GLint level,
1514 GLint xoffset,
1515 GLint yoffset,
1516 GLint zoffset,
1517 GLint x,
1518 GLint y,
1519 GLsizei width,
1520 GLsizei height)
1521{
Martin Radev1be913c2016-07-11 17:59:16 +03001522 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001523 {
Jamie Madill437fa652016-05-03 15:13:24 -04001524 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001525 return false;
1526 }
1527
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001528 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1529 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001530}
1531
Jamie Madill73a84962016-02-12 09:27:23 -05001532bool ValidateTexImage3D(Context *context,
1533 GLenum target,
1534 GLint level,
1535 GLint internalformat,
1536 GLsizei width,
1537 GLsizei height,
1538 GLsizei depth,
1539 GLint border,
1540 GLenum format,
1541 GLenum type,
1542 const GLvoid *pixels)
1543{
Martin Radev1be913c2016-07-11 17:59:16 +03001544 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001545 {
Jamie Madill437fa652016-05-03 15:13:24 -04001546 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001547 return false;
1548 }
1549
1550 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001551 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001552 pixels);
1553}
1554
Geoff Langc52f6f12016-10-14 10:18:00 -04001555bool ValidateTexImage3DRobustANGLE(Context *context,
1556 GLenum target,
1557 GLint level,
1558 GLint internalformat,
1559 GLsizei width,
1560 GLsizei height,
1561 GLsizei depth,
1562 GLint border,
1563 GLenum format,
1564 GLenum type,
1565 GLsizei bufSize,
1566 const GLvoid *pixels)
1567{
1568 if (context->getClientMajorVersion() < 3)
1569 {
1570 context->handleError(Error(GL_INVALID_OPERATION));
1571 return false;
1572 }
1573
1574 if (!ValidateRobustEntryPoint(context, bufSize))
1575 {
1576 return false;
1577 }
1578
1579 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1580 0, 0, width, height, depth, border, format, type,
1581 bufSize, pixels);
1582}
1583
Jamie Madill73a84962016-02-12 09:27:23 -05001584bool ValidateTexSubImage3D(Context *context,
1585 GLenum target,
1586 GLint level,
1587 GLint xoffset,
1588 GLint yoffset,
1589 GLint zoffset,
1590 GLsizei width,
1591 GLsizei height,
1592 GLsizei depth,
1593 GLenum format,
1594 GLenum type,
1595 const GLvoid *pixels)
1596{
Martin Radev1be913c2016-07-11 17:59:16 +03001597 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001600 return false;
1601 }
1602
1603 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1604 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001605 -1, pixels);
1606}
1607
1608bool ValidateTexSubImage3DRobustANGLE(Context *context,
1609 GLenum target,
1610 GLint level,
1611 GLint xoffset,
1612 GLint yoffset,
1613 GLint zoffset,
1614 GLsizei width,
1615 GLsizei height,
1616 GLsizei depth,
1617 GLenum format,
1618 GLenum type,
1619 GLsizei bufSize,
1620 const GLvoid *pixels)
1621{
1622 if (context->getClientMajorVersion() < 3)
1623 {
1624 context->handleError(Error(GL_INVALID_OPERATION));
1625 return false;
1626 }
1627
1628 if (!ValidateRobustEntryPoint(context, bufSize))
1629 {
1630 return false;
1631 }
1632
1633 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1634 yoffset, zoffset, width, height, depth, 0, format, type,
1635 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001636}
1637
1638bool ValidateCompressedTexSubImage3D(Context *context,
1639 GLenum target,
1640 GLint level,
1641 GLint xoffset,
1642 GLint yoffset,
1643 GLint zoffset,
1644 GLsizei width,
1645 GLsizei height,
1646 GLsizei depth,
1647 GLenum format,
1648 GLsizei imageSize,
1649 const GLvoid *data)
1650{
Martin Radev1be913c2016-07-11 17:59:16 +03001651 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001652 {
Jamie Madill437fa652016-05-03 15:13:24 -04001653 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001654 return false;
1655 }
1656
1657 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001658 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001659 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001660 if (blockSizeOrErr.isError())
1661 {
1662 context->handleError(blockSizeOrErr.getError());
1663 return false;
1664 }
1665 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001666 {
Jamie Madill437fa652016-05-03 15:13:24 -04001667 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001668 return false;
1669 }
1670
1671 if (!data)
1672 {
Jamie Madill437fa652016-05-03 15:13:24 -04001673 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001674 return false;
1675 }
1676
1677 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001678 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001679}
1680
Olli Etuaho41997e72016-03-10 13:38:39 +02001681bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1682{
1683 return ValidateGenOrDeleteES3(context, n);
1684}
1685
1686bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1687{
1688 return ValidateGenOrDeleteES3(context, n);
1689}
1690
1691bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1692{
1693 return ValidateGenOrDeleteCountES3(context, count);
1694}
1695
1696bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1697{
1698 return ValidateGenOrDeleteCountES3(context, count);
1699}
1700
1701bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1702{
1703 return ValidateGenOrDeleteES3(context, n);
1704}
1705
1706bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1707{
1708 if (!ValidateGenOrDeleteES3(context, n))
1709 {
1710 return false;
1711 }
1712 for (GLint i = 0; i < n; ++i)
1713 {
1714 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1715 if (transformFeedback != nullptr && transformFeedback->isActive())
1716 {
1717 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001719 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1720 return false;
1721 }
1722 }
1723 return true;
1724}
1725
1726bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1727{
1728 return ValidateGenOrDeleteES3(context, n);
1729}
1730
1731bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1732{
1733 return ValidateGenOrDeleteES3(context, n);
1734}
1735
1736bool ValidateGenOrDeleteES3(Context *context, GLint n)
1737{
Martin Radev1be913c2016-07-11 17:59:16 +03001738 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001739 {
Jamie Madill437fa652016-05-03 15:13:24 -04001740 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001741 return false;
1742 }
1743 return ValidateGenOrDelete(context, n);
1744}
1745
1746bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1747{
Martin Radev1be913c2016-07-11 17:59:16 +03001748 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001749 {
Jamie Madill437fa652016-05-03 15:13:24 -04001750 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001751 return false;
1752 }
1753 if (count < 0)
1754 {
Jamie Madill437fa652016-05-03 15:13:24 -04001755 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001756 return false;
1757 }
1758 return true;
1759}
1760
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001761bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1762{
Martin Radev1be913c2016-07-11 17:59:16 +03001763 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001766 return false;
1767 }
1768 switch (primitiveMode)
1769 {
1770 case GL_TRIANGLES:
1771 case GL_LINES:
1772 case GL_POINTS:
1773 break;
1774
1775 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001776 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001777 return false;
1778 }
1779
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001780 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001781 ASSERT(transformFeedback != nullptr);
1782
1783 if (transformFeedback->isActive())
1784 {
Jamie Madill437fa652016-05-03 15:13:24 -04001785 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001786 return false;
1787 }
1788 return true;
1789}
1790
Olli Etuaho4f667482016-03-30 15:56:35 +03001791bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1792{
Geoff Lang496c02d2016-10-20 11:38:11 -07001793 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1794}
1795
1796bool ValidateGetBufferPointervRobustANGLE(Context *context,
1797 GLenum target,
1798 GLenum pname,
1799 GLsizei bufSize,
1800 GLsizei *length,
1801 GLvoid **params)
1802{
1803 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001804 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001805 return false;
1806 }
1807
Geoff Lang496c02d2016-10-20 11:38:11 -07001808 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1809 {
1810 return false;
1811 }
1812
1813 if (!ValidateRobustBufferSize(context, bufSize, *length))
1814 {
1815 return false;
1816 }
1817
1818 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001819}
1820
1821bool ValidateUnmapBuffer(Context *context, GLenum target)
1822{
Martin Radev1be913c2016-07-11 17:59:16 +03001823 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001824 {
Jamie Madill437fa652016-05-03 15:13:24 -04001825 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001826 return false;
1827 }
1828
1829 return ValidateUnmapBufferBase(context, target);
1830}
1831
1832bool ValidateMapBufferRange(Context *context,
1833 GLenum target,
1834 GLintptr offset,
1835 GLsizeiptr length,
1836 GLbitfield access)
1837{
Martin Radev1be913c2016-07-11 17:59:16 +03001838 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001839 {
Jamie Madill437fa652016-05-03 15:13:24 -04001840 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001841 return false;
1842 }
1843
1844 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1845}
1846
1847bool ValidateFlushMappedBufferRange(Context *context,
1848 GLenum target,
1849 GLintptr offset,
1850 GLsizeiptr length)
1851{
Martin Radev1be913c2016-07-11 17:59:16 +03001852 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001853 {
Jamie Madill437fa652016-05-03 15:13:24 -04001854 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001855 return false;
1856 }
1857
1858 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1859}
1860
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001861bool ValidateIndexedStateQuery(ValidationContext *context,
1862 GLenum pname,
1863 GLuint index,
1864 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001865{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001866 if (length)
1867 {
1868 *length = 0;
1869 }
1870
Martin Radev66fb8202016-07-28 11:45:20 +03001871 GLenum nativeType;
1872 unsigned int numParams;
1873 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1874 {
1875 context->handleError(Error(GL_INVALID_ENUM));
1876 return false;
1877 }
1878
1879 const Caps &caps = context->getCaps();
1880 switch (pname)
1881 {
1882 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1883 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1884 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1885 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1886 {
1887 context->handleError(Error(GL_INVALID_VALUE));
1888 return false;
1889 }
1890 break;
1891
1892 case GL_UNIFORM_BUFFER_START:
1893 case GL_UNIFORM_BUFFER_SIZE:
1894 case GL_UNIFORM_BUFFER_BINDING:
1895 if (index >= caps.maxUniformBufferBindings)
1896 {
1897 context->handleError(Error(GL_INVALID_VALUE));
1898 return false;
1899 }
1900 break;
1901 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1902 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1903 if (index >= 3u)
1904 {
1905 context->handleError(Error(GL_INVALID_VALUE));
1906 return false;
1907 }
1908 break;
1909 default:
1910 context->handleError(Error(GL_INVALID_ENUM));
1911 return false;
1912 }
1913
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001914 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001915 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001916 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001917 }
1918
1919 return true;
1920}
1921
1922bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1923{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001924 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001925 {
1926 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1927 return false;
1928 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001929 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001930}
1931
Geoff Langcf255ea2016-10-20 11:39:09 -07001932bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
1933 GLenum target,
1934 GLuint index,
1935 GLsizei bufSize,
1936 GLsizei *length,
1937 GLint *data)
1938{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001939 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07001940 {
1941 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1942 return false;
1943 }
1944
1945 if (!ValidateRobustEntryPoint(context, bufSize))
1946 {
1947 return false;
1948 }
1949
1950 if (!ValidateIndexedStateQuery(context, target, index, length))
1951 {
1952 return false;
1953 }
1954
1955 if (!ValidateRobustBufferSize(context, bufSize, *length))
1956 {
1957 return false;
1958 }
1959
1960 return true;
1961}
1962
Martin Radev66fb8202016-07-28 11:45:20 +03001963bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1964{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001965 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001966 {
1967 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1968 return false;
1969 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001970 return ValidateIndexedStateQuery(context, target, index, nullptr);
1971}
1972
1973bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1974 GLenum target,
1975 GLuint index,
1976 GLsizei bufSize,
1977 GLsizei *length,
1978 GLint64 *data)
1979{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001980 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001981 {
1982 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1983 return false;
1984 }
1985
1986 if (!ValidateRobustEntryPoint(context, bufSize))
1987 {
1988 return false;
1989 }
1990
1991 if (!ValidateIndexedStateQuery(context, target, index, length))
1992 {
1993 return false;
1994 }
1995
1996 if (!ValidateRobustBufferSize(context, bufSize, *length))
1997 {
1998 return false;
1999 }
2000
2001 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002002}
2003
Jamie Madillb0817d12016-11-01 15:48:31 -04002004bool ValidateCopyBufferSubData(ValidationContext *context,
2005 GLenum readTarget,
2006 GLenum writeTarget,
2007 GLintptr readOffset,
2008 GLintptr writeOffset,
2009 GLsizeiptr size)
2010{
2011 if (context->getClientMajorVersion() < 3)
2012 {
2013 context->handleError(Error(GL_INVALID_OPERATION));
2014 return false;
2015 }
2016
2017 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2018 {
2019 context->handleError(Error(GL_INVALID_ENUM));
2020 return false;
2021 }
2022
2023 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2024 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2025
2026 if (!readBuffer || !writeBuffer)
2027 {
2028 context->handleError(Error(GL_INVALID_OPERATION));
2029 return false;
2030 }
2031
2032 // Verify that readBuffer and writeBuffer are not currently mapped
2033 if (readBuffer->isMapped() || writeBuffer->isMapped())
2034 {
2035 context->handleError(Error(GL_INVALID_OPERATION));
2036 return false;
2037 }
2038
2039 if (readOffset < 0 || writeOffset < 0 || size < 0 ||
2040 static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
2041 static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
2042 {
2043 context->handleError(Error(GL_INVALID_VALUE));
2044 return false;
2045 }
2046
2047 if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
2048 {
2049 context->handleError(Error(GL_INVALID_VALUE));
2050 return false;
2051 }
2052
2053 return true;
2054}
2055
Jamie Madillc29968b2016-01-20 11:17:23 -05002056} // namespace gl