blob: 692d739fcf9fb67e0f509577b39774d607760fb7 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
Geoff Langa9be0dc2014-12-17 12:34:40 -050020#include "common/utilities.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
Geoff Lang5d601382014-07-22 15:14:06 -040027static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
28{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050029 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
30 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
31 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
32 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -040033 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Martin Radev1be913c2016-07-11 17:59:16 +030034 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -040035 {
Jamie Madill437fa652016-05-03 15:13:24 -040036 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040037 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040038 }
39
40 // The type and format are valid if any supported internal format has that type and format
Jamie Madill55e98212016-10-05 16:39:13 -040041 if (!ValidES3Format(format) || !ValidES3Type(type))
Geoff Lang5d601382014-07-22 15:14:06 -040042 {
Jamie Madill437fa652016-05-03 15:13:24 -040043 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -040044 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040045 }
46
47 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040048 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040049 {
Jamie Madill437fa652016-05-03 15:13:24 -040050 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -040051 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040052 }
53
54 return true;
55}
56
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050057bool ValidateES3TexImageParametersBase(Context *context,
58 GLenum target,
59 GLint level,
60 GLenum internalformat,
61 bool isCompressed,
62 bool isSubImage,
63 GLint xoffset,
64 GLint yoffset,
65 GLint zoffset,
66 GLsizei width,
67 GLsizei height,
68 GLsizei depth,
69 GLint border,
70 GLenum format,
71 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -040072 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050073 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040074{
75 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -070076 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040077 {
Jamie Madill437fa652016-05-03 15:13:24 -040078 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040079 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040080 }
81
Geoff Lange8ebe7f2013-08-05 15:03:13 -040082 // Verify zero border
83 if (border != 0)
84 {
Jamie Madill437fa652016-05-03 15:13:24 -040085 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040086 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040087 }
88
Jamie Madill6f38f822014-06-06 17:12:20 -040089 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
90 std::numeric_limits<GLsizei>::max() - xoffset < width ||
91 std::numeric_limits<GLsizei>::max() - yoffset < height ||
92 std::numeric_limits<GLsizei>::max() - zoffset < depth)
93 {
Jamie Madill437fa652016-05-03 15:13:24 -040094 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040095 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040096 }
97
Geoff Langaae65a42014-05-26 12:43:44 -040098 const gl::Caps &caps = context->getCaps();
99
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400100 switch (target)
101 {
102 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500103 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
104 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400105 {
Jamie Madill437fa652016-05-03 15:13:24 -0400106 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108 }
109 break;
110
111 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
112 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
113 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
114 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
115 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
116 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500117 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 {
Jamie Madill437fa652016-05-03 15:13:24 -0400119 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500120 return false;
121 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400122
Geoff Langa9be0dc2014-12-17 12:34:40 -0500123 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
124 {
Jamie Madill437fa652016-05-03 15:13:24 -0400125 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 }
128 break;
129
130 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -0500131 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
132 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
133 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400134 {
Jamie Madill437fa652016-05-03 15:13:24 -0400135 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500136 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400137 }
138 break;
139
Geoff Langa9be0dc2014-12-17 12:34:40 -0500140 case GL_TEXTURE_2D_ARRAY:
141 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
142 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
Geoff Langb92c1332015-09-04 12:54:55 -0400143 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500144 {
Jamie Madill437fa652016-05-03 15:13:24 -0400145 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500146 return false;
147 }
148 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400149
150 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400151 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400153 }
154
Geoff Lang691e58c2014-12-19 17:03:25 -0500155 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 if (!texture)
157 {
Jamie Madill437fa652016-05-03 15:13:24 -0400158 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400159 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160 }
161
Geoff Lang69cce582015-09-17 13:20:36 -0400162 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400163 {
Jamie Madill437fa652016-05-03 15:13:24 -0400164 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400166 }
167
168 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400169 GLenum actualInternalFormat =
170 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lang5d601382014-07-22 15:14:06 -0400171 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400172 if (isCompressed)
173 {
tmartino7c102692015-10-02 16:43:40 -0400174 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400175 {
Jamie Madill437fa652016-05-03 15:13:24 -0400176 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400177 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400178 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400179 }
180
tmartino7c102692015-10-02 16:43:40 -0400181 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 {
Jamie Madill437fa652016-05-03 15:13:24 -0400183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400184 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400185 }
186
Martin Radev1be913c2016-07-11 17:59:16 +0300187 if (!actualFormatInfo.textureSupport(context->getClientMajorVersion(),
188 context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400189 {
Jamie Madill437fa652016-05-03 15:13:24 -0400190 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400191 return false;
192 }
193
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400194 if (target == GL_TEXTURE_3D)
195 {
Jamie Madill437fa652016-05-03 15:13:24 -0400196 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 }
199 }
200 else
201 {
Geoff Langbaadf232014-08-04 13:58:02 -0400202 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400203 {
Geoff Lang5d601382014-07-22 15:14:06 -0400204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400205 }
206
207 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
208 {
Jamie Madill437fa652016-05-03 15:13:24 -0400209 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400211 }
212 }
213
214 // Validate sub image parameters
215 if (isSubImage)
216 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500217 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400218 {
Jamie Madill437fa652016-05-03 15:13:24 -0400219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400220 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400221 }
222
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400223 if (width == 0 || height == 0 || depth == 0)
224 {
225 return false;
226 }
227
228 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
229 {
Jamie Madill437fa652016-05-03 15:13:24 -0400230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
234 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
235 std::numeric_limits<GLsizei>::max() - yoffset < height ||
236 std::numeric_limits<GLsizei>::max() - zoffset < depth)
237 {
Jamie Madill437fa652016-05-03 15:13:24 -0400238 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400239 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400240 }
241
Geoff Langa9be0dc2014-12-17 12:34:40 -0500242 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
243 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
244 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400245 {
Jamie Madill437fa652016-05-03 15:13:24 -0400246 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400248 }
249 }
250
Geoff Langff5b2d52016-09-07 11:32:23 -0400251 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
252 imageSize))
253 {
254 return false;
255 }
256
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400257 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700258 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400259 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400260 {
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400261 // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
262 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400263 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400264 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400265 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400266 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
267
Geoff Langff5b2d52016-09-07 11:32:23 -0400268 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400269 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400270 context->handleError(
271 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400272 return false;
273 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400274 }
275
Jamie Madill7a5f7382014-03-05 15:01:24 -0500276 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700277 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500278 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400279 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400280 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500281 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400282 }
283
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400284 return true;
285}
286
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500287bool ValidateES3TexImage2DParameters(Context *context,
288 GLenum target,
289 GLint level,
290 GLenum internalformat,
291 bool isCompressed,
292 bool isSubImage,
293 GLint xoffset,
294 GLint yoffset,
295 GLint zoffset,
296 GLsizei width,
297 GLsizei height,
298 GLsizei depth,
299 GLint border,
300 GLenum format,
301 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400302 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500303 const GLvoid *pixels)
304{
305 if (!ValidTexture2DDestinationTarget(context, target))
306 {
Jamie Madill437fa652016-05-03 15:13:24 -0400307 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500308 return false;
309 }
310
311 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
312 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400313 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500314}
315
316bool ValidateES3TexImage3DParameters(Context *context,
317 GLenum target,
318 GLint level,
319 GLenum internalformat,
320 bool isCompressed,
321 bool isSubImage,
322 GLint xoffset,
323 GLint yoffset,
324 GLint zoffset,
325 GLsizei width,
326 GLsizei height,
327 GLsizei depth,
328 GLint border,
329 GLenum format,
330 GLenum type,
331 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 Langff5b2d52016-09-07 11:32:23 -0400341 depth, border, format, type, -1, 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);
Martin Radev1be913c2016-07-11 17:59:16 +0300867 if (!formatInfo.textureSupport(context->getClientMajorVersion(), 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,
1272 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001273 {
1274 return false;
1275 }
1276
1277 return true;
1278}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001279
1280bool ValidateBindVertexArray(Context *context, GLuint array)
1281{
Martin Radev1be913c2016-07-11 17:59:16 +03001282 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001283 {
Jamie Madill437fa652016-05-03 15:13:24 -04001284 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001285 return false;
1286 }
1287
1288 return ValidateBindVertexArrayBase(context, array);
1289}
1290
Austin Kinrossbc781f32015-10-26 09:27:38 -07001291bool ValidateIsVertexArray(Context *context)
1292{
Martin Radev1be913c2016-07-11 17:59:16 +03001293 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001294 {
Jamie Madill437fa652016-05-03 15:13:24 -04001295 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001296 return false;
1297 }
1298
1299 return true;
1300}
Geoff Langc5629752015-12-07 16:29:04 -05001301
1302bool ValidateProgramBinary(Context *context,
1303 GLuint program,
1304 GLenum binaryFormat,
1305 const void *binary,
1306 GLint length)
1307{
Martin Radev1be913c2016-07-11 17:59:16 +03001308 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001309 {
Jamie Madill437fa652016-05-03 15:13:24 -04001310 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001311 return false;
1312 }
1313
1314 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1315}
1316
1317bool ValidateGetProgramBinary(Context *context,
1318 GLuint program,
1319 GLsizei bufSize,
1320 GLsizei *length,
1321 GLenum *binaryFormat,
1322 void *binary)
1323{
Martin Radev1be913c2016-07-11 17:59:16 +03001324 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001325 {
Jamie Madill437fa652016-05-03 15:13:24 -04001326 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001327 return false;
1328 }
1329
1330 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1331}
1332
Olli Etuahof0fee072016-03-30 15:11:58 +03001333bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001334{
Martin Radev1be913c2016-07-11 17:59:16 +03001335 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001338 return false;
1339 }
1340
1341 if (GetValidProgram(context, program) == nullptr)
1342 {
1343 return false;
1344 }
1345
1346 switch (pname)
1347 {
1348 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001349 if (value != GL_FALSE && value != GL_TRUE)
1350 {
Jamie Madill437fa652016-05-03 15:13:24 -04001351 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001352 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1353 return false;
1354 }
Geoff Langc5629752015-12-07 16:29:04 -05001355 break;
1356
1357 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001358 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001359 return false;
1360 }
1361
1362 return true;
1363}
Jamie Madillc29968b2016-01-20 11:17:23 -05001364
1365bool ValidateBlitFramebuffer(Context *context,
1366 GLint srcX0,
1367 GLint srcY0,
1368 GLint srcX1,
1369 GLint srcY1,
1370 GLint dstX0,
1371 GLint dstY0,
1372 GLint dstX1,
1373 GLint dstY1,
1374 GLbitfield mask,
1375 GLenum filter)
1376{
Martin Radev1be913c2016-07-11 17:59:16 +03001377 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001378 {
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001380 return false;
1381 }
1382
1383 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1384 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385}
Jamie Madillc29968b2016-01-20 11:17:23 -05001386
1387bool ValidateClearBufferiv(ValidationContext *context,
1388 GLenum buffer,
1389 GLint drawbuffer,
1390 const GLint *value)
1391{
1392 switch (buffer)
1393 {
1394 case GL_COLOR:
1395 if (drawbuffer < 0 ||
1396 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001399 return false;
1400 }
1401 break;
1402
1403 case GL_STENCIL:
1404 if (drawbuffer != 0)
1405 {
Jamie Madill437fa652016-05-03 15:13:24 -04001406 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001407 return false;
1408 }
1409 break;
1410
1411 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001412 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001413 return false;
1414 }
1415
1416 return ValidateClearBuffer(context);
1417}
1418
1419bool ValidateClearBufferuiv(ValidationContext *context,
1420 GLenum buffer,
1421 GLint drawbuffer,
1422 const GLuint *value)
1423{
1424 switch (buffer)
1425 {
1426 case GL_COLOR:
1427 if (drawbuffer < 0 ||
1428 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1429 {
Jamie Madill437fa652016-05-03 15:13:24 -04001430 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001431 return false;
1432 }
1433 break;
1434
1435 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001436 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001437 return false;
1438 }
1439
1440 return ValidateClearBuffer(context);
1441}
1442
1443bool ValidateClearBufferfv(ValidationContext *context,
1444 GLenum buffer,
1445 GLint drawbuffer,
1446 const GLfloat *value)
1447{
1448 switch (buffer)
1449 {
1450 case GL_COLOR:
1451 if (drawbuffer < 0 ||
1452 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1453 {
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 return false;
1456 }
1457 break;
1458
1459 case GL_DEPTH:
1460 if (drawbuffer != 0)
1461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001463 return false;
1464 }
1465 break;
1466
1467 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001468 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001469 return false;
1470 }
1471
1472 return ValidateClearBuffer(context);
1473}
1474
1475bool ValidateClearBufferfi(ValidationContext *context,
1476 GLenum buffer,
1477 GLint drawbuffer,
1478 GLfloat depth,
1479 GLint stencil)
1480{
1481 switch (buffer)
1482 {
1483 case GL_DEPTH_STENCIL:
1484 if (drawbuffer != 0)
1485 {
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001487 return false;
1488 }
1489 break;
1490
1491 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001492 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
1496 return ValidateClearBuffer(context);
1497}
1498
1499bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1500{
Martin Radev1be913c2016-07-11 17:59:16 +03001501 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001502 {
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001504 return false;
1505 }
1506
1507 return ValidateDrawBuffersBase(context, n, bufs);
1508}
1509
1510bool ValidateCopyTexSubImage3D(Context *context,
1511 GLenum target,
1512 GLint level,
1513 GLint xoffset,
1514 GLint yoffset,
1515 GLint zoffset,
1516 GLint x,
1517 GLint y,
1518 GLsizei width,
1519 GLsizei height)
1520{
Martin Radev1be913c2016-07-11 17:59:16 +03001521 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001522 {
Jamie Madill437fa652016-05-03 15:13:24 -04001523 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001524 return false;
1525 }
1526
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001527 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1528 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001529}
1530
Jamie Madill73a84962016-02-12 09:27:23 -05001531bool ValidateTexImage3D(Context *context,
1532 GLenum target,
1533 GLint level,
1534 GLint internalformat,
1535 GLsizei width,
1536 GLsizei height,
1537 GLsizei depth,
1538 GLint border,
1539 GLenum format,
1540 GLenum type,
1541 const GLvoid *pixels)
1542{
Martin Radev1be913c2016-07-11 17:59:16 +03001543 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001546 return false;
1547 }
1548
1549 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1550 0, 0, width, height, depth, border, format, type,
1551 pixels);
1552}
1553
1554bool ValidateTexSubImage3D(Context *context,
1555 GLenum target,
1556 GLint level,
1557 GLint xoffset,
1558 GLint yoffset,
1559 GLint zoffset,
1560 GLsizei width,
1561 GLsizei height,
1562 GLsizei depth,
1563 GLenum format,
1564 GLenum type,
1565 const GLvoid *pixels)
1566{
Martin Radev1be913c2016-07-11 17:59:16 +03001567 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001570 return false;
1571 }
1572
1573 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1574 yoffset, zoffset, width, height, depth, 0, format, type,
1575 pixels);
1576}
1577
1578bool ValidateCompressedTexSubImage3D(Context *context,
1579 GLenum target,
1580 GLint level,
1581 GLint xoffset,
1582 GLint yoffset,
1583 GLint zoffset,
1584 GLsizei width,
1585 GLsizei height,
1586 GLsizei depth,
1587 GLenum format,
1588 GLsizei imageSize,
1589 const GLvoid *data)
1590{
Martin Radev1be913c2016-07-11 17:59:16 +03001591 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001592 {
Jamie Madill437fa652016-05-03 15:13:24 -04001593 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001594 return false;
1595 }
1596
1597 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001598 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001599 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001600 if (blockSizeOrErr.isError())
1601 {
1602 context->handleError(blockSizeOrErr.getError());
1603 return false;
1604 }
1605 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001606 {
Jamie Madill437fa652016-05-03 15:13:24 -04001607 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001608 return false;
1609 }
1610
1611 if (!data)
1612 {
Jamie Madill437fa652016-05-03 15:13:24 -04001613 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001614 return false;
1615 }
1616
1617 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1618 width, height, depth, 0, GL_NONE, GL_NONE, data);
1619}
1620
Olli Etuaho41997e72016-03-10 13:38:39 +02001621bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1622{
1623 return ValidateGenOrDeleteES3(context, n);
1624}
1625
1626bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1627{
1628 return ValidateGenOrDeleteES3(context, n);
1629}
1630
1631bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1632{
1633 return ValidateGenOrDeleteCountES3(context, count);
1634}
1635
1636bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1637{
1638 return ValidateGenOrDeleteCountES3(context, count);
1639}
1640
1641bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1642{
1643 return ValidateGenOrDeleteES3(context, n);
1644}
1645
1646bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1647{
1648 if (!ValidateGenOrDeleteES3(context, n))
1649 {
1650 return false;
1651 }
1652 for (GLint i = 0; i < n; ++i)
1653 {
1654 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1655 if (transformFeedback != nullptr && transformFeedback->isActive())
1656 {
1657 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001658 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001659 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1660 return false;
1661 }
1662 }
1663 return true;
1664}
1665
1666bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1667{
1668 return ValidateGenOrDeleteES3(context, n);
1669}
1670
1671bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1672{
1673 return ValidateGenOrDeleteES3(context, n);
1674}
1675
1676bool ValidateGenOrDeleteES3(Context *context, GLint n)
1677{
Martin Radev1be913c2016-07-11 17:59:16 +03001678 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001679 {
Jamie Madill437fa652016-05-03 15:13:24 -04001680 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001681 return false;
1682 }
1683 return ValidateGenOrDelete(context, n);
1684}
1685
1686bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1687{
Martin Radev1be913c2016-07-11 17:59:16 +03001688 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001691 return false;
1692 }
1693 if (count < 0)
1694 {
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001696 return false;
1697 }
1698 return true;
1699}
1700
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001701bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1702{
Martin Radev1be913c2016-07-11 17:59:16 +03001703 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001704 {
Jamie Madill437fa652016-05-03 15:13:24 -04001705 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001706 return false;
1707 }
1708 switch (primitiveMode)
1709 {
1710 case GL_TRIANGLES:
1711 case GL_LINES:
1712 case GL_POINTS:
1713 break;
1714
1715 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001716 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001717 return false;
1718 }
1719
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001720 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001721 ASSERT(transformFeedback != nullptr);
1722
1723 if (transformFeedback->isActive())
1724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001726 return false;
1727 }
1728 return true;
1729}
1730
Olli Etuaho4f667482016-03-30 15:56:35 +03001731bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1732{
Martin Radev1be913c2016-07-11 17:59:16 +03001733 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001734 {
Jamie Madill437fa652016-05-03 15:13:24 -04001735 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001736 return false;
1737 }
1738
1739 return ValidateGetBufferPointervBase(context, target, pname, params);
1740}
1741
1742bool ValidateUnmapBuffer(Context *context, GLenum target)
1743{
Martin Radev1be913c2016-07-11 17:59:16 +03001744 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001745 {
Jamie Madill437fa652016-05-03 15:13:24 -04001746 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001747 return false;
1748 }
1749
1750 return ValidateUnmapBufferBase(context, target);
1751}
1752
1753bool ValidateMapBufferRange(Context *context,
1754 GLenum target,
1755 GLintptr offset,
1756 GLsizeiptr length,
1757 GLbitfield access)
1758{
Martin Radev1be913c2016-07-11 17:59:16 +03001759 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001760 {
Jamie Madill437fa652016-05-03 15:13:24 -04001761 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001762 return false;
1763 }
1764
1765 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1766}
1767
1768bool ValidateFlushMappedBufferRange(Context *context,
1769 GLenum target,
1770 GLintptr offset,
1771 GLsizeiptr length)
1772{
Martin Radev1be913c2016-07-11 17:59:16 +03001773 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001776 return false;
1777 }
1778
1779 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1780}
1781
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001782bool ValidateIndexedStateQuery(ValidationContext *context,
1783 GLenum pname,
1784 GLuint index,
1785 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001786{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001787 if (length)
1788 {
1789 *length = 0;
1790 }
1791
Martin Radev66fb8202016-07-28 11:45:20 +03001792 GLenum nativeType;
1793 unsigned int numParams;
1794 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1795 {
1796 context->handleError(Error(GL_INVALID_ENUM));
1797 return false;
1798 }
1799
1800 const Caps &caps = context->getCaps();
1801 switch (pname)
1802 {
1803 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1804 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1805 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1806 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1807 {
1808 context->handleError(Error(GL_INVALID_VALUE));
1809 return false;
1810 }
1811 break;
1812
1813 case GL_UNIFORM_BUFFER_START:
1814 case GL_UNIFORM_BUFFER_SIZE:
1815 case GL_UNIFORM_BUFFER_BINDING:
1816 if (index >= caps.maxUniformBufferBindings)
1817 {
1818 context->handleError(Error(GL_INVALID_VALUE));
1819 return false;
1820 }
1821 break;
1822 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1823 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1824 if (index >= 3u)
1825 {
1826 context->handleError(Error(GL_INVALID_VALUE));
1827 return false;
1828 }
1829 break;
1830 default:
1831 context->handleError(Error(GL_INVALID_ENUM));
1832 return false;
1833 }
1834
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001835 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001836 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001837 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001838 }
1839
1840 return true;
1841}
1842
1843bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1844{
1845 if (!context->getGLVersion().isES3OrGreater())
1846 {
1847 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1848 return false;
1849 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001850 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001851}
1852
1853bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1854{
1855 if (!context->getGLVersion().isES3OrGreater())
1856 {
1857 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1858 return false;
1859 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001860 return ValidateIndexedStateQuery(context, target, index, nullptr);
1861}
1862
1863bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1864 GLenum target,
1865 GLuint index,
1866 GLsizei bufSize,
1867 GLsizei *length,
1868 GLint64 *data)
1869{
1870 if (!context->getGLVersion().isES3OrGreater())
1871 {
1872 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1873 return false;
1874 }
1875
1876 if (!ValidateRobustEntryPoint(context, bufSize))
1877 {
1878 return false;
1879 }
1880
1881 if (!ValidateIndexedStateQuery(context, target, index, length))
1882 {
1883 return false;
1884 }
1885
1886 if (!ValidateRobustBufferSize(context, bufSize, *length))
1887 {
1888 return false;
1889 }
1890
1891 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001892}
1893
Jamie Madillc29968b2016-01-20 11:17:23 -05001894} // namespace gl