blob: 6084c94e978ac3f278fca98fe8c98ed681d54b52 [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{
346 GLenum mEffectiveFormat;
347 GLenum mDestFormat;
348 GLuint mMinRedBits;
349 GLuint mMaxRedBits;
350 GLuint mMinGreenBits;
351 GLuint mMaxGreenBits;
352 GLuint mMinBlueBits;
353 GLuint mMaxBlueBits;
354 GLuint mMinAlphaBits;
355 GLuint mMaxAlphaBits;
356
357 EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
358 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
359 GLuint minAlphaBits, GLuint maxAlphaBits)
360 : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
361 mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
362 mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
363 mMaxAlphaBits(maxAlphaBits) {};
364};
365
366typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
367
368static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
369{
370 EffectiveInternalFormatList list;
371
372 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
373 // linear source buffer component sizes.
374 // | Source channel min/max sizes |
375 // Effective Internal Format | N/A | R | G | B | A |
376 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
377 list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
378 list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
379 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
380 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
381 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
382 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
383 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
384 list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
385
386 return list;
387}
388
389static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
390{
391 EffectiveInternalFormatList list;
392
393 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
394 // linear source buffer component sizes.
395 // | Source channel min/max sizes |
396 // Effective Internal Format | Dest Format | R | G | B | A |
397 list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
398 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
399 list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
400 list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
401 list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
402 list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
403 list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
404 list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
405
406 return list;
407}
408
409static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
410 GLenum *outEffectiveFormat)
411{
412 const EffectiveInternalFormatList *list = NULL;
413 GLenum targetFormat = GL_NONE;
414
415 if (destFormat.pixelBytes > 0)
416 {
417 static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
418 list = &sizedList;
419 }
420 else
421 {
422 static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
423 list = &unsizedList;
424 targetFormat = destFormat.format;
425 }
426
427 for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
428 {
429 const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
430 if ((formatInfo.mDestFormat == targetFormat) &&
431 (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
432 (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
433 (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
434 (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
435 {
436 *outEffectiveFormat = formatInfo.mEffectiveFormat;
437 return true;
438 }
439 }
440
441 return false;
442}
443
444struct CopyConversion
445{
446 GLenum mTextureFormat;
447 GLenum mFramebufferFormat;
448
449 CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
450 : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
451
452 bool operator<(const CopyConversion& other) const
453 {
454 return memcmp(this, &other, sizeof(CopyConversion)) < 0;
455 }
456};
457
458typedef std::set<CopyConversion> CopyConversionSet;
459
460static CopyConversionSet BuildValidES3CopyTexImageCombinations()
461{
462 CopyConversionSet set;
463
464 // From ES 3.0.1 spec, table 3.15
465 set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
466 set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
467 set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
468 set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
469 set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
470 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
471 set.insert(CopyConversion(GL_RED, GL_RED));
472 set.insert(CopyConversion(GL_RED, GL_RG));
473 set.insert(CopyConversion(GL_RED, GL_RGB));
474 set.insert(CopyConversion(GL_RED, GL_RGBA));
475 set.insert(CopyConversion(GL_RG, GL_RG));
476 set.insert(CopyConversion(GL_RG, GL_RGB));
477 set.insert(CopyConversion(GL_RG, GL_RGBA));
478 set.insert(CopyConversion(GL_RGB, GL_RGB));
479 set.insert(CopyConversion(GL_RGB, GL_RGBA));
480 set.insert(CopyConversion(GL_RGBA, GL_RGBA));
481
482 // Necessary for ANGLE back-buffers
483 set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
484 set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
485 set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
486 set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
487 set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
488 set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
489 set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
Geoff Lang4e58af62016-08-26 10:56:52 -0400490 set.insert(CopyConversion(GL_BGRA_EXT, GL_BGRA_EXT));
Geoff Lang5d601382014-07-22 15:14:06 -0400491
492 set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
493 set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
494 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
495 set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
496 set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
497 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
498 set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
499 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
500 set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
501 set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
502
503 return set;
504}
505
Corentin Wallez76287682016-04-25 09:23:38 -0400506static bool EqualOrFirstZero(GLuint first, GLuint second)
507{
508 return first == 0 || first == second;
509}
510
Jamie Madill0c8abca2016-07-22 20:21:26 -0400511static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
512 const Format &framebufferFormat,
513 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400514{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400515 const auto &textureFormatInfo = *textureFormat.info;
516 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400517
518 static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400519 if (conversionSet.find(CopyConversion(textureFormatInfo.format,
520 framebufferFormatInfo.format)) != conversionSet.end())
Geoff Lang5d601382014-07-22 15:14:06 -0400521 {
522 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
523 // must both be signed, unsigned, or fixed point and both source and destinations
524 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
525 // conversion between fixed and floating point.
526
Jamie Madill0c8abca2016-07-22 20:21:26 -0400527 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
528 (framebufferFormatInfo.colorEncoding == GL_SRGB))
Geoff Lang5d601382014-07-22 15:14:06 -0400529 {
530 return false;
531 }
532
Jamie Madill0c8abca2016-07-22 20:21:26 -0400533 if (((textureFormatInfo.componentType == GL_INT) !=
534 (framebufferFormatInfo.componentType == GL_INT)) ||
535 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
536 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
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_UNSIGNED_NORMALIZED ||
542 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
543 textureFormatInfo.componentType == GL_FLOAT) &&
544 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
545 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
546 framebufferFormatInfo.componentType == GL_FLOAT))
Geoff Lang5d601382014-07-22 15:14:06 -0400547 {
548 return false;
549 }
550
551 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
552 // The effective internal format of the source buffer is determined with the following rules applied in order:
553 // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
554 // effective internal format is the source buffer's sized internal format.
555 // * If the source buffer is a texture that was created with an unsized base internal format, then the
556 // effective internal format is the source image array's effective internal format, as specified by table
557 // 3.12, which is determined from the <format> and <type> that were used when the source image array was
558 // specified by TexImage*.
559 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
560 // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
561 // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
562 // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
563 // is SRGB.
564 const InternalFormat *sourceEffectiveFormat = NULL;
565 if (readBufferHandle != 0)
566 {
567 // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
Jamie Madill0c8abca2016-07-22 20:21:26 -0400568 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400569 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400570 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400571 }
572 else
573 {
574 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
575 // 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 -0400576 GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
577 framebufferFormatInfo.type);
Geoff Lang051dbc72015-01-05 15:48:58 -0500578 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400579 }
580 }
581 else
582 {
583 // The effective internal format must be derived from the source framebuffer's channel sizes.
584 // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
Jamie Madill0c8abca2016-07-22 20:21:26 -0400585 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400586 {
587 GLenum effectiveFormat;
Jamie Madill0c8abca2016-07-22 20:21:26 -0400588 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
589 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400590 {
591 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
592 }
593 else
594 {
595 return false;
596 }
597 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400598 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
Geoff Lang5d601382014-07-22 15:14:06 -0400599 {
600 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Jamie Madill0c8abca2016-07-22 20:21:26 -0400601 if (textureFormat.sized &&
602 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
603 (framebufferFormatInfo.greenBits >= 1 &&
604 framebufferFormatInfo.greenBits <= 8) &&
605 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
606 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
Geoff Lang5d601382014-07-22 15:14:06 -0400607 {
608 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
609 }
610 else
611 {
612 return false;
613 }
614 }
615 else
616 {
617 UNREACHABLE();
618 return false;
619 }
620 }
621
Jamie Madill0c8abca2016-07-22 20:21:26 -0400622 if (textureFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400623 {
Corentin Wallez76287682016-04-25 09:23:38 -0400624 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
625 // format is sized, component sizes of the source and destination formats must exactly
626 // match if the destination format exists.
Jamie Madill0c8abca2016-07-22 20:21:26 -0400627 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
628 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
629 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
630 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
Geoff Lang5d601382014-07-22 15:14:06 -0400631 {
632 return false;
633 }
634 }
635
Geoff Lang5d601382014-07-22 15:14:06 -0400636 return true; // A conversion function exists, and no rule in the specification has precluded conversion
637 // between these formats.
638 }
639
640 return false;
641}
642
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500643bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
644 GLenum target,
645 GLint level,
646 GLenum internalformat,
647 bool isSubImage,
648 GLint xoffset,
649 GLint yoffset,
650 GLint zoffset,
651 GLint x,
652 GLint y,
653 GLsizei width,
654 GLsizei height,
655 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400657 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400658 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400659 xoffset, yoffset, zoffset, x, y, width, height, border,
660 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400661 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400662 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400663 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400664 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665
Jamie Madill51f40ec2016-06-15 14:06:00 -0400666 const auto &state = context->getGLState();
667 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
668 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400669
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700670 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400671 {
Jamie Madill437fa652016-05-03 15:13:24 -0400672 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400673 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400674 }
675
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700676 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400677 {
Jamie Madill437fa652016-05-03 15:13:24 -0400678 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400679 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400680 }
681
Jamie Madill0c8abca2016-07-22 20:21:26 -0400682 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400683
684 if (isSubImage)
685 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400686 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500687 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688 {
Jamie Madill437fa652016-05-03 15:13:24 -0400689 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400690 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400691 }
692 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400693 else
694 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400695 // Use format/type from the source FBO. (Might not be perfect for all cases?)
696 const auto framebufferFormat = source->getFormat();
697 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
698 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400699 {
Jamie Madill437fa652016-05-03 15:13:24 -0400700 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400701 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400702 }
703 }
704
Geoff Lang784a8fd2013-09-24 12:33:16 -0400705 // If width or height is zero, it is a no-op. Return false without setting an error.
706 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400707}
708
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500709bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
710 GLenum target,
711 GLint level,
712 GLenum internalformat,
713 bool isSubImage,
714 GLint xoffset,
715 GLint yoffset,
716 GLint zoffset,
717 GLint x,
718 GLint y,
719 GLsizei width,
720 GLsizei height,
721 GLint border)
722{
723 if (!ValidTexture2DDestinationTarget(context, target))
724 {
Jamie Madill437fa652016-05-03 15:13:24 -0400725 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500726 return false;
727 }
728
729 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
730 xoffset, yoffset, zoffset, x, y, width, height,
731 border);
732}
733
734bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
735 GLenum target,
736 GLint level,
737 GLenum internalformat,
738 bool isSubImage,
739 GLint xoffset,
740 GLint yoffset,
741 GLint zoffset,
742 GLint x,
743 GLint y,
744 GLsizei width,
745 GLsizei height,
746 GLint border)
747{
748 if (!ValidTexture3DDestinationTarget(context, target))
749 {
Jamie Madill437fa652016-05-03 15:13:24 -0400750 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500751 return false;
752 }
753
754 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
755 xoffset, yoffset, zoffset, x, y, width, height,
756 border);
757}
758
759bool ValidateES3TexStorageParametersBase(Context *context,
760 GLenum target,
761 GLsizei levels,
762 GLenum internalformat,
763 GLsizei width,
764 GLsizei height,
765 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766{
767 if (width < 1 || height < 1 || depth < 1 || levels < 1)
768 {
Jamie Madill437fa652016-05-03 15:13:24 -0400769 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 }
772
Geoff Langb92c1332015-09-04 12:54:55 -0400773 GLsizei maxDim = std::max(width, height);
774 if (target != GL_TEXTURE_2D_ARRAY)
775 {
776 maxDim = std::max(maxDim, depth);
777 }
778
779 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 {
Jamie Madill437fa652016-05-03 15:13:24 -0400781 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400782 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 }
784
Geoff Langaae65a42014-05-26 12:43:44 -0400785 const gl::Caps &caps = context->getCaps();
786
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 switch (target)
788 {
789 case GL_TEXTURE_2D:
790 {
Geoff Langaae65a42014-05-26 12:43:44 -0400791 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
792 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793 {
Jamie Madill437fa652016-05-03 15:13:24 -0400794 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797 }
798 break;
799
Geoff Lang01c21d22013-09-24 11:52:16 -0400800 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 if (width != height)
803 {
Jamie Madill437fa652016-05-03 15:13:24 -0400804 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400805 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 }
807
Geoff Langaae65a42014-05-26 12:43:44 -0400808 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 {
Jamie Madill437fa652016-05-03 15:13:24 -0400810 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400811 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 }
813 }
814 break;
815
816 case GL_TEXTURE_3D:
817 {
Geoff Langaae65a42014-05-26 12:43:44 -0400818 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
819 static_cast<GLuint>(height) > caps.max3DTextureSize ||
820 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 {
Jamie Madill437fa652016-05-03 15:13:24 -0400822 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400823 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 }
825 }
826 break;
827
828 case GL_TEXTURE_2D_ARRAY:
829 {
Geoff Langaae65a42014-05-26 12:43:44 -0400830 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
831 static_cast<GLuint>(height) > caps.max2DTextureSize ||
832 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 {
Jamie Madill437fa652016-05-03 15:13:24 -0400834 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
837 }
838 break;
839
840 default:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500841 UNREACHABLE();
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 }
844
Geoff Lang691e58c2014-12-19 17:03:25 -0500845 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 if (!texture || texture->id() == 0)
847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851
Geoff Lang69cce582015-09-17 13:20:36 -0400852 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 {
Jamie Madill437fa652016-05-03 15:13:24 -0400854 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400855 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400856 }
857
Geoff Lang5d601382014-07-22 15:14:06 -0400858 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Martin Radev1be913c2016-07-11 17:59:16 +0300859 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Jamie Madill437fa652016-05-03 15:13:24 -0400861 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 }
864
Geoff Lang5d601382014-07-22 15:14:06 -0400865 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 {
Jamie Madill437fa652016-05-03 15:13:24 -0400867 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400868 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 }
870
871 return true;
872}
873
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500874bool ValidateES3TexStorage2DParameters(Context *context,
875 GLenum target,
876 GLsizei levels,
877 GLenum internalformat,
878 GLsizei width,
879 GLsizei height,
880 GLsizei depth)
881{
882 if (!ValidTexture2DTarget(context, target))
883 {
Jamie Madill437fa652016-05-03 15:13:24 -0400884 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500885 return false;
886 }
887
888 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
889 height, depth);
890}
891
892bool ValidateES3TexStorage3DParameters(Context *context,
893 GLenum target,
894 GLsizei levels,
895 GLenum internalformat,
896 GLsizei width,
897 GLsizei height,
898 GLsizei depth)
899{
900 if (!ValidTexture3DTarget(context, target))
901 {
Jamie Madill437fa652016-05-03 15:13:24 -0400902 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500903 return false;
904 }
905
906 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
907 height, depth);
908}
909
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500910bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
911{
Martin Radev1be913c2016-07-11 17:59:16 +0300912 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500913 {
Jamie Madill437fa652016-05-03 15:13:24 -0400914 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500915 return false;
916 }
917
918 return ValidateBeginQueryBase(context, target, id);
919}
920
921bool ValidateEndQuery(gl::Context *context, GLenum target)
922{
Martin Radev1be913c2016-07-11 17:59:16 +0300923 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500924 {
Jamie Madill437fa652016-05-03 15:13:24 -0400925 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500926 return false;
927 }
928
929 return ValidateEndQueryBase(context, target);
930}
931
932bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
933{
Martin Radev1be913c2016-07-11 17:59:16 +0300934 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500935 {
Jamie Madill437fa652016-05-03 15:13:24 -0400936 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500937 return false;
938 }
939
940 return ValidateGetQueryivBase(context, target, pname);
941}
942
943bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
944{
Martin Radev1be913c2016-07-11 17:59:16 +0300945 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500946 {
Jamie Madill437fa652016-05-03 15:13:24 -0400947 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500948 return false;
949 }
950
951 return ValidateGetQueryObjectValueBase(context, id, pname);
952}
953
Geoff Langb1196682014-07-23 13:47:29 -0400954bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
Jamie Madill570f7c82014-07-03 10:38:54 -0400955 GLuint texture, GLint level, GLint layer)
956{
Martin Radev1be913c2016-07-11 17:59:16 +0300957 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400958 {
Jamie Madill437fa652016-05-03 15:13:24 -0400959 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400960 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400961 }
962
Jamie Madill55ec3b12014-07-03 10:38:57 -0400963 if (layer < 0)
964 {
Jamie Madill437fa652016-05-03 15:13:24 -0400965 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400966 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400967 }
968
969 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
970 {
971 return false;
972 }
973
974 const gl::Caps &caps = context->getCaps();
975 if (texture != 0)
976 {
977 gl::Texture *tex = context->getTexture(texture);
978 ASSERT(tex);
979
980 switch (tex->getTarget())
981 {
982 case GL_TEXTURE_2D_ARRAY:
983 {
984 if (level > gl::log2(caps.max2DTextureSize))
985 {
Jamie Madill437fa652016-05-03 15:13:24 -0400986 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400987 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400988 }
989
990 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
991 {
Jamie Madill437fa652016-05-03 15:13:24 -0400992 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400993 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400994 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400995 }
996 break;
997
998 case GL_TEXTURE_3D:
999 {
1000 if (level > gl::log2(caps.max3DTextureSize))
1001 {
Jamie Madill437fa652016-05-03 15:13:24 -04001002 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001003 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001004 }
1005
1006 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1007 {
Jamie Madill437fa652016-05-03 15:13:24 -04001008 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001009 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001010 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001011 }
1012 break;
1013
1014 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001015 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001017 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001018
Jamie Madilla3944d42016-07-22 22:13:26 -04001019 const auto &format = tex->getFormat(tex->getTarget(), level);
1020 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001021 {
Jamie Madill437fa652016-05-03 15:13:24 -04001022 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001023 return false;
1024 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001025 }
1026
1027 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001028}
1029
Corentin Walleze0902642014-11-04 12:32:15 -08001030bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
1031 GLenum internalformat, GLsizei width, GLsizei height)
1032{
1033 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
1034 {
1035 return false;
1036 }
1037
1038 //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.
1039 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1040 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
1041 {
Jamie Madill437fa652016-05-03 15:13:24 -04001042 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001043 return false;
1044 }
1045
1046 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1047 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1048 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001051 Error(GL_INVALID_OPERATION,
1052 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001053 return false;
1054 }
1055
1056 return true;
1057}
1058
Austin Kinross08332632015-05-05 13:35:47 -07001059bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
1060 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061{
Martin Radev1be913c2016-07-11 17:59:16 +03001062 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001063 {
Jamie Madill437fa652016-05-03 15:13:24 -04001064 context->handleError(
1065 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001066 return false;
1067 }
1068
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 bool defaultFramebuffer = false;
1070
1071 switch (target)
1072 {
1073 case GL_DRAW_FRAMEBUFFER:
1074 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001075 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1076 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 case GL_READ_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001078 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1079 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 }
1084
Austin Kinross08332632015-05-05 13:35:47 -07001085 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086}
1087
Jamie Madillc29968b2016-01-20 11:17:23 -05001088bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001089{
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001091 {
Jamie Madill437fa652016-05-03 15:13:24 -04001092 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001093 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001094 }
1095
Jamie Madill51f40ec2016-06-15 14:06:00 -04001096 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1097 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001098 {
Jamie Madill437fa652016-05-03 15:13:24 -04001099 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001100 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001101 }
1102
1103 return true;
1104}
1105
Olli Etuaho71dfb362016-03-10 14:04:27 +02001106bool ValidateDrawRangeElements(Context *context,
1107 GLenum mode,
1108 GLuint start,
1109 GLuint end,
1110 GLsizei count,
1111 GLenum type,
1112 const GLvoid *indices,
1113 IndexRange *indexRange)
1114{
Martin Radev1be913c2016-07-11 17:59:16 +03001115 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001116 {
Jamie Madill437fa652016-05-03 15:13:24 -04001117 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001118 return false;
1119 }
1120
1121 if (end < start)
1122 {
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001124 return false;
1125 }
1126
1127 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1128 {
1129 return false;
1130 }
1131
1132 if (indexRange->end > end || indexRange->start < start)
1133 {
1134 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001135 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001136 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1137 return false;
1138 }
1139 return true;
1140}
1141
Geoff Langb1196682014-07-23 13:47:29 -04001142bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001143{
Martin Radev1be913c2016-07-11 17:59:16 +03001144 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001145 {
Jamie Madill437fa652016-05-03 15:13:24 -04001146 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001148 }
1149
Jamie Madill78f41802014-08-25 15:47:55 -04001150 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001151}
1152
Jamie Madillb885e572015-02-03 16:16:04 -05001153bool ValidateReadBuffer(Context *context, GLenum src)
1154{
Martin Radev1be913c2016-07-11 17:59:16 +03001155 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001156 {
Jamie Madill437fa652016-05-03 15:13:24 -04001157 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001158 return false;
1159 }
1160
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001161 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001162
1163 if (readFBO == nullptr)
1164 {
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001166 return false;
1167 }
1168
1169 if (src == GL_NONE)
1170 {
1171 return true;
1172 }
1173
Olli Etuaho84c9f592016-03-09 14:37:25 +02001174 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001175 {
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001177 return false;
1178 }
1179
1180 if (readFBO->id() == 0)
1181 {
1182 if (src != GL_BACK)
1183 {
1184 const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001185 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001186 return false;
1187 }
1188 }
1189 else
1190 {
1191 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1192
1193 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1194 {
1195 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001196 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001197 return false;
1198 }
1199 }
1200
1201 return true;
1202}
1203
Jamie Madill86af3d22015-07-21 15:14:07 -04001204bool ValidateCompressedTexImage3D(Context *context,
1205 GLenum target,
1206 GLint level,
1207 GLenum internalformat,
1208 GLsizei width,
1209 GLsizei height,
1210 GLsizei depth,
1211 GLint border,
1212 GLsizei imageSize,
1213 const GLvoid *data)
1214{
Martin Radev1be913c2016-07-11 17:59:16 +03001215 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001216 {
Jamie Madill437fa652016-05-03 15:13:24 -04001217 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001218 return false;
1219 }
1220
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001221 if (!ValidTextureTarget(context, target))
1222 {
1223 context->handleError(Error(GL_INVALID_ENUM));
1224 return false;
1225 }
1226
Jamie Madille2e406c2016-06-02 13:04:10 -04001227 // Validate image size
1228 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1229 {
1230 context->handleError(Error(GL_INVALID_VALUE));
1231 return false;
1232 }
1233
Jamie Madill86af3d22015-07-21 15:14:07 -04001234 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001235 if (!formatInfo.compressed)
1236 {
1237 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1238 return false;
1239 }
1240
Jamie Madill513558d2016-06-02 13:04:11 -04001241 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001242 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001243 if (blockSizeOrErr.isError())
1244 {
Jamie Madill513558d2016-06-02 13:04:11 -04001245 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001246 return false;
1247 }
1248 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001249 {
Jamie Madill437fa652016-05-03 15:13:24 -04001250 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001251 return false;
1252 }
1253
1254 // 3D texture target validation
1255 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1256 {
Jamie Madill437fa652016-05-03 15:13:24 -04001257 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001258 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1259 return false;
1260 }
1261
1262 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001263 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1264 0, width, height, depth, border, GL_NONE, GL_NONE, data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001265 {
1266 return false;
1267 }
1268
1269 return true;
1270}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001271
1272bool ValidateBindVertexArray(Context *context, GLuint array)
1273{
Martin Radev1be913c2016-07-11 17:59:16 +03001274 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001275 {
Jamie Madill437fa652016-05-03 15:13:24 -04001276 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001277 return false;
1278 }
1279
1280 return ValidateBindVertexArrayBase(context, array);
1281}
1282
Austin Kinrossbc781f32015-10-26 09:27:38 -07001283bool ValidateIsVertexArray(Context *context)
1284{
Martin Radev1be913c2016-07-11 17:59:16 +03001285 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001286 {
Jamie Madill437fa652016-05-03 15:13:24 -04001287 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001288 return false;
1289 }
1290
1291 return true;
1292}
Geoff Langc5629752015-12-07 16:29:04 -05001293
1294bool ValidateProgramBinary(Context *context,
1295 GLuint program,
1296 GLenum binaryFormat,
1297 const void *binary,
1298 GLint length)
1299{
Martin Radev1be913c2016-07-11 17:59:16 +03001300 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001301 {
Jamie Madill437fa652016-05-03 15:13:24 -04001302 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001303 return false;
1304 }
1305
1306 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1307}
1308
1309bool ValidateGetProgramBinary(Context *context,
1310 GLuint program,
1311 GLsizei bufSize,
1312 GLsizei *length,
1313 GLenum *binaryFormat,
1314 void *binary)
1315{
Martin Radev1be913c2016-07-11 17:59:16 +03001316 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001317 {
Jamie Madill437fa652016-05-03 15:13:24 -04001318 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001319 return false;
1320 }
1321
1322 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1323}
1324
Olli Etuahof0fee072016-03-30 15:11:58 +03001325bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001326{
Martin Radev1be913c2016-07-11 17:59:16 +03001327 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001330 return false;
1331 }
1332
1333 if (GetValidProgram(context, program) == nullptr)
1334 {
1335 return false;
1336 }
1337
1338 switch (pname)
1339 {
1340 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001341 if (value != GL_FALSE && value != GL_TRUE)
1342 {
Jamie Madill437fa652016-05-03 15:13:24 -04001343 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001344 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1345 return false;
1346 }
Geoff Langc5629752015-12-07 16:29:04 -05001347 break;
1348
1349 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001350 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001351 return false;
1352 }
1353
1354 return true;
1355}
Jamie Madillc29968b2016-01-20 11:17:23 -05001356
1357bool ValidateBlitFramebuffer(Context *context,
1358 GLint srcX0,
1359 GLint srcY0,
1360 GLint srcX1,
1361 GLint srcY1,
1362 GLint dstX0,
1363 GLint dstY0,
1364 GLint dstX1,
1365 GLint dstY1,
1366 GLbitfield mask,
1367 GLenum filter)
1368{
Martin Radev1be913c2016-07-11 17:59:16 +03001369 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001370 {
Jamie Madill437fa652016-05-03 15:13:24 -04001371 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001372 return false;
1373 }
1374
1375 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1376 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377}
Jamie Madillc29968b2016-01-20 11:17:23 -05001378
1379bool ValidateClearBufferiv(ValidationContext *context,
1380 GLenum buffer,
1381 GLint drawbuffer,
1382 const GLint *value)
1383{
1384 switch (buffer)
1385 {
1386 case GL_COLOR:
1387 if (drawbuffer < 0 ||
1388 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001391 return false;
1392 }
1393 break;
1394
1395 case GL_STENCIL:
1396 if (drawbuffer != 0)
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 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001405 return false;
1406 }
1407
1408 return ValidateClearBuffer(context);
1409}
1410
1411bool ValidateClearBufferuiv(ValidationContext *context,
1412 GLenum buffer,
1413 GLint drawbuffer,
1414 const GLuint *value)
1415{
1416 switch (buffer)
1417 {
1418 case GL_COLOR:
1419 if (drawbuffer < 0 ||
1420 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1421 {
Jamie Madill437fa652016-05-03 15:13:24 -04001422 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001423 return false;
1424 }
1425 break;
1426
1427 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001429 return false;
1430 }
1431
1432 return ValidateClearBuffer(context);
1433}
1434
1435bool ValidateClearBufferfv(ValidationContext *context,
1436 GLenum buffer,
1437 GLint drawbuffer,
1438 const GLfloat *value)
1439{
1440 switch (buffer)
1441 {
1442 case GL_COLOR:
1443 if (drawbuffer < 0 ||
1444 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001447 return false;
1448 }
1449 break;
1450
1451 case GL_DEPTH:
1452 if (drawbuffer != 0)
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 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001460 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001461 return false;
1462 }
1463
1464 return ValidateClearBuffer(context);
1465}
1466
1467bool ValidateClearBufferfi(ValidationContext *context,
1468 GLenum buffer,
1469 GLint drawbuffer,
1470 GLfloat depth,
1471 GLint stencil)
1472{
1473 switch (buffer)
1474 {
1475 case GL_DEPTH_STENCIL:
1476 if (drawbuffer != 0)
1477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001479 return false;
1480 }
1481 break;
1482
1483 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001484 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001485 return false;
1486 }
1487
1488 return ValidateClearBuffer(context);
1489}
1490
1491bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1492{
Martin Radev1be913c2016-07-11 17:59:16 +03001493 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 {
Jamie Madill437fa652016-05-03 15:13:24 -04001495 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001496 return false;
1497 }
1498
1499 return ValidateDrawBuffersBase(context, n, bufs);
1500}
1501
1502bool ValidateCopyTexSubImage3D(Context *context,
1503 GLenum target,
1504 GLint level,
1505 GLint xoffset,
1506 GLint yoffset,
1507 GLint zoffset,
1508 GLint x,
1509 GLint y,
1510 GLsizei width,
1511 GLsizei height)
1512{
Martin Radev1be913c2016-07-11 17:59:16 +03001513 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001514 {
Jamie Madill437fa652016-05-03 15:13:24 -04001515 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001516 return false;
1517 }
1518
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001519 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1520 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001521}
1522
Jamie Madill73a84962016-02-12 09:27:23 -05001523bool ValidateTexImage3D(Context *context,
1524 GLenum target,
1525 GLint level,
1526 GLint internalformat,
1527 GLsizei width,
1528 GLsizei height,
1529 GLsizei depth,
1530 GLint border,
1531 GLenum format,
1532 GLenum type,
1533 const GLvoid *pixels)
1534{
Martin Radev1be913c2016-07-11 17:59:16 +03001535 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001538 return false;
1539 }
1540
1541 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1542 0, 0, width, height, depth, border, format, type,
1543 pixels);
1544}
1545
1546bool ValidateTexSubImage3D(Context *context,
1547 GLenum target,
1548 GLint level,
1549 GLint xoffset,
1550 GLint yoffset,
1551 GLint zoffset,
1552 GLsizei width,
1553 GLsizei height,
1554 GLsizei depth,
1555 GLenum format,
1556 GLenum type,
1557 const GLvoid *pixels)
1558{
Martin Radev1be913c2016-07-11 17:59:16 +03001559 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001560 {
Jamie Madill437fa652016-05-03 15:13:24 -04001561 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001562 return false;
1563 }
1564
1565 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1566 yoffset, zoffset, width, height, depth, 0, format, type,
1567 pixels);
1568}
1569
1570bool ValidateCompressedTexSubImage3D(Context *context,
1571 GLenum target,
1572 GLint level,
1573 GLint xoffset,
1574 GLint yoffset,
1575 GLint zoffset,
1576 GLsizei width,
1577 GLsizei height,
1578 GLsizei depth,
1579 GLenum format,
1580 GLsizei imageSize,
1581 const GLvoid *data)
1582{
Martin Radev1be913c2016-07-11 17:59:16 +03001583 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001584 {
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001586 return false;
1587 }
1588
1589 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001590 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001591 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001592 if (blockSizeOrErr.isError())
1593 {
1594 context->handleError(blockSizeOrErr.getError());
1595 return false;
1596 }
1597 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001600 return false;
1601 }
1602
1603 if (!data)
1604 {
Jamie Madill437fa652016-05-03 15:13:24 -04001605 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001606 return false;
1607 }
1608
1609 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
1610 width, height, depth, 0, GL_NONE, GL_NONE, data);
1611}
1612
Olli Etuaho41997e72016-03-10 13:38:39 +02001613bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1614{
1615 return ValidateGenOrDeleteES3(context, n);
1616}
1617
1618bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1619{
1620 return ValidateGenOrDeleteES3(context, n);
1621}
1622
1623bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1624{
1625 return ValidateGenOrDeleteCountES3(context, count);
1626}
1627
1628bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1629{
1630 return ValidateGenOrDeleteCountES3(context, count);
1631}
1632
1633bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1634{
1635 return ValidateGenOrDeleteES3(context, n);
1636}
1637
1638bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1639{
1640 if (!ValidateGenOrDeleteES3(context, n))
1641 {
1642 return false;
1643 }
1644 for (GLint i = 0; i < n; ++i)
1645 {
1646 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1647 if (transformFeedback != nullptr && transformFeedback->isActive())
1648 {
1649 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001650 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001651 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1652 return false;
1653 }
1654 }
1655 return true;
1656}
1657
1658bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1659{
1660 return ValidateGenOrDeleteES3(context, n);
1661}
1662
1663bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1664{
1665 return ValidateGenOrDeleteES3(context, n);
1666}
1667
1668bool ValidateGenOrDeleteES3(Context *context, GLint n)
1669{
Martin Radev1be913c2016-07-11 17:59:16 +03001670 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001671 {
Jamie Madill437fa652016-05-03 15:13:24 -04001672 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001673 return false;
1674 }
1675 return ValidateGenOrDelete(context, n);
1676}
1677
1678bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1679{
Martin Radev1be913c2016-07-11 17:59:16 +03001680 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001681 {
Jamie Madill437fa652016-05-03 15:13:24 -04001682 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001683 return false;
1684 }
1685 if (count < 0)
1686 {
Jamie Madill437fa652016-05-03 15:13:24 -04001687 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001688 return false;
1689 }
1690 return true;
1691}
1692
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001693bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1694{
Martin Radev1be913c2016-07-11 17:59:16 +03001695 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001696 {
Jamie Madill437fa652016-05-03 15:13:24 -04001697 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001698 return false;
1699 }
1700 switch (primitiveMode)
1701 {
1702 case GL_TRIANGLES:
1703 case GL_LINES:
1704 case GL_POINTS:
1705 break;
1706
1707 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001709 return false;
1710 }
1711
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001712 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001713 ASSERT(transformFeedback != nullptr);
1714
1715 if (transformFeedback->isActive())
1716 {
Jamie Madill437fa652016-05-03 15:13:24 -04001717 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001718 return false;
1719 }
1720 return true;
1721}
1722
Olli Etuaho37477912016-03-30 14:54:40 +03001723bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
1724{
Martin Radev1be913c2016-07-11 17:59:16 +03001725 if (context->getClientMajorVersion() < 3)
Olli Etuaho37477912016-03-30 14:54:40 +03001726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho37477912016-03-30 14:54:40 +03001728 return false;
1729 }
1730
1731 if (!context->isSampler(sampler))
1732 {
Jamie Madill437fa652016-05-03 15:13:24 -04001733 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho37477912016-03-30 14:54:40 +03001734 return false;
1735 }
1736
1737 if (!ValidateSamplerObjectParameter(context, pname))
1738 {
1739 return false;
1740 }
1741
Ian Ewellbda75592016-04-18 17:25:54 -04001742 if (!ValidateTexParamParameters(context, GL_TEXTURE_2D, pname, param))
Olli Etuaho37477912016-03-30 14:54:40 +03001743 {
1744 return false;
1745 }
1746 return true;
1747}
1748
1749bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
1750{
1751 // The only float parameters are MIN_LOD and MAX_LOD. For these any value is permissible, so
1752 // ValidateSamplerParameteri can be used for validation here.
1753 return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
1754}
1755
Olli Etuaho4f667482016-03-30 15:56:35 +03001756bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1757{
Martin Radev1be913c2016-07-11 17:59:16 +03001758 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001761 return false;
1762 }
1763
1764 return ValidateGetBufferPointervBase(context, target, pname, params);
1765}
1766
1767bool ValidateUnmapBuffer(Context *context, GLenum target)
1768{
Martin Radev1be913c2016-07-11 17:59:16 +03001769 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001772 return false;
1773 }
1774
1775 return ValidateUnmapBufferBase(context, target);
1776}
1777
1778bool ValidateMapBufferRange(Context *context,
1779 GLenum target,
1780 GLintptr offset,
1781 GLsizeiptr length,
1782 GLbitfield access)
1783{
Martin Radev1be913c2016-07-11 17:59:16 +03001784 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001785 {
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001787 return false;
1788 }
1789
1790 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1791}
1792
1793bool ValidateFlushMappedBufferRange(Context *context,
1794 GLenum target,
1795 GLintptr offset,
1796 GLsizeiptr length)
1797{
Martin Radev1be913c2016-07-11 17:59:16 +03001798 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001799 {
Jamie Madill437fa652016-05-03 15:13:24 -04001800 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001801 return false;
1802 }
1803
1804 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1805}
1806
Martin Radev66fb8202016-07-28 11:45:20 +03001807bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
1808{
1809 GLenum nativeType;
1810 unsigned int numParams;
1811 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1812 {
1813 context->handleError(Error(GL_INVALID_ENUM));
1814 return false;
1815 }
1816
1817 const Caps &caps = context->getCaps();
1818 switch (pname)
1819 {
1820 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1821 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1822 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1823 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1824 {
1825 context->handleError(Error(GL_INVALID_VALUE));
1826 return false;
1827 }
1828 break;
1829
1830 case GL_UNIFORM_BUFFER_START:
1831 case GL_UNIFORM_BUFFER_SIZE:
1832 case GL_UNIFORM_BUFFER_BINDING:
1833 if (index >= caps.maxUniformBufferBindings)
1834 {
1835 context->handleError(Error(GL_INVALID_VALUE));
1836 return false;
1837 }
1838 break;
1839 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1840 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1841 if (index >= 3u)
1842 {
1843 context->handleError(Error(GL_INVALID_VALUE));
1844 return false;
1845 }
1846 break;
1847 default:
1848 context->handleError(Error(GL_INVALID_ENUM));
1849 return false;
1850 }
1851
1852 // pname is valid, but there are no parameters to return
1853 if (numParams == 0)
1854 {
1855 return false;
1856 }
1857
1858 return true;
1859}
1860
1861bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1862{
1863 if (!context->getGLVersion().isES3OrGreater())
1864 {
1865 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1866 return false;
1867 }
1868 return ValidateIndexedStateQuery(context, target, index);
1869}
1870
1871bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1872{
1873 if (!context->getGLVersion().isES3OrGreater())
1874 {
1875 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1876 return false;
1877 }
1878 return ValidateIndexedStateQuery(context, target, index);
1879}
1880
Jamie Madillc29968b2016-01-20 11:17:23 -05001881} // namespace gl