blob: f5a0aa897d9cb7eb0fa3de31bade1920ff4305b5 [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 ValidateInvalidateFramebuffer(Context *context,
994 GLenum target,
995 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -0700996 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997{
Martin Radev1be913c2016-07-11 17:59:16 +0300998 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -0700999 {
Jamie Madill437fa652016-05-03 15:13:24 -04001000 context->handleError(
1001 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001002 return false;
1003 }
1004
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 bool defaultFramebuffer = false;
1006
1007 switch (target)
1008 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 case GL_DRAW_FRAMEBUFFER:
1010 case GL_FRAMEBUFFER:
1011 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1012 break;
1013 case GL_READ_FRAMEBUFFER:
1014 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1015 break;
1016 default:
1017 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
He Yunchaoced53ae2016-11-29 15:00:51 +08001021 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1022 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023}
1024
Jamie Madillc29968b2016-01-20 11:17:23 -05001025bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001026{
Martin Radev1be913c2016-07-11 17:59:16 +03001027 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001028 {
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001030 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001031 }
1032
Jamie Madill51f40ec2016-06-15 14:06:00 -04001033 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1034 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001035 {
Jamie Madill437fa652016-05-03 15:13:24 -04001036 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001037 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001038 }
1039
1040 return true;
1041}
1042
Olli Etuaho71dfb362016-03-10 14:04:27 +02001043bool ValidateDrawRangeElements(Context *context,
1044 GLenum mode,
1045 GLuint start,
1046 GLuint end,
1047 GLsizei count,
1048 GLenum type,
1049 const GLvoid *indices,
1050 IndexRange *indexRange)
1051{
Martin Radev1be913c2016-07-11 17:59:16 +03001052 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001053 {
Jamie Madill437fa652016-05-03 15:13:24 -04001054 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001055 return false;
1056 }
1057
1058 if (end < start)
1059 {
Jamie Madill437fa652016-05-03 15:13:24 -04001060 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001061 return false;
1062 }
1063
1064 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1065 {
1066 return false;
1067 }
1068
1069 if (indexRange->end > end || indexRange->start < start)
1070 {
1071 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001072 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001073 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1074 return false;
1075 }
1076 return true;
1077}
1078
He Yunchaoced53ae2016-11-29 15:00:51 +08001079bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001080{
Martin Radev1be913c2016-07-11 17:59:16 +03001081 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001082 {
Jamie Madill437fa652016-05-03 15:13:24 -04001083 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001085 }
1086
Jamie Madill78f41802014-08-25 15:47:55 -04001087 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001088}
1089
Jamie Madillb885e572015-02-03 16:16:04 -05001090bool ValidateReadBuffer(Context *context, GLenum src)
1091{
Martin Radev1be913c2016-07-11 17:59:16 +03001092 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001093 {
Jamie Madill437fa652016-05-03 15:13:24 -04001094 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001095 return false;
1096 }
1097
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001098 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001099
1100 if (readFBO == nullptr)
1101 {
Jamie Madill437fa652016-05-03 15:13:24 -04001102 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001103 return false;
1104 }
1105
1106 if (src == GL_NONE)
1107 {
1108 return true;
1109 }
1110
Olli Etuaho84c9f592016-03-09 14:37:25 +02001111 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001112 {
Jamie Madill437fa652016-05-03 15:13:24 -04001113 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001114 return false;
1115 }
1116
1117 if (readFBO->id() == 0)
1118 {
1119 if (src != GL_BACK)
1120 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001121 const char *errorMsg =
1122 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001123 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001124 return false;
1125 }
1126 }
1127 else
1128 {
1129 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1130
1131 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1132 {
1133 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001134 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001135 return false;
1136 }
1137 }
1138
1139 return true;
1140}
1141
Jamie Madill86af3d22015-07-21 15:14:07 -04001142bool ValidateCompressedTexImage3D(Context *context,
1143 GLenum target,
1144 GLint level,
1145 GLenum internalformat,
1146 GLsizei width,
1147 GLsizei height,
1148 GLsizei depth,
1149 GLint border,
1150 GLsizei imageSize,
1151 const GLvoid *data)
1152{
Martin Radev1be913c2016-07-11 17:59:16 +03001153 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001154 {
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001156 return false;
1157 }
1158
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001159 if (!ValidTextureTarget(context, target))
1160 {
1161 context->handleError(Error(GL_INVALID_ENUM));
1162 return false;
1163 }
1164
Jamie Madille2e406c2016-06-02 13:04:10 -04001165 // Validate image size
1166 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1167 {
1168 context->handleError(Error(GL_INVALID_VALUE));
1169 return false;
1170 }
1171
Jamie Madill86af3d22015-07-21 15:14:07 -04001172 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001173 if (!formatInfo.compressed)
1174 {
1175 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1176 return false;
1177 }
1178
Jamie Madill513558d2016-06-02 13:04:11 -04001179 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001180 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001181 if (blockSizeOrErr.isError())
1182 {
Jamie Madill513558d2016-06-02 13:04:11 -04001183 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001184 return false;
1185 }
1186 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001189 return false;
1190 }
1191
1192 // 3D texture target validation
1193 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1194 {
Jamie Madill437fa652016-05-03 15:13:24 -04001195 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001196 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1197 return false;
1198 }
1199
1200 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001201 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001202 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1203 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001204 {
1205 return false;
1206 }
1207
1208 return true;
1209}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001210
1211bool ValidateBindVertexArray(Context *context, GLuint array)
1212{
Martin Radev1be913c2016-07-11 17:59:16 +03001213 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001214 {
Jamie Madill437fa652016-05-03 15:13:24 -04001215 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001216 return false;
1217 }
1218
1219 return ValidateBindVertexArrayBase(context, array);
1220}
1221
Austin Kinrossbc781f32015-10-26 09:27:38 -07001222bool ValidateIsVertexArray(Context *context)
1223{
Martin Radev1be913c2016-07-11 17:59:16 +03001224 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001225 {
Jamie Madill437fa652016-05-03 15:13:24 -04001226 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001227 return false;
1228 }
1229
1230 return true;
1231}
Geoff Langc5629752015-12-07 16:29:04 -05001232
Jiajia Qin6eafb042016-12-27 17:04:07 +08001233static bool ValidateBindBufferCommon(Context *context,
1234 GLenum target,
1235 GLuint index,
1236 GLuint buffer,
1237 GLintptr offset,
1238 GLsizeiptr size)
1239{
1240 if (context->getClientMajorVersion() < 3)
1241 {
1242 context->handleError(Error(GL_INVALID_OPERATION));
1243 return false;
1244 }
1245
1246 if (buffer != 0 && offset < 0)
1247 {
1248 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1249 return false;
1250 }
1251
1252 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1253 !context->isBufferGenerated(buffer))
1254 {
1255 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1256 return false;
1257 }
1258
1259 const Caps &caps = context->getCaps();
1260 switch (target)
1261 {
1262 case GL_TRANSFORM_FEEDBACK_BUFFER:
1263 {
1264 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1265 {
1266 context->handleError(Error(GL_INVALID_VALUE,
1267 "index is greater than or equal to the number of "
1268 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1269 return false;
1270 }
1271 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1272 {
1273 context->handleError(
1274 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1275 return false;
1276 }
1277
1278 TransformFeedback *curTransformFeedback =
1279 context->getGLState().getCurrentTransformFeedback();
1280 if (curTransformFeedback && curTransformFeedback->isActive())
1281 {
1282 context->handleError(Error(GL_INVALID_OPERATION,
1283 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1284 "feedback is currently active."));
1285 return false;
1286 }
1287 break;
1288 }
1289 case GL_UNIFORM_BUFFER:
1290 {
1291 if (index >= caps.maxUniformBufferBindings)
1292 {
1293 context->handleError(Error(GL_INVALID_VALUE,
1294 "index is greater than or equal to the number of "
1295 "UNIFORM_BUFFER indexed binding points."));
1296 return false;
1297 }
1298
1299 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1300 {
1301 context->handleError(
1302 Error(GL_INVALID_VALUE,
1303 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1304 return false;
1305 }
1306 break;
1307 }
1308 case GL_ATOMIC_COUNTER_BUFFER:
1309 {
1310 if (context->getClientVersion() < ES_3_1)
1311 {
Yunchao He61afff12017-03-14 15:34:03 +08001312 context->handleError(Error(
1313 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001314 return false;
1315 }
1316 if (index >= caps.maxAtomicCounterBufferBindings)
1317 {
1318 context->handleError(Error(GL_INVALID_VALUE,
1319 "index is greater than or equal to the number of "
1320 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1321 return false;
1322 }
1323 if (buffer != 0 && (offset % 4) != 0)
1324 {
1325 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1326 return false;
1327 }
1328 break;
1329 }
1330 case GL_SHADER_STORAGE_BUFFER:
1331 {
1332 if (context->getClientVersion() < ES_3_1)
1333 {
Yunchao He61afff12017-03-14 15:34:03 +08001334 context->handleError(Error(
1335 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001336 return false;
1337 }
1338 break;
1339 }
1340 default:
1341 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1342 return false;
1343 }
1344
1345 return true;
1346}
1347
1348bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1349{
1350 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1351}
1352
1353bool ValidateBindBufferRange(Context *context,
1354 GLenum target,
1355 GLuint index,
1356 GLuint buffer,
1357 GLintptr offset,
1358 GLsizeiptr size)
1359{
1360 if (buffer != 0 && size <= 0)
1361 {
1362 context->handleError(
1363 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1364 return false;
1365 }
1366 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1367}
1368
Geoff Langc5629752015-12-07 16:29:04 -05001369bool ValidateProgramBinary(Context *context,
1370 GLuint program,
1371 GLenum binaryFormat,
1372 const void *binary,
1373 GLint length)
1374{
Martin Radev1be913c2016-07-11 17:59:16 +03001375 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001376 {
Jamie Madill437fa652016-05-03 15:13:24 -04001377 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001378 return false;
1379 }
1380
1381 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1382}
1383
1384bool ValidateGetProgramBinary(Context *context,
1385 GLuint program,
1386 GLsizei bufSize,
1387 GLsizei *length,
1388 GLenum *binaryFormat,
1389 void *binary)
1390{
Martin Radev1be913c2016-07-11 17:59:16 +03001391 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001394 return false;
1395 }
1396
1397 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1398}
1399
Olli Etuahof0fee072016-03-30 15:11:58 +03001400bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001401{
Martin Radev1be913c2016-07-11 17:59:16 +03001402 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001403 {
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001405 return false;
1406 }
1407
1408 if (GetValidProgram(context, program) == nullptr)
1409 {
1410 return false;
1411 }
1412
1413 switch (pname)
1414 {
1415 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001416 if (value != GL_FALSE && value != GL_TRUE)
1417 {
Jamie Madill437fa652016-05-03 15:13:24 -04001418 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001419 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1420 return false;
1421 }
Geoff Langc5629752015-12-07 16:29:04 -05001422 break;
1423
Yunchao He61afff12017-03-14 15:34:03 +08001424 case GL_PROGRAM_SEPARABLE:
1425 if (context->getClientVersion() < ES_3_1)
1426 {
1427 context->handleError(
1428 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1429 return false;
1430 }
1431
1432 if (value != GL_FALSE && value != GL_TRUE)
1433 {
1434 context->handleError(Error(
1435 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1436 return false;
1437 }
1438 break;
1439
Geoff Langc5629752015-12-07 16:29:04 -05001440 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001442 return false;
1443 }
1444
1445 return true;
1446}
Jamie Madillc29968b2016-01-20 11:17:23 -05001447
1448bool ValidateBlitFramebuffer(Context *context,
1449 GLint srcX0,
1450 GLint srcY0,
1451 GLint srcX1,
1452 GLint srcY1,
1453 GLint dstX0,
1454 GLint dstY0,
1455 GLint dstX1,
1456 GLint dstY1,
1457 GLbitfield mask,
1458 GLenum filter)
1459{
Martin Radev1be913c2016-07-11 17:59:16 +03001460 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001463 return false;
1464 }
1465
1466 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1467 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001468}
Jamie Madillc29968b2016-01-20 11:17:23 -05001469
1470bool ValidateClearBufferiv(ValidationContext *context,
1471 GLenum buffer,
1472 GLint drawbuffer,
1473 const GLint *value)
1474{
1475 switch (buffer)
1476 {
1477 case GL_COLOR:
1478 if (drawbuffer < 0 ||
1479 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1480 {
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001482 return false;
1483 }
1484 break;
1485
1486 case GL_STENCIL:
1487 if (drawbuffer != 0)
1488 {
Jamie Madill437fa652016-05-03 15:13:24 -04001489 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 return false;
1491 }
1492 break;
1493
1494 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001495 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001496 return false;
1497 }
1498
1499 return ValidateClearBuffer(context);
1500}
1501
1502bool ValidateClearBufferuiv(ValidationContext *context,
1503 GLenum buffer,
1504 GLint drawbuffer,
1505 const GLuint *value)
1506{
1507 switch (buffer)
1508 {
1509 case GL_COLOR:
1510 if (drawbuffer < 0 ||
1511 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1512 {
Jamie Madill437fa652016-05-03 15:13:24 -04001513 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001514 return false;
1515 }
1516 break;
1517
1518 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001519 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001520 return false;
1521 }
1522
1523 return ValidateClearBuffer(context);
1524}
1525
1526bool ValidateClearBufferfv(ValidationContext *context,
1527 GLenum buffer,
1528 GLint drawbuffer,
1529 const GLfloat *value)
1530{
1531 switch (buffer)
1532 {
1533 case GL_COLOR:
1534 if (drawbuffer < 0 ||
1535 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001538 return false;
1539 }
1540 break;
1541
1542 case GL_DEPTH:
1543 if (drawbuffer != 0)
1544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001546 return false;
1547 }
1548 break;
1549
1550 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001551 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001552 return false;
1553 }
1554
1555 return ValidateClearBuffer(context);
1556}
1557
1558bool ValidateClearBufferfi(ValidationContext *context,
1559 GLenum buffer,
1560 GLint drawbuffer,
1561 GLfloat depth,
1562 GLint stencil)
1563{
1564 switch (buffer)
1565 {
1566 case GL_DEPTH_STENCIL:
1567 if (drawbuffer != 0)
1568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001570 return false;
1571 }
1572 break;
1573
1574 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001576 return false;
1577 }
1578
1579 return ValidateClearBuffer(context);
1580}
1581
1582bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1583{
Martin Radev1be913c2016-07-11 17:59:16 +03001584 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001585 {
Jamie Madill437fa652016-05-03 15:13:24 -04001586 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001587 return false;
1588 }
1589
1590 return ValidateDrawBuffersBase(context, n, bufs);
1591}
1592
1593bool ValidateCopyTexSubImage3D(Context *context,
1594 GLenum target,
1595 GLint level,
1596 GLint xoffset,
1597 GLint yoffset,
1598 GLint zoffset,
1599 GLint x,
1600 GLint y,
1601 GLsizei width,
1602 GLsizei height)
1603{
Martin Radev1be913c2016-07-11 17:59:16 +03001604 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001605 {
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001607 return false;
1608 }
1609
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001610 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1611 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001612}
1613
Jamie Madill73a84962016-02-12 09:27:23 -05001614bool ValidateTexImage3D(Context *context,
1615 GLenum target,
1616 GLint level,
1617 GLint internalformat,
1618 GLsizei width,
1619 GLsizei height,
1620 GLsizei depth,
1621 GLint border,
1622 GLenum format,
1623 GLenum type,
1624 const GLvoid *pixels)
1625{
Martin Radev1be913c2016-07-11 17:59:16 +03001626 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001627 {
Jamie Madill437fa652016-05-03 15:13:24 -04001628 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001629 return false;
1630 }
1631
1632 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001633 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001634 pixels);
1635}
1636
Geoff Langc52f6f12016-10-14 10:18:00 -04001637bool ValidateTexImage3DRobustANGLE(Context *context,
1638 GLenum target,
1639 GLint level,
1640 GLint internalformat,
1641 GLsizei width,
1642 GLsizei height,
1643 GLsizei depth,
1644 GLint border,
1645 GLenum format,
1646 GLenum type,
1647 GLsizei bufSize,
1648 const GLvoid *pixels)
1649{
1650 if (context->getClientMajorVersion() < 3)
1651 {
1652 context->handleError(Error(GL_INVALID_OPERATION));
1653 return false;
1654 }
1655
1656 if (!ValidateRobustEntryPoint(context, bufSize))
1657 {
1658 return false;
1659 }
1660
1661 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1662 0, 0, width, height, depth, border, format, type,
1663 bufSize, pixels);
1664}
1665
Jamie Madill73a84962016-02-12 09:27:23 -05001666bool ValidateTexSubImage3D(Context *context,
1667 GLenum target,
1668 GLint level,
1669 GLint xoffset,
1670 GLint yoffset,
1671 GLint zoffset,
1672 GLsizei width,
1673 GLsizei height,
1674 GLsizei depth,
1675 GLenum format,
1676 GLenum type,
1677 const GLvoid *pixels)
1678{
Martin Radev1be913c2016-07-11 17:59:16 +03001679 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001682 return false;
1683 }
1684
1685 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1686 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001687 -1, pixels);
1688}
1689
1690bool ValidateTexSubImage3DRobustANGLE(Context *context,
1691 GLenum target,
1692 GLint level,
1693 GLint xoffset,
1694 GLint yoffset,
1695 GLint zoffset,
1696 GLsizei width,
1697 GLsizei height,
1698 GLsizei depth,
1699 GLenum format,
1700 GLenum type,
1701 GLsizei bufSize,
1702 const GLvoid *pixels)
1703{
1704 if (context->getClientMajorVersion() < 3)
1705 {
1706 context->handleError(Error(GL_INVALID_OPERATION));
1707 return false;
1708 }
1709
1710 if (!ValidateRobustEntryPoint(context, bufSize))
1711 {
1712 return false;
1713 }
1714
1715 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1716 yoffset, zoffset, width, height, depth, 0, format, type,
1717 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001718}
1719
1720bool ValidateCompressedTexSubImage3D(Context *context,
1721 GLenum target,
1722 GLint level,
1723 GLint xoffset,
1724 GLint yoffset,
1725 GLint zoffset,
1726 GLsizei width,
1727 GLsizei height,
1728 GLsizei depth,
1729 GLenum format,
1730 GLsizei imageSize,
1731 const GLvoid *data)
1732{
Martin Radev1be913c2016-07-11 17:59:16 +03001733 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001734 {
Jamie Madill437fa652016-05-03 15:13:24 -04001735 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001736 return false;
1737 }
1738
1739 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001740 if (!formatInfo.compressed)
1741 {
1742 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1743 return false;
1744 }
1745
Jamie Madill513558d2016-06-02 13:04:11 -04001746 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001747 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001748 if (blockSizeOrErr.isError())
1749 {
1750 context->handleError(blockSizeOrErr.getError());
1751 return false;
1752 }
1753 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001754 {
Jamie Madill437fa652016-05-03 15:13:24 -04001755 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001756 return false;
1757 }
1758
1759 if (!data)
1760 {
Jamie Madill437fa652016-05-03 15:13:24 -04001761 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001762 return false;
1763 }
1764
1765 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001766 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001767}
1768
Olli Etuaho41997e72016-03-10 13:38:39 +02001769bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1770{
1771 return ValidateGenOrDeleteES3(context, n);
1772}
1773
1774bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1775{
1776 return ValidateGenOrDeleteES3(context, n);
1777}
1778
1779bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1780{
1781 return ValidateGenOrDeleteCountES3(context, count);
1782}
1783
1784bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1785{
1786 return ValidateGenOrDeleteCountES3(context, count);
1787}
1788
1789bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1790{
1791 return ValidateGenOrDeleteES3(context, n);
1792}
1793
1794bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1795{
1796 if (!ValidateGenOrDeleteES3(context, n))
1797 {
1798 return false;
1799 }
1800 for (GLint i = 0; i < n; ++i)
1801 {
1802 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1803 if (transformFeedback != nullptr && transformFeedback->isActive())
1804 {
1805 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001806 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001807 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1808 return false;
1809 }
1810 }
1811 return true;
1812}
1813
1814bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1815{
1816 return ValidateGenOrDeleteES3(context, n);
1817}
1818
1819bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1820{
1821 return ValidateGenOrDeleteES3(context, n);
1822}
1823
1824bool ValidateGenOrDeleteES3(Context *context, GLint n)
1825{
Martin Radev1be913c2016-07-11 17:59:16 +03001826 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001829 return false;
1830 }
1831 return ValidateGenOrDelete(context, n);
1832}
1833
1834bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1835{
Martin Radev1be913c2016-07-11 17:59:16 +03001836 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001837 {
Jamie Madill437fa652016-05-03 15:13:24 -04001838 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001839 return false;
1840 }
1841 if (count < 0)
1842 {
Jamie Madill437fa652016-05-03 15:13:24 -04001843 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001844 return false;
1845 }
1846 return true;
1847}
1848
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001849bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1850{
Martin Radev1be913c2016-07-11 17:59:16 +03001851 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001852 {
Jamie Madill437fa652016-05-03 15:13:24 -04001853 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001854 return false;
1855 }
1856 switch (primitiveMode)
1857 {
1858 case GL_TRIANGLES:
1859 case GL_LINES:
1860 case GL_POINTS:
1861 break;
1862
1863 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001864 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001865 return false;
1866 }
1867
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001868 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001869 ASSERT(transformFeedback != nullptr);
1870
1871 if (transformFeedback->isActive())
1872 {
Jamie Madill437fa652016-05-03 15:13:24 -04001873 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001874 return false;
1875 }
1876 return true;
1877}
1878
Olli Etuaho4f667482016-03-30 15:56:35 +03001879bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1880{
Geoff Lang496c02d2016-10-20 11:38:11 -07001881 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1882}
1883
1884bool ValidateGetBufferPointervRobustANGLE(Context *context,
1885 GLenum target,
1886 GLenum pname,
1887 GLsizei bufSize,
1888 GLsizei *length,
1889 GLvoid **params)
1890{
1891 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001892 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001893 return false;
1894 }
1895
Geoff Lang496c02d2016-10-20 11:38:11 -07001896 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1897 {
1898 return false;
1899 }
1900
1901 if (!ValidateRobustBufferSize(context, bufSize, *length))
1902 {
1903 return false;
1904 }
1905
1906 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001907}
1908
1909bool ValidateUnmapBuffer(Context *context, GLenum target)
1910{
Martin Radev1be913c2016-07-11 17:59:16 +03001911 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001912 {
Jamie Madill437fa652016-05-03 15:13:24 -04001913 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001914 return false;
1915 }
1916
1917 return ValidateUnmapBufferBase(context, target);
1918}
1919
1920bool ValidateMapBufferRange(Context *context,
1921 GLenum target,
1922 GLintptr offset,
1923 GLsizeiptr length,
1924 GLbitfield access)
1925{
Martin Radev1be913c2016-07-11 17:59:16 +03001926 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001927 {
Jamie Madill437fa652016-05-03 15:13:24 -04001928 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001929 return false;
1930 }
1931
1932 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1933}
1934
1935bool ValidateFlushMappedBufferRange(Context *context,
1936 GLenum target,
1937 GLintptr offset,
1938 GLsizeiptr length)
1939{
Martin Radev1be913c2016-07-11 17:59:16 +03001940 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001941 {
Jamie Madill437fa652016-05-03 15:13:24 -04001942 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001943 return false;
1944 }
1945
1946 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1947}
1948
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001949bool ValidateIndexedStateQuery(ValidationContext *context,
1950 GLenum pname,
1951 GLuint index,
1952 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001953{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001954 if (length)
1955 {
1956 *length = 0;
1957 }
1958
Martin Radev66fb8202016-07-28 11:45:20 +03001959 GLenum nativeType;
1960 unsigned int numParams;
1961 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1962 {
1963 context->handleError(Error(GL_INVALID_ENUM));
1964 return false;
1965 }
1966
1967 const Caps &caps = context->getCaps();
1968 switch (pname)
1969 {
1970 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1971 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1972 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1973 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1974 {
1975 context->handleError(Error(GL_INVALID_VALUE));
1976 return false;
1977 }
1978 break;
1979
1980 case GL_UNIFORM_BUFFER_START:
1981 case GL_UNIFORM_BUFFER_SIZE:
1982 case GL_UNIFORM_BUFFER_BINDING:
1983 if (index >= caps.maxUniformBufferBindings)
1984 {
1985 context->handleError(Error(GL_INVALID_VALUE));
1986 return false;
1987 }
1988 break;
Shao80957d92017-02-20 21:25:59 +08001989
Martin Radev66fb8202016-07-28 11:45:20 +03001990 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1991 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1992 if (index >= 3u)
1993 {
1994 context->handleError(Error(GL_INVALID_VALUE));
1995 return false;
1996 }
1997 break;
Shao80957d92017-02-20 21:25:59 +08001998
Jiajia Qin6eafb042016-12-27 17:04:07 +08001999 case GL_ATOMIC_COUNTER_BUFFER_START:
2000 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2001 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2002 if (context->getClientVersion() < ES_3_1)
2003 {
2004 context->handleError(
2005 Error(GL_INVALID_ENUM,
2006 "Atomic Counter buffers are not supported in this version of GL"));
2007 return false;
2008 }
2009 if (index >= caps.maxAtomicCounterBufferBindings)
2010 {
2011 context->handleError(
2012 Error(GL_INVALID_VALUE,
2013 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2014 return false;
2015 }
2016 break;
Shao80957d92017-02-20 21:25:59 +08002017
2018 case GL_VERTEX_BINDING_BUFFER:
2019 case GL_VERTEX_BINDING_DIVISOR:
2020 case GL_VERTEX_BINDING_OFFSET:
2021 case GL_VERTEX_BINDING_STRIDE:
2022 if (context->getClientVersion() < ES_3_1)
2023 {
2024 context->handleError(
2025 Error(GL_INVALID_ENUM,
2026 "Vertex Attrib Bindings are not supported in this version of GL"));
2027 return false;
2028 }
2029 if (index >= caps.maxVertexAttribBindings)
2030 {
2031 context->handleError(
2032 Error(GL_INVALID_VALUE,
2033 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2034 return false;
2035 }
2036 break;
2037
Martin Radev66fb8202016-07-28 11:45:20 +03002038 default:
2039 context->handleError(Error(GL_INVALID_ENUM));
2040 return false;
2041 }
2042
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002043 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002044 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002045 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002046 }
2047
2048 return true;
2049}
2050
2051bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2052{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002053 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002054 {
2055 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2056 return false;
2057 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002058 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002059}
2060
Geoff Langcf255ea2016-10-20 11:39:09 -07002061bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2062 GLenum target,
2063 GLuint index,
2064 GLsizei bufSize,
2065 GLsizei *length,
2066 GLint *data)
2067{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002068 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002069 {
2070 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2071 return false;
2072 }
2073
2074 if (!ValidateRobustEntryPoint(context, bufSize))
2075 {
2076 return false;
2077 }
2078
2079 if (!ValidateIndexedStateQuery(context, target, index, length))
2080 {
2081 return false;
2082 }
2083
2084 if (!ValidateRobustBufferSize(context, bufSize, *length))
2085 {
2086 return false;
2087 }
2088
2089 return true;
2090}
2091
Martin Radev66fb8202016-07-28 11:45:20 +03002092bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2093{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002094 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002095 {
2096 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2097 return false;
2098 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002099 return ValidateIndexedStateQuery(context, target, index, nullptr);
2100}
2101
2102bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2103 GLenum target,
2104 GLuint index,
2105 GLsizei bufSize,
2106 GLsizei *length,
2107 GLint64 *data)
2108{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002109 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002110 {
2111 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2112 return false;
2113 }
2114
2115 if (!ValidateRobustEntryPoint(context, bufSize))
2116 {
2117 return false;
2118 }
2119
2120 if (!ValidateIndexedStateQuery(context, target, index, length))
2121 {
2122 return false;
2123 }
2124
2125 if (!ValidateRobustBufferSize(context, bufSize, *length))
2126 {
2127 return false;
2128 }
2129
2130 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002131}
2132
Jamie Madillb0817d12016-11-01 15:48:31 -04002133bool ValidateCopyBufferSubData(ValidationContext *context,
2134 GLenum readTarget,
2135 GLenum writeTarget,
2136 GLintptr readOffset,
2137 GLintptr writeOffset,
2138 GLsizeiptr size)
2139{
2140 if (context->getClientMajorVersion() < 3)
2141 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002142 context->handleError(
2143 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002144 return false;
2145 }
2146
2147 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2148 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002149 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002150 return false;
2151 }
2152
2153 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2154 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2155
2156 if (!readBuffer || !writeBuffer)
2157 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002158 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002159 return false;
2160 }
2161
2162 // Verify that readBuffer and writeBuffer are not currently mapped
2163 if (readBuffer->isMapped() || writeBuffer->isMapped())
2164 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002165 context->handleError(
2166 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002167 return false;
2168 }
2169
Jamie Madilld2f0c742016-11-02 10:34:41 -04002170 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2171 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2172 CheckedNumeric<GLintptr> checkedSize(size);
2173
2174 auto checkedReadSum = checkedReadOffset + checkedSize;
2175 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2176
2177 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2178 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2179 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002180 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002181 context->handleError(
2182 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002183 return false;
2184 }
2185
Jamie Madilld2f0c742016-11-02 10:34:41 -04002186 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002187 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002188 context->handleError(
2189 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002190 return false;
2191 }
2192
Jamie Madilld2f0c742016-11-02 10:34:41 -04002193 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2194 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2195 {
2196 context->handleError(
2197 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2198 return false;
2199 }
2200
2201 if (readBuffer == writeBuffer)
2202 {
2203 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2204 if (!checkedOffsetDiff.IsValid())
2205 {
2206 // This shold not be possible.
2207 UNREACHABLE();
2208 context->handleError(
2209 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2210 return false;
2211 }
2212
2213 if (checkedOffsetDiff.ValueOrDie() < size)
2214 {
2215 context->handleError(Error(GL_INVALID_VALUE));
2216 return false;
2217 }
2218 }
2219
Jamie Madillb0817d12016-11-01 15:48:31 -04002220 return true;
2221}
2222
Geoff Langc339c4e2016-11-29 10:37:36 -05002223bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2224{
2225 if (context->getClientMajorVersion() < 3)
2226 {
2227 context->handleError(
2228 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2229 return false;
2230 }
2231
2232 switch (name)
2233 {
2234 case GL_EXTENSIONS:
2235 if (index >= context->getExtensionStringCount())
2236 {
2237 context->handleError(Error(
2238 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2239 return false;
2240 }
2241 break;
2242
2243 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2244 if (!context->getExtensions().requestExtension)
2245 {
2246 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2247 return false;
2248 }
2249 if (index >= context->getRequestableExtensionStringCount())
2250 {
2251 context->handleError(
2252 Error(GL_INVALID_VALUE,
2253 "index must be less than the number of requestable extension strings."));
2254 return false;
2255 }
2256 break;
2257
2258 default:
2259 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2260 return false;
2261 }
2262
2263 return true;
2264}
2265
Jamie Madille8fb6402017-02-14 17:56:40 -05002266bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2267 GLenum target,
2268 GLsizei samples,
2269 GLenum internalformat,
2270 GLsizei width,
2271 GLsizei height)
2272{
2273 if (context->getClientMajorVersion() < 3)
2274 {
2275 context->handleError(Error(GL_INVALID_OPERATION));
2276 return false;
2277 }
2278
2279 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2280 height))
2281 {
2282 return false;
2283 }
2284
2285 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2286 // format if samples is greater than zero.
2287 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2288 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2289 samples > 0)
2290 {
2291 context->handleError(Error(GL_INVALID_OPERATION));
2292 return false;
2293 }
2294
2295 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2296 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2297 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2298 {
2299 context->handleError(
2300 Error(GL_INVALID_OPERATION,
2301 "Samples must not be greater than maximum supported value for the format."));
2302 return false;
2303 }
2304
2305 return true;
2306}
2307
Geoff Langaa086d62017-03-23 16:47:21 -04002308bool ValidateVertexAttribIPointer(ValidationContext *context,
2309 GLuint index,
2310 GLint size,
2311 GLenum type,
2312 GLsizei stride,
2313 const GLvoid *pointer)
2314{
2315 if (context->getClientMajorVersion() < 3)
2316 {
Geoff Langaa086d62017-03-23 16:47:21 -04002317 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002318 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002319 return false;
2320 }
2321
Shao80957d92017-02-20 21:25:59 +08002322 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002323 {
Geoff Langaa086d62017-03-23 16:47:21 -04002324 return false;
2325 }
2326
Geoff Langaa086d62017-03-23 16:47:21 -04002327 if (stride < 0)
2328 {
Shao80957d92017-02-20 21:25:59 +08002329 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002330 return false;
2331 }
2332
Shao80957d92017-02-20 21:25:59 +08002333 const Caps &caps = context->getCaps();
2334 if (context->getClientVersion() >= ES_3_1)
2335 {
2336 if (stride > caps.maxVertexAttribStride)
2337 {
2338 context->handleError(
2339 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2340 return false;
2341 }
2342
2343 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2344 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2345 // validation should be inherited.
2346 if (index >= caps.maxVertexAttribBindings)
2347 {
2348 context->handleError(
2349 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2350 return false;
2351 }
2352 }
2353
Geoff Langaa086d62017-03-23 16:47:21 -04002354 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2355 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2356 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2357 // and the pointer argument is not NULL.
2358 if (context->getGLState().getVertexArrayId() != 0 &&
2359 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2360 {
2361 context->handleError(
2362 Error(GL_INVALID_OPERATION,
2363 "Client data cannot be used with a non-default vertex array object."));
2364 return false;
2365 }
2366
2367 return true;
2368}
2369
Jamie Madillc29968b2016-01-20 11:17:23 -05002370} // namespace gl