blob: e2384aaf174446c93708eaa26aad1ae2511a44f3 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madilld2f0c742016-11-02 10:34:41 -040011#include "base/numerics/safe_conversions.h"
12#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/validationES.h"
15#include "libANGLE/Context.h"
16#include "libANGLE/Texture.h"
17#include "libANGLE/Framebuffer.h"
18#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
He Yunchaoced53ae2016-11-29 15:00:51 +080027static bool ValidateTexImageFormatCombination(gl::Context *context,
28 GLenum internalFormat,
29 GLenum format,
30 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040031{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050032 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
33 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
34 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
35 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -040036 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Langeb66a6e2016-10-31 13:06:12 -040037 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -040038 {
Jamie Madill437fa652016-05-03 15:13:24 -040039 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040040 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040041 }
42
43 // The type and format are valid if any supported internal format has that type and format
Jamie Madill55e98212016-10-05 16:39:13 -040044 if (!ValidES3Format(format) || !ValidES3Type(type))
Geoff Lang5d601382014-07-22 15:14:06 -040045 {
Jamie Madill437fa652016-05-03 15:13:24 -040046 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -040047 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040048 }
49
50 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040051 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040052 {
Jamie Madill437fa652016-05-03 15:13:24 -040053 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -040054 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040055 }
56
57 return true;
58}
59
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050060bool ValidateES3TexImageParametersBase(Context *context,
61 GLenum target,
62 GLint level,
63 GLenum internalformat,
64 bool isCompressed,
65 bool isSubImage,
66 GLint xoffset,
67 GLint yoffset,
68 GLint zoffset,
69 GLsizei width,
70 GLsizei height,
71 GLsizei depth,
72 GLint border,
73 GLenum format,
74 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -040075 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050076 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040077{
78 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -070079 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040083 }
84
Geoff Lange8ebe7f2013-08-05 15:03:13 -040085 // Verify zero border
86 if (border != 0)
87 {
Jamie Madill437fa652016-05-03 15:13:24 -040088 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040090 }
91
Jamie Madill6f38f822014-06-06 17:12:20 -040092 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
93 std::numeric_limits<GLsizei>::max() - xoffset < width ||
94 std::numeric_limits<GLsizei>::max() - yoffset < height ||
95 std::numeric_limits<GLsizei>::max() - zoffset < depth)
96 {
Jamie Madill437fa652016-05-03 15:13:24 -040097 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040098 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040099 }
100
Geoff Langaae65a42014-05-26 12:43:44 -0400101 const gl::Caps &caps = context->getCaps();
102
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400103 switch (target)
104 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800105 case GL_TEXTURE_2D:
106 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
107 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
108 {
109 context->handleError(Error(GL_INVALID_VALUE));
110 return false;
111 }
112 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400113
He Yunchaoced53ae2016-11-29 15:00:51 +0800114 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
115 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
116 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
117 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
118 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
119 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
120 if (!isSubImage && width != height)
121 {
122 context->handleError(Error(GL_INVALID_VALUE));
123 return false;
124 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400125
He Yunchaoced53ae2016-11-29 15:00:51 +0800126 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
127 {
128 context->handleError(Error(GL_INVALID_VALUE));
129 return false;
130 }
131 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400132
He Yunchaoced53ae2016-11-29 15:00:51 +0800133 case GL_TEXTURE_3D:
134 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
135 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
136 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
137 {
138 context->handleError(Error(GL_INVALID_VALUE));
139 return false;
140 }
141 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400142
He Yunchaoced53ae2016-11-29 15:00:51 +0800143 case GL_TEXTURE_2D_ARRAY:
144 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
145 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
146 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
147 {
148 context->handleError(Error(GL_INVALID_VALUE));
149 return false;
150 }
151 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400152
He Yunchaoced53ae2016-11-29 15:00:51 +0800153 default:
154 context->handleError(Error(GL_INVALID_ENUM));
155 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 }
157
He Yunchaoced53ae2016-11-29 15:00:51 +0800158 gl::Texture *texture =
159 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160 if (!texture)
161 {
Jamie Madill437fa652016-05-03 15:13:24 -0400162 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400163 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400164 }
165
Geoff Lang69cce582015-09-17 13:20:36 -0400166 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400167 {
Jamie Madill437fa652016-05-03 15:13:24 -0400168 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400169 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400170 }
171
172 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400173 GLenum actualInternalFormat =
174 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500175 if (isSubImage && actualInternalFormat == GL_NONE)
176 {
177 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
178 return false;
179 }
180
Geoff Lang5d601382014-07-22 15:14:06 -0400181 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 if (isCompressed)
183 {
tmartino7c102692015-10-02 16:43:40 -0400184 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400185 {
Jamie Madill437fa652016-05-03 15:13:24 -0400186 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400187 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400188 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400189 }
190
Geoff Lang44ff5a72017-02-03 15:15:43 -0500191 if (!ValidCompressedImageSize(context, actualInternalFormat, xoffset, yoffset, width,
192 height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400193 {
Jamie Madill437fa652016-05-03 15:13:24 -0400194 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400195 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400196 }
197
Geoff Langeb66a6e2016-10-31 13:06:12 -0400198 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400199 {
Jamie Madill437fa652016-05-03 15:13:24 -0400200 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400201 return false;
202 }
203
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400204 if (target == GL_TEXTURE_3D)
205 {
Jamie Madill437fa652016-05-03 15:13:24 -0400206 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400207 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400208 }
209 }
210 else
211 {
Geoff Langbaadf232014-08-04 13:58:02 -0400212 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400213 {
Geoff Lang5d601382014-07-22 15:14:06 -0400214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400215 }
216
217 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
218 {
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 }
223
224 // Validate sub image parameters
225 if (isSubImage)
226 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500227 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400228 {
Jamie Madill437fa652016-05-03 15:13:24 -0400229 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400231 }
232
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400233 if (width == 0 || height == 0 || depth == 0)
234 {
235 return false;
236 }
237
238 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
239 {
Jamie Madill437fa652016-05-03 15:13:24 -0400240 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400241 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400242 }
243
244 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
245 std::numeric_limits<GLsizei>::max() - yoffset < height ||
246 std::numeric_limits<GLsizei>::max() - zoffset < depth)
247 {
Jamie Madill437fa652016-05-03 15:13:24 -0400248 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400249 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400250 }
251
Geoff Langa9be0dc2014-12-17 12:34:40 -0500252 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
253 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
254 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 {
Jamie Madill437fa652016-05-03 15:13:24 -0400256 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400257 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258 }
259 }
260
Geoff Langff5b2d52016-09-07 11:32:23 -0400261 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
262 imageSize))
263 {
264 return false;
265 }
266
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400267 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700268 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400269 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400270 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800271 // ...data is not evenly divisible into the number of bytes needed to store in memory a
272 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400273 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400274 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400275 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400276 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400277 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
278
Geoff Langff5b2d52016-09-07 11:32:23 -0400279 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400280 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400281 context->handleError(
282 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400283 return false;
284 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400285 }
286
Jamie Madill7a5f7382014-03-05 15:01:24 -0500287 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700288 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500289 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400290 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400291 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500292 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400293 }
294
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400295 return true;
296}
297
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500298bool ValidateES3TexImage2DParameters(Context *context,
299 GLenum target,
300 GLint level,
301 GLenum internalformat,
302 bool isCompressed,
303 bool isSubImage,
304 GLint xoffset,
305 GLint yoffset,
306 GLint zoffset,
307 GLsizei width,
308 GLsizei height,
309 GLsizei depth,
310 GLint border,
311 GLenum format,
312 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400313 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500314 const GLvoid *pixels)
315{
316 if (!ValidTexture2DDestinationTarget(context, target))
317 {
Jamie Madill437fa652016-05-03 15:13:24 -0400318 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500319 return false;
320 }
321
322 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
323 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400324 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500325}
326
327bool ValidateES3TexImage3DParameters(Context *context,
328 GLenum target,
329 GLint level,
330 GLenum internalformat,
331 bool isCompressed,
332 bool isSubImage,
333 GLint xoffset,
334 GLint yoffset,
335 GLint zoffset,
336 GLsizei width,
337 GLsizei height,
338 GLsizei depth,
339 GLint border,
340 GLenum format,
341 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400342 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500343 const GLvoid *pixels)
344{
345 if (!ValidTexture3DDestinationTarget(context, target))
346 {
Jamie Madill437fa652016-05-03 15:13:24 -0400347 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500348 return false;
349 }
350
351 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
352 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400353 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500354}
355
Geoff Lang5d601382014-07-22 15:14:06 -0400356struct EffectiveInternalFormatInfo
357{
Jamie Madill76648fe2016-10-05 17:01:41 -0400358 GLenum effectiveFormat;
359 GLenum destFormat;
360 GLuint minRedBits;
361 GLuint maxRedBits;
362 GLuint minGreenBits;
363 GLuint maxGreenBits;
364 GLuint minBlueBits;
365 GLuint maxBlueBits;
366 GLuint minAlphaBits;
367 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400368};
369
Jamie Madill76648fe2016-10-05 17:01:41 -0400370static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
371 GLenum targetFormat,
372 const EffectiveInternalFormatInfo *list,
373 size_t size,
374 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400375{
Jamie Madill76648fe2016-10-05 17:01:41 -0400376 for (size_t curFormat = 0; curFormat < size; ++curFormat)
377 {
378 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
379 if ((formatInfo.destFormat == targetFormat) &&
380 (formatInfo.minRedBits <= srcFormat.redBits &&
381 formatInfo.maxRedBits >= srcFormat.redBits) &&
382 (formatInfo.minGreenBits <= srcFormat.greenBits &&
383 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
384 (formatInfo.minBlueBits <= srcFormat.blueBits &&
385 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
386 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
387 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
388 {
389 *outEffectiveFormat = formatInfo.effectiveFormat;
390 return true;
391 }
392 }
Geoff Lang5d601382014-07-22 15:14:06 -0400393
Jamie Madill76648fe2016-10-05 17:01:41 -0400394 *outEffectiveFormat = GL_NONE;
395 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400396}
397
Jamie Madill76648fe2016-10-05 17:01:41 -0400398bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
399 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400400{
Jamie Madill76648fe2016-10-05 17:01:41 -0400401 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
402 // Effective internal format coresponding to destination internal format and linear source
403 // buffer component sizes.
404 // | Source channel min/max sizes |
405 // Effective Internal Format | N/A | R | G | B | A |
406 // clang-format off
407 constexpr EffectiveInternalFormatInfo list[] = {
408 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
409 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
410 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
411 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
412 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
413 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
414 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
415 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
416 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
417 };
418 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400419
Jamie Madill76648fe2016-10-05 17:01:41 -0400420 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
421}
Geoff Lang5d601382014-07-22 15:14:06 -0400422
Jamie Madill76648fe2016-10-05 17:01:41 -0400423bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
424 const InternalFormat &destFormat,
425 GLenum *outEffectiveFormat)
426{
427 constexpr GLuint umax = UINT_MAX;
428
429 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
430 // Effective internal format coresponding to destination internal format andlinear source buffer
431 // component sizes.
432 // | Source channel min/max sizes |
433 // Effective Internal Format | Dest Format | R | G | B | A |
434 // clang-format off
435 constexpr EffectiveInternalFormatInfo list[] = {
436 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
437 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
438 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
439 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
440 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
441 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
442 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
443 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
444 };
445 // clang-format on
446
447 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
448 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400449}
450
He Yunchaoced53ae2016-11-29 15:00:51 +0800451static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
452 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400453 GLenum *outEffectiveFormat)
454{
Geoff Lang5d601382014-07-22 15:14:06 -0400455 if (destFormat.pixelBytes > 0)
456 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400457 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400458 }
459 else
460 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400461 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400462 }
Geoff Lang5d601382014-07-22 15:14:06 -0400463}
464
Corentin Wallez76287682016-04-25 09:23:38 -0400465static bool EqualOrFirstZero(GLuint first, GLuint second)
466{
467 return first == 0 || first == second;
468}
469
Jamie Madill0c8abca2016-07-22 20:21:26 -0400470static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
471 const Format &framebufferFormat,
472 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400473{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400474 const auto &textureFormatInfo = *textureFormat.info;
475 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400476
Jamie Madill21b786b2016-11-01 17:41:31 -0400477 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400478 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400479 return false;
480 }
Geoff Lang5d601382014-07-22 15:14:06 -0400481
Jamie Madill21b786b2016-11-01 17:41:31 -0400482 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
483 // must both be signed, unsigned, or fixed point and both source and destinations
484 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
485 // conversion between fixed and floating point.
486
487 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
488 (framebufferFormatInfo.colorEncoding == GL_SRGB))
489 {
490 return false;
491 }
492
493 if (((textureFormatInfo.componentType == GL_INT) !=
494 (framebufferFormatInfo.componentType == GL_INT)) ||
495 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
496 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
497 {
498 return false;
499 }
500
501 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
502 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
503 textureFormatInfo.componentType == GL_FLOAT) &&
504 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
505 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
506 framebufferFormatInfo.componentType == GL_FLOAT))
507 {
508 return false;
509 }
510
511 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
512 // The effective internal format of the source buffer is determined with the following rules
513 // applied in order:
514 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
515 // format then the effective internal format is the source buffer's sized internal format.
516 // * If the source buffer is a texture that was created with an unsized base internal format,
517 // then the effective internal format is the source image array's effective internal
518 // format, as specified by table 3.12, which is determined from the <format> and <type>
519 // that were used when the source image array was specified by TexImage*.
520 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
521 // where Destination Internal Format matches internalformat and where the [source channel
522 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
523 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
524 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
525 const InternalFormat *sourceEffectiveFormat = NULL;
526 if (readBufferHandle != 0)
527 {
528 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
529 // renderbuffer
530 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400531 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400532 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400533 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400534 else
Geoff Lang5d601382014-07-22 15:14:06 -0400535 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400536 // Renderbuffers cannot be created with an unsized internal format, so this must be an
537 // unsized-format texture. We can use the same table we use when creating textures to
538 // get its effective sized format.
539 GLenum sizedInternalFormat =
540 GetSizedInternalFormat(framebufferFormatInfo.format, framebufferFormatInfo.type);
541 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400542 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400543 }
544 else
545 {
546 // The effective internal format must be derived from the source framebuffer's channel
547 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
548 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400549 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400550 GLenum effectiveFormat;
551 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
552 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400553 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400554 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400555 }
556 else
557 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400558 return false;
559 }
560 }
561 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
562 {
563 // SRGB buffers can only be copied to sized format destinations according to table 3.18
564 if (textureFormat.sized &&
565 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
566 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
567 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
568 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
569 {
570 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
571 }
572 else
573 {
574 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400575 }
576 }
577 else
578 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400579 UNREACHABLE();
580 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400581 }
Geoff Lang5d601382014-07-22 15:14:06 -0400582 }
583
Jamie Madill21b786b2016-11-01 17:41:31 -0400584 if (textureFormat.sized)
585 {
586 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
587 // sized, component sizes of the source and destination formats must exactly match if the
588 // destination format exists.
589 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
590 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
591 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
592 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
593 {
594 return false;
595 }
596 }
597
598 return true; // A conversion function exists, and no rule in the specification has precluded
599 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400600}
601
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500602bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
603 GLenum target,
604 GLint level,
605 GLenum internalformat,
606 bool isSubImage,
607 GLint xoffset,
608 GLint yoffset,
609 GLint zoffset,
610 GLint x,
611 GLint y,
612 GLsizei width,
613 GLsizei height,
614 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400615{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400616 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400617 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400618 xoffset, yoffset, zoffset, x, y, width, height, border,
619 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400620 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400621 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400622 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400623 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624
Jamie Madill51f40ec2016-06-15 14:06:00 -0400625 const auto &state = context->getGLState();
626 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
627 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400628
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700629 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400630 {
Jamie Madill437fa652016-05-03 15:13:24 -0400631 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400632 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400633 }
634
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700635 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400636 {
Jamie Madill437fa652016-05-03 15:13:24 -0400637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400638 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400639 }
640
Jamie Madill0c8abca2016-07-22 20:21:26 -0400641 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400642
643 if (isSubImage)
644 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400645 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500646 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400647 {
Jamie Madill437fa652016-05-03 15:13:24 -0400648 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400649 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650 }
651 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400652 else
653 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400654 // Use format/type from the source FBO. (Might not be perfect for all cases?)
655 const auto framebufferFormat = source->getFormat();
656 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
657 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400658 {
Jamie Madill437fa652016-05-03 15:13:24 -0400659 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400660 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400661 }
662 }
663
Geoff Lang784a8fd2013-09-24 12:33:16 -0400664 // If width or height is zero, it is a no-op. Return false without setting an error.
665 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400666}
667
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
669 GLenum target,
670 GLint level,
671 GLenum internalformat,
672 bool isSubImage,
673 GLint xoffset,
674 GLint yoffset,
675 GLint zoffset,
676 GLint x,
677 GLint y,
678 GLsizei width,
679 GLsizei height,
680 GLint border)
681{
682 if (!ValidTexture2DDestinationTarget(context, target))
683 {
Jamie Madill437fa652016-05-03 15:13:24 -0400684 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500685 return false;
686 }
687
688 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
689 xoffset, yoffset, zoffset, x, y, width, height,
690 border);
691}
692
693bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
694 GLenum target,
695 GLint level,
696 GLenum internalformat,
697 bool isSubImage,
698 GLint xoffset,
699 GLint yoffset,
700 GLint zoffset,
701 GLint x,
702 GLint y,
703 GLsizei width,
704 GLsizei height,
705 GLint border)
706{
707 if (!ValidTexture3DDestinationTarget(context, target))
708 {
Jamie Madill437fa652016-05-03 15:13:24 -0400709 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500710 return false;
711 }
712
713 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
714 xoffset, yoffset, zoffset, x, y, width, height,
715 border);
716}
717
718bool ValidateES3TexStorageParametersBase(Context *context,
719 GLenum target,
720 GLsizei levels,
721 GLenum internalformat,
722 GLsizei width,
723 GLsizei height,
724 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725{
726 if (width < 1 || height < 1 || depth < 1 || levels < 1)
727 {
Jamie Madill437fa652016-05-03 15:13:24 -0400728 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400729 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400730 }
731
Geoff Langb92c1332015-09-04 12:54:55 -0400732 GLsizei maxDim = std::max(width, height);
733 if (target != GL_TEXTURE_2D_ARRAY)
734 {
735 maxDim = std::max(maxDim, depth);
736 }
737
738 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 {
Jamie Madill437fa652016-05-03 15:13:24 -0400740 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400741 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400742 }
743
Geoff Langaae65a42014-05-26 12:43:44 -0400744 const gl::Caps &caps = context->getCaps();
745
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746 switch (target)
747 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800748 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400749 {
Geoff Langaae65a42014-05-26 12:43:44 -0400750 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
751 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 {
Jamie Madill437fa652016-05-03 15:13:24 -0400753 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400754 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 }
756 }
757 break;
758
He Yunchaoced53ae2016-11-29 15:00:51 +0800759 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 if (width != height)
762 {
Jamie Madill437fa652016-05-03 15:13:24 -0400763 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400764 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400765 }
766
Geoff Langaae65a42014-05-26 12:43:44 -0400767 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 {
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 }
773 break;
774
He Yunchaoced53ae2016-11-29 15:00:51 +0800775 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 {
Geoff Langaae65a42014-05-26 12:43:44 -0400777 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
778 static_cast<GLuint>(height) > caps.max3DTextureSize ||
779 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 {
Jamie Madill437fa652016-05-03 15:13:24 -0400781 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400782 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 }
784 }
785 break;
786
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 {
Geoff Langaae65a42014-05-26 12:43:44 -0400789 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
790 static_cast<GLuint>(height) > caps.max2DTextureSize ||
791 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 {
Jamie Madill437fa652016-05-03 15:13:24 -0400793 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796 }
797 break;
798
He Yunchaoced53ae2016-11-29 15:00:51 +0800799 default:
800 UNREACHABLE();
801 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 }
803
Geoff Lang691e58c2014-12-19 17:03:25 -0500804 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805 if (!texture || texture->id() == 0)
806 {
Jamie Madill437fa652016-05-03 15:13:24 -0400807 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400808 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 }
810
Geoff Lang69cce582015-09-17 13:20:36 -0400811 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 {
Jamie Madill437fa652016-05-03 15:13:24 -0400813 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 }
816
Geoff Lang5d601382014-07-22 15:14:06 -0400817 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400818 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 {
Jamie Madill437fa652016-05-03 15:13:24 -0400820 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400821 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822 }
823
Geoff Lang5d601382014-07-22 15:14:06 -0400824 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 {
Jamie Madill437fa652016-05-03 15:13:24 -0400826 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 }
829
830 return true;
831}
832
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500833bool ValidateES3TexStorage2DParameters(Context *context,
834 GLenum target,
835 GLsizei levels,
836 GLenum internalformat,
837 GLsizei width,
838 GLsizei height,
839 GLsizei depth)
840{
841 if (!ValidTexture2DTarget(context, target))
842 {
Jamie Madill437fa652016-05-03 15:13:24 -0400843 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500844 return false;
845 }
846
847 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
848 height, depth);
849}
850
851bool ValidateES3TexStorage3DParameters(Context *context,
852 GLenum target,
853 GLsizei levels,
854 GLenum internalformat,
855 GLsizei width,
856 GLsizei height,
857 GLsizei depth)
858{
859 if (!ValidTexture3DTarget(context, target))
860 {
Jamie Madill437fa652016-05-03 15:13:24 -0400861 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500862 return false;
863 }
864
865 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
866 height, depth);
867}
868
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500869bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
870{
Martin Radev1be913c2016-07-11 17:59:16 +0300871 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500872 {
Jamie Madill437fa652016-05-03 15:13:24 -0400873 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500874 return false;
875 }
876
877 return ValidateBeginQueryBase(context, target, id);
878}
879
880bool ValidateEndQuery(gl::Context *context, GLenum target)
881{
Martin Radev1be913c2016-07-11 17:59:16 +0300882 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500883 {
Jamie Madill437fa652016-05-03 15:13:24 -0400884 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500885 return false;
886 }
887
888 return ValidateEndQueryBase(context, target);
889}
890
891bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
892{
Martin Radev1be913c2016-07-11 17:59:16 +0300893 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500894 {
Jamie Madill437fa652016-05-03 15:13:24 -0400895 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500896 return false;
897 }
898
Geoff Lang2186c382016-10-14 10:54:54 -0400899 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500900}
901
902bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
903{
Martin Radev1be913c2016-07-11 17:59:16 +0300904 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500905 {
Jamie Madill437fa652016-05-03 15:13:24 -0400906 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500907 return false;
908 }
909
Geoff Lang2186c382016-10-14 10:54:54 -0400910 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500911}
912
He Yunchaoced53ae2016-11-29 15:00:51 +0800913bool ValidateFramebufferTextureLayer(Context *context,
914 GLenum target,
915 GLenum attachment,
916 GLuint texture,
917 GLint level,
918 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400919{
Martin Radev1be913c2016-07-11 17:59:16 +0300920 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400924 }
925
Jamie Madill55ec3b12014-07-03 10:38:57 -0400926 if (layer < 0)
927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400930 }
931
932 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
933 {
934 return false;
935 }
936
937 const gl::Caps &caps = context->getCaps();
938 if (texture != 0)
939 {
940 gl::Texture *tex = context->getTexture(texture);
941 ASSERT(tex);
942
943 switch (tex->getTarget())
944 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800945 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400946 {
947 if (level > gl::log2(caps.max2DTextureSize))
948 {
Jamie Madill437fa652016-05-03 15:13:24 -0400949 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400951 }
952
953 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
954 {
Jamie Madill437fa652016-05-03 15:13:24 -0400955 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400956 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400957 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400958 }
959 break;
960
He Yunchaoced53ae2016-11-29 15:00:51 +0800961 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400962 {
963 if (level > gl::log2(caps.max3DTextureSize))
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 (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
970 {
Jamie Madill437fa652016-05-03 15:13:24 -0400971 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400972 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400973 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400974 }
975 break;
976
He Yunchaoced53ae2016-11-29 15:00:51 +0800977 default:
978 context->handleError(Error(GL_INVALID_OPERATION));
979 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400980 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500981
Jamie Madilla3944d42016-07-22 22:13:26 -0400982 const auto &format = tex->getFormat(tex->getTarget(), level);
983 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500984 {
Jamie Madill437fa652016-05-03 15:13:24 -0400985 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500986 return false;
987 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400988 }
989
990 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -0400991}
992
He Yunchaoced53ae2016-11-29 15:00:51 +0800993bool ValidateES3RenderbufferStorageParameters(gl::Context *context,
994 GLenum target,
995 GLsizei samples,
996 GLenum internalformat,
997 GLsizei width,
998 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -0800999{
He Yunchaoced53ae2016-11-29 15:00:51 +08001000 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
1001 height))
Corentin Walleze0902642014-11-04 12:32:15 -08001002 {
1003 return false;
1004 }
1005
He Yunchaoced53ae2016-11-29 15:00:51 +08001006 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
1007 // format if samples is greater than zero.
Corentin Walleze0902642014-11-04 12:32:15 -08001008 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
1010 samples > 0)
Corentin Walleze0902642014-11-04 12:32:15 -08001011 {
Jamie Madill437fa652016-05-03 15:13:24 -04001012 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001013 return false;
1014 }
1015
1016 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1017 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1018 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1019 {
Jamie Madill437fa652016-05-03 15:13:24 -04001020 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001021 Error(GL_INVALID_OPERATION,
1022 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001023 return false;
1024 }
1025
1026 return true;
1027}
1028
He Yunchaoced53ae2016-11-29 15:00:51 +08001029bool ValidateInvalidateFramebuffer(Context *context,
1030 GLenum target,
1031 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001032 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033{
Martin Radev1be913c2016-07-11 17:59:16 +03001034 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001035 {
Jamie Madill437fa652016-05-03 15:13:24 -04001036 context->handleError(
1037 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001038 return false;
1039 }
1040
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 bool defaultFramebuffer = false;
1042
1043 switch (target)
1044 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001045 case GL_DRAW_FRAMEBUFFER:
1046 case GL_FRAMEBUFFER:
1047 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1048 break;
1049 case GL_READ_FRAMEBUFFER:
1050 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1051 break;
1052 default:
1053 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 }
1056
He Yunchaoced53ae2016-11-29 15:00:51 +08001057 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1058 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059}
1060
Jamie Madillc29968b2016-01-20 11:17:23 -05001061bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001062{
Martin Radev1be913c2016-07-11 17:59:16 +03001063 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001064 {
Jamie Madill437fa652016-05-03 15:13:24 -04001065 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001066 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001067 }
1068
Jamie Madill51f40ec2016-06-15 14:06:00 -04001069 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1070 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001071 {
Jamie Madill437fa652016-05-03 15:13:24 -04001072 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001073 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001074 }
1075
1076 return true;
1077}
1078
Olli Etuaho71dfb362016-03-10 14:04:27 +02001079bool ValidateDrawRangeElements(Context *context,
1080 GLenum mode,
1081 GLuint start,
1082 GLuint end,
1083 GLsizei count,
1084 GLenum type,
1085 const GLvoid *indices,
1086 IndexRange *indexRange)
1087{
Martin Radev1be913c2016-07-11 17:59:16 +03001088 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001089 {
Jamie Madill437fa652016-05-03 15:13:24 -04001090 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001091 return false;
1092 }
1093
1094 if (end < start)
1095 {
Jamie Madill437fa652016-05-03 15:13:24 -04001096 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001097 return false;
1098 }
1099
1100 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1101 {
1102 return false;
1103 }
1104
1105 if (indexRange->end > end || indexRange->start < start)
1106 {
1107 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001108 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001109 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1110 return false;
1111 }
1112 return true;
1113}
1114
He Yunchaoced53ae2016-11-29 15:00:51 +08001115bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001116{
Martin Radev1be913c2016-07-11 17:59:16 +03001117 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001118 {
Jamie Madill437fa652016-05-03 15:13:24 -04001119 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001120 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001121 }
1122
Jamie Madill78f41802014-08-25 15:47:55 -04001123 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001124}
1125
Jamie Madillb885e572015-02-03 16:16:04 -05001126bool ValidateReadBuffer(Context *context, GLenum src)
1127{
Martin Radev1be913c2016-07-11 17:59:16 +03001128 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001129 {
Jamie Madill437fa652016-05-03 15:13:24 -04001130 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001131 return false;
1132 }
1133
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001134 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001135
1136 if (readFBO == nullptr)
1137 {
Jamie Madill437fa652016-05-03 15:13:24 -04001138 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001139 return false;
1140 }
1141
1142 if (src == GL_NONE)
1143 {
1144 return true;
1145 }
1146
Olli Etuaho84c9f592016-03-09 14:37:25 +02001147 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001148 {
Jamie Madill437fa652016-05-03 15:13:24 -04001149 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001150 return false;
1151 }
1152
1153 if (readFBO->id() == 0)
1154 {
1155 if (src != GL_BACK)
1156 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001157 const char *errorMsg =
1158 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001159 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001160 return false;
1161 }
1162 }
1163 else
1164 {
1165 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1166
1167 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1168 {
1169 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001170 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001171 return false;
1172 }
1173 }
1174
1175 return true;
1176}
1177
Jamie Madill86af3d22015-07-21 15:14:07 -04001178bool ValidateCompressedTexImage3D(Context *context,
1179 GLenum target,
1180 GLint level,
1181 GLenum internalformat,
1182 GLsizei width,
1183 GLsizei height,
1184 GLsizei depth,
1185 GLint border,
1186 GLsizei imageSize,
1187 const GLvoid *data)
1188{
Martin Radev1be913c2016-07-11 17:59:16 +03001189 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001190 {
Jamie Madill437fa652016-05-03 15:13:24 -04001191 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001192 return false;
1193 }
1194
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001195 if (!ValidTextureTarget(context, target))
1196 {
1197 context->handleError(Error(GL_INVALID_ENUM));
1198 return false;
1199 }
1200
Jamie Madille2e406c2016-06-02 13:04:10 -04001201 // Validate image size
1202 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1203 {
1204 context->handleError(Error(GL_INVALID_VALUE));
1205 return false;
1206 }
1207
Jamie Madill86af3d22015-07-21 15:14:07 -04001208 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001209 if (!formatInfo.compressed)
1210 {
1211 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1212 return false;
1213 }
1214
Jamie Madill513558d2016-06-02 13:04:11 -04001215 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001216 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001217 if (blockSizeOrErr.isError())
1218 {
Jamie Madill513558d2016-06-02 13:04:11 -04001219 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001220 return false;
1221 }
1222 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001223 {
Jamie Madill437fa652016-05-03 15:13:24 -04001224 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001225 return false;
1226 }
1227
1228 // 3D texture target validation
1229 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001232 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1233 return false;
1234 }
1235
1236 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001237 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001238 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1239 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001240 {
1241 return false;
1242 }
1243
1244 return true;
1245}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001246
1247bool ValidateBindVertexArray(Context *context, GLuint array)
1248{
Martin Radev1be913c2016-07-11 17:59:16 +03001249 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001250 {
Jamie Madill437fa652016-05-03 15:13:24 -04001251 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001252 return false;
1253 }
1254
1255 return ValidateBindVertexArrayBase(context, array);
1256}
1257
Austin Kinrossbc781f32015-10-26 09:27:38 -07001258bool ValidateIsVertexArray(Context *context)
1259{
Martin Radev1be913c2016-07-11 17:59:16 +03001260 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001261 {
Jamie Madill437fa652016-05-03 15:13:24 -04001262 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001263 return false;
1264 }
1265
1266 return true;
1267}
Geoff Langc5629752015-12-07 16:29:04 -05001268
1269bool ValidateProgramBinary(Context *context,
1270 GLuint program,
1271 GLenum binaryFormat,
1272 const void *binary,
1273 GLint length)
1274{
Martin Radev1be913c2016-07-11 17:59:16 +03001275 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001276 {
Jamie Madill437fa652016-05-03 15:13:24 -04001277 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001278 return false;
1279 }
1280
1281 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1282}
1283
1284bool ValidateGetProgramBinary(Context *context,
1285 GLuint program,
1286 GLsizei bufSize,
1287 GLsizei *length,
1288 GLenum *binaryFormat,
1289 void *binary)
1290{
Martin Radev1be913c2016-07-11 17:59:16 +03001291 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001292 {
Jamie Madill437fa652016-05-03 15:13:24 -04001293 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001294 return false;
1295 }
1296
1297 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1298}
1299
Olli Etuahof0fee072016-03-30 15:11:58 +03001300bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001301{
Martin Radev1be913c2016-07-11 17:59:16 +03001302 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001303 {
Jamie Madill437fa652016-05-03 15:13:24 -04001304 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001305 return false;
1306 }
1307
1308 if (GetValidProgram(context, program) == nullptr)
1309 {
1310 return false;
1311 }
1312
1313 switch (pname)
1314 {
1315 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001316 if (value != GL_FALSE && value != GL_TRUE)
1317 {
Jamie Madill437fa652016-05-03 15:13:24 -04001318 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001319 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1320 return false;
1321 }
Geoff Langc5629752015-12-07 16:29:04 -05001322 break;
1323
1324 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001325 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001326 return false;
1327 }
1328
1329 return true;
1330}
Jamie Madillc29968b2016-01-20 11:17:23 -05001331
1332bool ValidateBlitFramebuffer(Context *context,
1333 GLint srcX0,
1334 GLint srcY0,
1335 GLint srcX1,
1336 GLint srcY1,
1337 GLint dstX0,
1338 GLint dstY0,
1339 GLint dstX1,
1340 GLint dstY1,
1341 GLbitfield mask,
1342 GLenum filter)
1343{
Martin Radev1be913c2016-07-11 17:59:16 +03001344 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001345 {
Jamie Madill437fa652016-05-03 15:13:24 -04001346 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001347 return false;
1348 }
1349
1350 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1351 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352}
Jamie Madillc29968b2016-01-20 11:17:23 -05001353
1354bool ValidateClearBufferiv(ValidationContext *context,
1355 GLenum buffer,
1356 GLint drawbuffer,
1357 const GLint *value)
1358{
1359 switch (buffer)
1360 {
1361 case GL_COLOR:
1362 if (drawbuffer < 0 ||
1363 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1364 {
Jamie Madill437fa652016-05-03 15:13:24 -04001365 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001366 return false;
1367 }
1368 break;
1369
1370 case GL_STENCIL:
1371 if (drawbuffer != 0)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001374 return false;
1375 }
1376 break;
1377
1378 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001380 return false;
1381 }
1382
1383 return ValidateClearBuffer(context);
1384}
1385
1386bool ValidateClearBufferuiv(ValidationContext *context,
1387 GLenum buffer,
1388 GLint drawbuffer,
1389 const GLuint *value)
1390{
1391 switch (buffer)
1392 {
1393 case GL_COLOR:
1394 if (drawbuffer < 0 ||
1395 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1396 {
Jamie Madill437fa652016-05-03 15:13:24 -04001397 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001398 return false;
1399 }
1400 break;
1401
1402 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001403 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001404 return false;
1405 }
1406
1407 return ValidateClearBuffer(context);
1408}
1409
1410bool ValidateClearBufferfv(ValidationContext *context,
1411 GLenum buffer,
1412 GLint drawbuffer,
1413 const GLfloat *value)
1414{
1415 switch (buffer)
1416 {
1417 case GL_COLOR:
1418 if (drawbuffer < 0 ||
1419 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1420 {
Jamie Madill437fa652016-05-03 15:13:24 -04001421 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001422 return false;
1423 }
1424 break;
1425
1426 case GL_DEPTH:
1427 if (drawbuffer != 0)
1428 {
Jamie Madill437fa652016-05-03 15:13:24 -04001429 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001430 return false;
1431 }
1432 break;
1433
1434 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001436 return false;
1437 }
1438
1439 return ValidateClearBuffer(context);
1440}
1441
1442bool ValidateClearBufferfi(ValidationContext *context,
1443 GLenum buffer,
1444 GLint drawbuffer,
1445 GLfloat depth,
1446 GLint stencil)
1447{
1448 switch (buffer)
1449 {
1450 case GL_DEPTH_STENCIL:
1451 if (drawbuffer != 0)
1452 {
Jamie Madill437fa652016-05-03 15:13:24 -04001453 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001454 return false;
1455 }
1456 break;
1457
1458 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001459 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001460 return false;
1461 }
1462
1463 return ValidateClearBuffer(context);
1464}
1465
1466bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1467{
Martin Radev1be913c2016-07-11 17:59:16 +03001468 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001469 {
Jamie Madill437fa652016-05-03 15:13:24 -04001470 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001471 return false;
1472 }
1473
1474 return ValidateDrawBuffersBase(context, n, bufs);
1475}
1476
1477bool ValidateCopyTexSubImage3D(Context *context,
1478 GLenum target,
1479 GLint level,
1480 GLint xoffset,
1481 GLint yoffset,
1482 GLint zoffset,
1483 GLint x,
1484 GLint y,
1485 GLsizei width,
1486 GLsizei height)
1487{
Martin Radev1be913c2016-07-11 17:59:16 +03001488 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 {
Jamie Madill437fa652016-05-03 15:13:24 -04001490 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001491 return false;
1492 }
1493
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001494 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1495 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001496}
1497
Jamie Madill73a84962016-02-12 09:27:23 -05001498bool ValidateTexImage3D(Context *context,
1499 GLenum target,
1500 GLint level,
1501 GLint internalformat,
1502 GLsizei width,
1503 GLsizei height,
1504 GLsizei depth,
1505 GLint border,
1506 GLenum format,
1507 GLenum type,
1508 const GLvoid *pixels)
1509{
Martin Radev1be913c2016-07-11 17:59:16 +03001510 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001511 {
Jamie Madill437fa652016-05-03 15:13:24 -04001512 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001513 return false;
1514 }
1515
1516 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001517 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001518 pixels);
1519}
1520
Geoff Langc52f6f12016-10-14 10:18:00 -04001521bool ValidateTexImage3DRobustANGLE(Context *context,
1522 GLenum target,
1523 GLint level,
1524 GLint internalformat,
1525 GLsizei width,
1526 GLsizei height,
1527 GLsizei depth,
1528 GLint border,
1529 GLenum format,
1530 GLenum type,
1531 GLsizei bufSize,
1532 const GLvoid *pixels)
1533{
1534 if (context->getClientMajorVersion() < 3)
1535 {
1536 context->handleError(Error(GL_INVALID_OPERATION));
1537 return false;
1538 }
1539
1540 if (!ValidateRobustEntryPoint(context, bufSize))
1541 {
1542 return false;
1543 }
1544
1545 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1546 0, 0, width, height, depth, border, format, type,
1547 bufSize, pixels);
1548}
1549
Jamie Madill73a84962016-02-12 09:27:23 -05001550bool ValidateTexSubImage3D(Context *context,
1551 GLenum target,
1552 GLint level,
1553 GLint xoffset,
1554 GLint yoffset,
1555 GLint zoffset,
1556 GLsizei width,
1557 GLsizei height,
1558 GLsizei depth,
1559 GLenum format,
1560 GLenum type,
1561 const GLvoid *pixels)
1562{
Martin Radev1be913c2016-07-11 17:59:16 +03001563 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001564 {
Jamie Madill437fa652016-05-03 15:13:24 -04001565 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001566 return false;
1567 }
1568
1569 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1570 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001571 -1, pixels);
1572}
1573
1574bool ValidateTexSubImage3DRobustANGLE(Context *context,
1575 GLenum target,
1576 GLint level,
1577 GLint xoffset,
1578 GLint yoffset,
1579 GLint zoffset,
1580 GLsizei width,
1581 GLsizei height,
1582 GLsizei depth,
1583 GLenum format,
1584 GLenum type,
1585 GLsizei bufSize,
1586 const GLvoid *pixels)
1587{
1588 if (context->getClientMajorVersion() < 3)
1589 {
1590 context->handleError(Error(GL_INVALID_OPERATION));
1591 return false;
1592 }
1593
1594 if (!ValidateRobustEntryPoint(context, bufSize))
1595 {
1596 return false;
1597 }
1598
1599 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1600 yoffset, zoffset, width, height, depth, 0, format, type,
1601 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001602}
1603
1604bool ValidateCompressedTexSubImage3D(Context *context,
1605 GLenum target,
1606 GLint level,
1607 GLint xoffset,
1608 GLint yoffset,
1609 GLint zoffset,
1610 GLsizei width,
1611 GLsizei height,
1612 GLsizei depth,
1613 GLenum format,
1614 GLsizei imageSize,
1615 const GLvoid *data)
1616{
Martin Radev1be913c2016-07-11 17:59:16 +03001617 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001618 {
Jamie Madill437fa652016-05-03 15:13:24 -04001619 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001620 return false;
1621 }
1622
1623 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001624 if (!formatInfo.compressed)
1625 {
1626 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1627 return false;
1628 }
1629
Jamie Madill513558d2016-06-02 13:04:11 -04001630 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001631 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001632 if (blockSizeOrErr.isError())
1633 {
1634 context->handleError(blockSizeOrErr.getError());
1635 return false;
1636 }
1637 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001638 {
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001640 return false;
1641 }
1642
1643 if (!data)
1644 {
Jamie Madill437fa652016-05-03 15:13:24 -04001645 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001646 return false;
1647 }
1648
1649 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001650 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001651}
1652
Olli Etuaho41997e72016-03-10 13:38:39 +02001653bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1654{
1655 return ValidateGenOrDeleteES3(context, n);
1656}
1657
1658bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1659{
1660 return ValidateGenOrDeleteES3(context, n);
1661}
1662
1663bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1664{
1665 return ValidateGenOrDeleteCountES3(context, count);
1666}
1667
1668bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1669{
1670 return ValidateGenOrDeleteCountES3(context, count);
1671}
1672
1673bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1674{
1675 return ValidateGenOrDeleteES3(context, n);
1676}
1677
1678bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1679{
1680 if (!ValidateGenOrDeleteES3(context, n))
1681 {
1682 return false;
1683 }
1684 for (GLint i = 0; i < n; ++i)
1685 {
1686 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1687 if (transformFeedback != nullptr && transformFeedback->isActive())
1688 {
1689 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001691 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1692 return false;
1693 }
1694 }
1695 return true;
1696}
1697
1698bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1699{
1700 return ValidateGenOrDeleteES3(context, n);
1701}
1702
1703bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1704{
1705 return ValidateGenOrDeleteES3(context, n);
1706}
1707
1708bool ValidateGenOrDeleteES3(Context *context, GLint n)
1709{
Martin Radev1be913c2016-07-11 17:59:16 +03001710 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001711 {
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001713 return false;
1714 }
1715 return ValidateGenOrDelete(context, n);
1716}
1717
1718bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1719{
Martin Radev1be913c2016-07-11 17:59:16 +03001720 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001721 {
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001723 return false;
1724 }
1725 if (count < 0)
1726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001728 return false;
1729 }
1730 return true;
1731}
1732
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001733bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1734{
Martin Radev1be913c2016-07-11 17:59:16 +03001735 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001736 {
Jamie Madill437fa652016-05-03 15:13:24 -04001737 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001738 return false;
1739 }
1740 switch (primitiveMode)
1741 {
1742 case GL_TRIANGLES:
1743 case GL_LINES:
1744 case GL_POINTS:
1745 break;
1746
1747 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001748 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001749 return false;
1750 }
1751
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001752 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001753 ASSERT(transformFeedback != nullptr);
1754
1755 if (transformFeedback->isActive())
1756 {
Jamie Madill437fa652016-05-03 15:13:24 -04001757 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001758 return false;
1759 }
1760 return true;
1761}
1762
Olli Etuaho4f667482016-03-30 15:56:35 +03001763bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1764{
Geoff Lang496c02d2016-10-20 11:38:11 -07001765 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1766}
1767
1768bool ValidateGetBufferPointervRobustANGLE(Context *context,
1769 GLenum target,
1770 GLenum pname,
1771 GLsizei bufSize,
1772 GLsizei *length,
1773 GLvoid **params)
1774{
1775 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001776 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001777 return false;
1778 }
1779
Geoff Lang496c02d2016-10-20 11:38:11 -07001780 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1781 {
1782 return false;
1783 }
1784
1785 if (!ValidateRobustBufferSize(context, bufSize, *length))
1786 {
1787 return false;
1788 }
1789
1790 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001791}
1792
1793bool ValidateUnmapBuffer(Context *context, GLenum target)
1794{
Martin Radev1be913c2016-07-11 17:59:16 +03001795 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001796 {
Jamie Madill437fa652016-05-03 15:13:24 -04001797 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001798 return false;
1799 }
1800
1801 return ValidateUnmapBufferBase(context, target);
1802}
1803
1804bool ValidateMapBufferRange(Context *context,
1805 GLenum target,
1806 GLintptr offset,
1807 GLsizeiptr length,
1808 GLbitfield access)
1809{
Martin Radev1be913c2016-07-11 17:59:16 +03001810 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001811 {
Jamie Madill437fa652016-05-03 15:13:24 -04001812 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001813 return false;
1814 }
1815
1816 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1817}
1818
1819bool ValidateFlushMappedBufferRange(Context *context,
1820 GLenum target,
1821 GLintptr offset,
1822 GLsizeiptr length)
1823{
Martin Radev1be913c2016-07-11 17:59:16 +03001824 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001827 return false;
1828 }
1829
1830 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1831}
1832
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001833bool ValidateIndexedStateQuery(ValidationContext *context,
1834 GLenum pname,
1835 GLuint index,
1836 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001837{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001838 if (length)
1839 {
1840 *length = 0;
1841 }
1842
Martin Radev66fb8202016-07-28 11:45:20 +03001843 GLenum nativeType;
1844 unsigned int numParams;
1845 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1846 {
1847 context->handleError(Error(GL_INVALID_ENUM));
1848 return false;
1849 }
1850
1851 const Caps &caps = context->getCaps();
1852 switch (pname)
1853 {
1854 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1855 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1856 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1857 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1858 {
1859 context->handleError(Error(GL_INVALID_VALUE));
1860 return false;
1861 }
1862 break;
1863
1864 case GL_UNIFORM_BUFFER_START:
1865 case GL_UNIFORM_BUFFER_SIZE:
1866 case GL_UNIFORM_BUFFER_BINDING:
1867 if (index >= caps.maxUniformBufferBindings)
1868 {
1869 context->handleError(Error(GL_INVALID_VALUE));
1870 return false;
1871 }
1872 break;
1873 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1874 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1875 if (index >= 3u)
1876 {
1877 context->handleError(Error(GL_INVALID_VALUE));
1878 return false;
1879 }
1880 break;
1881 default:
1882 context->handleError(Error(GL_INVALID_ENUM));
1883 return false;
1884 }
1885
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001886 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001887 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001888 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001889 }
1890
1891 return true;
1892}
1893
1894bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1895{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001896 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001897 {
1898 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1899 return false;
1900 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001901 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001902}
1903
Geoff Langcf255ea2016-10-20 11:39:09 -07001904bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
1905 GLenum target,
1906 GLuint index,
1907 GLsizei bufSize,
1908 GLsizei *length,
1909 GLint *data)
1910{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001911 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07001912 {
1913 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1914 return false;
1915 }
1916
1917 if (!ValidateRobustEntryPoint(context, bufSize))
1918 {
1919 return false;
1920 }
1921
1922 if (!ValidateIndexedStateQuery(context, target, index, length))
1923 {
1924 return false;
1925 }
1926
1927 if (!ValidateRobustBufferSize(context, bufSize, *length))
1928 {
1929 return false;
1930 }
1931
1932 return true;
1933}
1934
Martin Radev66fb8202016-07-28 11:45:20 +03001935bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1936{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001937 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001938 {
1939 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1940 return false;
1941 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001942 return ValidateIndexedStateQuery(context, target, index, nullptr);
1943}
1944
1945bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1946 GLenum target,
1947 GLuint index,
1948 GLsizei bufSize,
1949 GLsizei *length,
1950 GLint64 *data)
1951{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001952 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001953 {
1954 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1955 return false;
1956 }
1957
1958 if (!ValidateRobustEntryPoint(context, bufSize))
1959 {
1960 return false;
1961 }
1962
1963 if (!ValidateIndexedStateQuery(context, target, index, length))
1964 {
1965 return false;
1966 }
1967
1968 if (!ValidateRobustBufferSize(context, bufSize, *length))
1969 {
1970 return false;
1971 }
1972
1973 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001974}
1975
Jamie Madillb0817d12016-11-01 15:48:31 -04001976bool ValidateCopyBufferSubData(ValidationContext *context,
1977 GLenum readTarget,
1978 GLenum writeTarget,
1979 GLintptr readOffset,
1980 GLintptr writeOffset,
1981 GLsizeiptr size)
1982{
1983 if (context->getClientMajorVersion() < 3)
1984 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001985 context->handleError(
1986 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001987 return false;
1988 }
1989
1990 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
1991 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001992 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001993 return false;
1994 }
1995
1996 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
1997 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
1998
1999 if (!readBuffer || !writeBuffer)
2000 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002001 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002002 return false;
2003 }
2004
2005 // Verify that readBuffer and writeBuffer are not currently mapped
2006 if (readBuffer->isMapped() || writeBuffer->isMapped())
2007 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002008 context->handleError(
2009 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002010 return false;
2011 }
2012
Jamie Madilld2f0c742016-11-02 10:34:41 -04002013 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2014 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2015 CheckedNumeric<GLintptr> checkedSize(size);
2016
2017 auto checkedReadSum = checkedReadOffset + checkedSize;
2018 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2019
2020 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2021 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2022 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002023 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002024 context->handleError(
2025 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002026 return false;
2027 }
2028
Jamie Madilld2f0c742016-11-02 10:34:41 -04002029 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002030 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002031 context->handleError(
2032 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002033 return false;
2034 }
2035
Jamie Madilld2f0c742016-11-02 10:34:41 -04002036 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2037 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2038 {
2039 context->handleError(
2040 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2041 return false;
2042 }
2043
2044 if (readBuffer == writeBuffer)
2045 {
2046 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2047 if (!checkedOffsetDiff.IsValid())
2048 {
2049 // This shold not be possible.
2050 UNREACHABLE();
2051 context->handleError(
2052 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2053 return false;
2054 }
2055
2056 if (checkedOffsetDiff.ValueOrDie() < size)
2057 {
2058 context->handleError(Error(GL_INVALID_VALUE));
2059 return false;
2060 }
2061 }
2062
Jamie Madillb0817d12016-11-01 15:48:31 -04002063 return true;
2064}
2065
Geoff Langc339c4e2016-11-29 10:37:36 -05002066bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2067{
2068 if (context->getClientMajorVersion() < 3)
2069 {
2070 context->handleError(
2071 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2072 return false;
2073 }
2074
2075 switch (name)
2076 {
2077 case GL_EXTENSIONS:
2078 if (index >= context->getExtensionStringCount())
2079 {
2080 context->handleError(Error(
2081 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2082 return false;
2083 }
2084 break;
2085
2086 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2087 if (!context->getExtensions().requestExtension)
2088 {
2089 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2090 return false;
2091 }
2092 if (index >= context->getRequestableExtensionStringCount())
2093 {
2094 context->handleError(
2095 Error(GL_INVALID_VALUE,
2096 "index must be less than the number of requestable extension strings."));
2097 return false;
2098 }
2099 break;
2100
2101 default:
2102 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2103 return false;
2104 }
2105
2106 return true;
2107}
2108
Jamie Madillc29968b2016-01-20 11:17:23 -05002109} // namespace gl