blob: 13a1d2f7557517536e5728ab15ce60d2597c27ec [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
1233bool ValidateProgramBinary(Context *context,
1234 GLuint program,
1235 GLenum binaryFormat,
1236 const void *binary,
1237 GLint length)
1238{
Martin Radev1be913c2016-07-11 17:59:16 +03001239 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001242 return false;
1243 }
1244
1245 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1246}
1247
1248bool ValidateGetProgramBinary(Context *context,
1249 GLuint program,
1250 GLsizei bufSize,
1251 GLsizei *length,
1252 GLenum *binaryFormat,
1253 void *binary)
1254{
Martin Radev1be913c2016-07-11 17:59:16 +03001255 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001256 {
Jamie Madill437fa652016-05-03 15:13:24 -04001257 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001258 return false;
1259 }
1260
1261 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1262}
1263
Olli Etuahof0fee072016-03-30 15:11:58 +03001264bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001265{
Martin Radev1be913c2016-07-11 17:59:16 +03001266 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001267 {
Jamie Madill437fa652016-05-03 15:13:24 -04001268 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001269 return false;
1270 }
1271
1272 if (GetValidProgram(context, program) == nullptr)
1273 {
1274 return false;
1275 }
1276
1277 switch (pname)
1278 {
1279 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001280 if (value != GL_FALSE && value != GL_TRUE)
1281 {
Jamie Madill437fa652016-05-03 15:13:24 -04001282 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001283 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1284 return false;
1285 }
Geoff Langc5629752015-12-07 16:29:04 -05001286 break;
1287
1288 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001289 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001290 return false;
1291 }
1292
1293 return true;
1294}
Jamie Madillc29968b2016-01-20 11:17:23 -05001295
1296bool ValidateBlitFramebuffer(Context *context,
1297 GLint srcX0,
1298 GLint srcY0,
1299 GLint srcX1,
1300 GLint srcY1,
1301 GLint dstX0,
1302 GLint dstY0,
1303 GLint dstX1,
1304 GLint dstY1,
1305 GLbitfield mask,
1306 GLenum filter)
1307{
Martin Radev1be913c2016-07-11 17:59:16 +03001308 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001309 {
Jamie Madill437fa652016-05-03 15:13:24 -04001310 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001311 return false;
1312 }
1313
1314 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1315 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316}
Jamie Madillc29968b2016-01-20 11:17:23 -05001317
1318bool ValidateClearBufferiv(ValidationContext *context,
1319 GLenum buffer,
1320 GLint drawbuffer,
1321 const GLint *value)
1322{
1323 switch (buffer)
1324 {
1325 case GL_COLOR:
1326 if (drawbuffer < 0 ||
1327 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001330 return false;
1331 }
1332 break;
1333
1334 case GL_STENCIL:
1335 if (drawbuffer != 0)
1336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001338 return false;
1339 }
1340 break;
1341
1342 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001343 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001344 return false;
1345 }
1346
1347 return ValidateClearBuffer(context);
1348}
1349
1350bool ValidateClearBufferuiv(ValidationContext *context,
1351 GLenum buffer,
1352 GLint drawbuffer,
1353 const GLuint *value)
1354{
1355 switch (buffer)
1356 {
1357 case GL_COLOR:
1358 if (drawbuffer < 0 ||
1359 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001362 return false;
1363 }
1364 break;
1365
1366 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001368 return false;
1369 }
1370
1371 return ValidateClearBuffer(context);
1372}
1373
1374bool ValidateClearBufferfv(ValidationContext *context,
1375 GLenum buffer,
1376 GLint drawbuffer,
1377 const GLfloat *value)
1378{
1379 switch (buffer)
1380 {
1381 case GL_COLOR:
1382 if (drawbuffer < 0 ||
1383 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001386 return false;
1387 }
1388 break;
1389
1390 case GL_DEPTH:
1391 if (drawbuffer != 0)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001394 return false;
1395 }
1396 break;
1397
1398 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001400 return false;
1401 }
1402
1403 return ValidateClearBuffer(context);
1404}
1405
1406bool ValidateClearBufferfi(ValidationContext *context,
1407 GLenum buffer,
1408 GLint drawbuffer,
1409 GLfloat depth,
1410 GLint stencil)
1411{
1412 switch (buffer)
1413 {
1414 case GL_DEPTH_STENCIL:
1415 if (drawbuffer != 0)
1416 {
Jamie Madill437fa652016-05-03 15:13:24 -04001417 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001418 return false;
1419 }
1420 break;
1421
1422 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001424 return false;
1425 }
1426
1427 return ValidateClearBuffer(context);
1428}
1429
1430bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1431{
Martin Radev1be913c2016-07-11 17:59:16 +03001432 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001433 {
Jamie Madill437fa652016-05-03 15:13:24 -04001434 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001435 return false;
1436 }
1437
1438 return ValidateDrawBuffersBase(context, n, bufs);
1439}
1440
1441bool ValidateCopyTexSubImage3D(Context *context,
1442 GLenum target,
1443 GLint level,
1444 GLint xoffset,
1445 GLint yoffset,
1446 GLint zoffset,
1447 GLint x,
1448 GLint y,
1449 GLsizei width,
1450 GLsizei height)
1451{
Martin Radev1be913c2016-07-11 17:59:16 +03001452 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001453 {
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 return false;
1456 }
1457
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001458 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1459 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001460}
1461
Jamie Madill73a84962016-02-12 09:27:23 -05001462bool ValidateTexImage3D(Context *context,
1463 GLenum target,
1464 GLint level,
1465 GLint internalformat,
1466 GLsizei width,
1467 GLsizei height,
1468 GLsizei depth,
1469 GLint border,
1470 GLenum format,
1471 GLenum type,
1472 const GLvoid *pixels)
1473{
Martin Radev1be913c2016-07-11 17:59:16 +03001474 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001475 {
Jamie Madill437fa652016-05-03 15:13:24 -04001476 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001477 return false;
1478 }
1479
1480 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001481 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001482 pixels);
1483}
1484
Geoff Langc52f6f12016-10-14 10:18:00 -04001485bool ValidateTexImage3DRobustANGLE(Context *context,
1486 GLenum target,
1487 GLint level,
1488 GLint internalformat,
1489 GLsizei width,
1490 GLsizei height,
1491 GLsizei depth,
1492 GLint border,
1493 GLenum format,
1494 GLenum type,
1495 GLsizei bufSize,
1496 const GLvoid *pixels)
1497{
1498 if (context->getClientMajorVersion() < 3)
1499 {
1500 context->handleError(Error(GL_INVALID_OPERATION));
1501 return false;
1502 }
1503
1504 if (!ValidateRobustEntryPoint(context, bufSize))
1505 {
1506 return false;
1507 }
1508
1509 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1510 0, 0, width, height, depth, border, format, type,
1511 bufSize, pixels);
1512}
1513
Jamie Madill73a84962016-02-12 09:27:23 -05001514bool ValidateTexSubImage3D(Context *context,
1515 GLenum target,
1516 GLint level,
1517 GLint xoffset,
1518 GLint yoffset,
1519 GLint zoffset,
1520 GLsizei width,
1521 GLsizei height,
1522 GLsizei depth,
1523 GLenum format,
1524 GLenum type,
1525 const GLvoid *pixels)
1526{
Martin Radev1be913c2016-07-11 17:59:16 +03001527 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001530 return false;
1531 }
1532
1533 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1534 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001535 -1, pixels);
1536}
1537
1538bool ValidateTexSubImage3DRobustANGLE(Context *context,
1539 GLenum target,
1540 GLint level,
1541 GLint xoffset,
1542 GLint yoffset,
1543 GLint zoffset,
1544 GLsizei width,
1545 GLsizei height,
1546 GLsizei depth,
1547 GLenum format,
1548 GLenum type,
1549 GLsizei bufSize,
1550 const GLvoid *pixels)
1551{
1552 if (context->getClientMajorVersion() < 3)
1553 {
1554 context->handleError(Error(GL_INVALID_OPERATION));
1555 return false;
1556 }
1557
1558 if (!ValidateRobustEntryPoint(context, bufSize))
1559 {
1560 return false;
1561 }
1562
1563 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1564 yoffset, zoffset, width, height, depth, 0, format, type,
1565 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001566}
1567
1568bool ValidateCompressedTexSubImage3D(Context *context,
1569 GLenum target,
1570 GLint level,
1571 GLint xoffset,
1572 GLint yoffset,
1573 GLint zoffset,
1574 GLsizei width,
1575 GLsizei height,
1576 GLsizei depth,
1577 GLenum format,
1578 GLsizei imageSize,
1579 const GLvoid *data)
1580{
Martin Radev1be913c2016-07-11 17:59:16 +03001581 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001584 return false;
1585 }
1586
1587 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001588 if (!formatInfo.compressed)
1589 {
1590 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1591 return false;
1592 }
1593
Jamie Madill513558d2016-06-02 13:04:11 -04001594 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001595 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001596 if (blockSizeOrErr.isError())
1597 {
1598 context->handleError(blockSizeOrErr.getError());
1599 return false;
1600 }
1601 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001602 {
Jamie Madill437fa652016-05-03 15:13:24 -04001603 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001604 return false;
1605 }
1606
1607 if (!data)
1608 {
Jamie Madill437fa652016-05-03 15:13:24 -04001609 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001610 return false;
1611 }
1612
1613 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001614 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001615}
1616
Olli Etuaho41997e72016-03-10 13:38:39 +02001617bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1618{
1619 return ValidateGenOrDeleteES3(context, n);
1620}
1621
1622bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1623{
1624 return ValidateGenOrDeleteES3(context, n);
1625}
1626
1627bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1628{
1629 return ValidateGenOrDeleteCountES3(context, count);
1630}
1631
1632bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1633{
1634 return ValidateGenOrDeleteCountES3(context, count);
1635}
1636
1637bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1638{
1639 return ValidateGenOrDeleteES3(context, n);
1640}
1641
1642bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1643{
1644 if (!ValidateGenOrDeleteES3(context, n))
1645 {
1646 return false;
1647 }
1648 for (GLint i = 0; i < n; ++i)
1649 {
1650 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1651 if (transformFeedback != nullptr && transformFeedback->isActive())
1652 {
1653 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001655 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1656 return false;
1657 }
1658 }
1659 return true;
1660}
1661
1662bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1663{
1664 return ValidateGenOrDeleteES3(context, n);
1665}
1666
1667bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1668{
1669 return ValidateGenOrDeleteES3(context, n);
1670}
1671
1672bool ValidateGenOrDeleteES3(Context *context, GLint n)
1673{
Martin Radev1be913c2016-07-11 17:59:16 +03001674 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001675 {
Jamie Madill437fa652016-05-03 15:13:24 -04001676 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001677 return false;
1678 }
1679 return ValidateGenOrDelete(context, n);
1680}
1681
1682bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1683{
Martin Radev1be913c2016-07-11 17:59:16 +03001684 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001685 {
Jamie Madill437fa652016-05-03 15:13:24 -04001686 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001687 return false;
1688 }
1689 if (count < 0)
1690 {
Jamie Madill437fa652016-05-03 15:13:24 -04001691 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001692 return false;
1693 }
1694 return true;
1695}
1696
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001697bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1698{
Martin Radev1be913c2016-07-11 17:59:16 +03001699 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001702 return false;
1703 }
1704 switch (primitiveMode)
1705 {
1706 case GL_TRIANGLES:
1707 case GL_LINES:
1708 case GL_POINTS:
1709 break;
1710
1711 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001713 return false;
1714 }
1715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001716 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001717 ASSERT(transformFeedback != nullptr);
1718
1719 if (transformFeedback->isActive())
1720 {
Jamie Madill437fa652016-05-03 15:13:24 -04001721 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001722 return false;
1723 }
1724 return true;
1725}
1726
Olli Etuaho4f667482016-03-30 15:56:35 +03001727bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1728{
Geoff Lang496c02d2016-10-20 11:38:11 -07001729 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1730}
1731
1732bool ValidateGetBufferPointervRobustANGLE(Context *context,
1733 GLenum target,
1734 GLenum pname,
1735 GLsizei bufSize,
1736 GLsizei *length,
1737 GLvoid **params)
1738{
1739 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001740 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001741 return false;
1742 }
1743
Geoff Lang496c02d2016-10-20 11:38:11 -07001744 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1745 {
1746 return false;
1747 }
1748
1749 if (!ValidateRobustBufferSize(context, bufSize, *length))
1750 {
1751 return false;
1752 }
1753
1754 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001755}
1756
1757bool ValidateUnmapBuffer(Context *context, GLenum target)
1758{
Martin Radev1be913c2016-07-11 17:59:16 +03001759 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001760 {
Jamie Madill437fa652016-05-03 15:13:24 -04001761 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001762 return false;
1763 }
1764
1765 return ValidateUnmapBufferBase(context, target);
1766}
1767
1768bool ValidateMapBufferRange(Context *context,
1769 GLenum target,
1770 GLintptr offset,
1771 GLsizeiptr length,
1772 GLbitfield access)
1773{
Martin Radev1be913c2016-07-11 17:59:16 +03001774 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001775 {
Jamie Madill437fa652016-05-03 15:13:24 -04001776 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001777 return false;
1778 }
1779
1780 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1781}
1782
1783bool ValidateFlushMappedBufferRange(Context *context,
1784 GLenum target,
1785 GLintptr offset,
1786 GLsizeiptr length)
1787{
Martin Radev1be913c2016-07-11 17:59:16 +03001788 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001789 {
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001791 return false;
1792 }
1793
1794 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1795}
1796
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001797bool ValidateIndexedStateQuery(ValidationContext *context,
1798 GLenum pname,
1799 GLuint index,
1800 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001801{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001802 if (length)
1803 {
1804 *length = 0;
1805 }
1806
Martin Radev66fb8202016-07-28 11:45:20 +03001807 GLenum nativeType;
1808 unsigned int numParams;
1809 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1810 {
1811 context->handleError(Error(GL_INVALID_ENUM));
1812 return false;
1813 }
1814
1815 const Caps &caps = context->getCaps();
1816 switch (pname)
1817 {
1818 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1819 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1820 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1821 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1822 {
1823 context->handleError(Error(GL_INVALID_VALUE));
1824 return false;
1825 }
1826 break;
1827
1828 case GL_UNIFORM_BUFFER_START:
1829 case GL_UNIFORM_BUFFER_SIZE:
1830 case GL_UNIFORM_BUFFER_BINDING:
1831 if (index >= caps.maxUniformBufferBindings)
1832 {
1833 context->handleError(Error(GL_INVALID_VALUE));
1834 return false;
1835 }
1836 break;
1837 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1838 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1839 if (index >= 3u)
1840 {
1841 context->handleError(Error(GL_INVALID_VALUE));
1842 return false;
1843 }
1844 break;
1845 default:
1846 context->handleError(Error(GL_INVALID_ENUM));
1847 return false;
1848 }
1849
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001850 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001851 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001852 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001853 }
1854
1855 return true;
1856}
1857
1858bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1859{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001860 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001861 {
1862 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1863 return false;
1864 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001865 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001866}
1867
Geoff Langcf255ea2016-10-20 11:39:09 -07001868bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
1869 GLenum target,
1870 GLuint index,
1871 GLsizei bufSize,
1872 GLsizei *length,
1873 GLint *data)
1874{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001875 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07001876 {
1877 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1878 return false;
1879 }
1880
1881 if (!ValidateRobustEntryPoint(context, bufSize))
1882 {
1883 return false;
1884 }
1885
1886 if (!ValidateIndexedStateQuery(context, target, index, length))
1887 {
1888 return false;
1889 }
1890
1891 if (!ValidateRobustBufferSize(context, bufSize, *length))
1892 {
1893 return false;
1894 }
1895
1896 return true;
1897}
1898
Martin Radev66fb8202016-07-28 11:45:20 +03001899bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1900{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001901 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001902 {
1903 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1904 return false;
1905 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001906 return ValidateIndexedStateQuery(context, target, index, nullptr);
1907}
1908
1909bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1910 GLenum target,
1911 GLuint index,
1912 GLsizei bufSize,
1913 GLsizei *length,
1914 GLint64 *data)
1915{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001916 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001917 {
1918 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1919 return false;
1920 }
1921
1922 if (!ValidateRobustEntryPoint(context, bufSize))
1923 {
1924 return false;
1925 }
1926
1927 if (!ValidateIndexedStateQuery(context, target, index, length))
1928 {
1929 return false;
1930 }
1931
1932 if (!ValidateRobustBufferSize(context, bufSize, *length))
1933 {
1934 return false;
1935 }
1936
1937 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001938}
1939
Jamie Madillb0817d12016-11-01 15:48:31 -04001940bool ValidateCopyBufferSubData(ValidationContext *context,
1941 GLenum readTarget,
1942 GLenum writeTarget,
1943 GLintptr readOffset,
1944 GLintptr writeOffset,
1945 GLsizeiptr size)
1946{
1947 if (context->getClientMajorVersion() < 3)
1948 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001949 context->handleError(
1950 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001951 return false;
1952 }
1953
1954 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
1955 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001956 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001957 return false;
1958 }
1959
1960 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
1961 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
1962
1963 if (!readBuffer || !writeBuffer)
1964 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001965 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001966 return false;
1967 }
1968
1969 // Verify that readBuffer and writeBuffer are not currently mapped
1970 if (readBuffer->isMapped() || writeBuffer->isMapped())
1971 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001972 context->handleError(
1973 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001974 return false;
1975 }
1976
Jamie Madilld2f0c742016-11-02 10:34:41 -04001977 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
1978 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
1979 CheckedNumeric<GLintptr> checkedSize(size);
1980
1981 auto checkedReadSum = checkedReadOffset + checkedSize;
1982 auto checkedWriteSum = checkedWriteOffset + checkedSize;
1983
1984 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
1985 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
1986 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04001987 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001988 context->handleError(
1989 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04001990 return false;
1991 }
1992
Jamie Madilld2f0c742016-11-02 10:34:41 -04001993 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04001994 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001995 context->handleError(
1996 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001997 return false;
1998 }
1999
Jamie Madilld2f0c742016-11-02 10:34:41 -04002000 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2001 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2002 {
2003 context->handleError(
2004 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2005 return false;
2006 }
2007
2008 if (readBuffer == writeBuffer)
2009 {
2010 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2011 if (!checkedOffsetDiff.IsValid())
2012 {
2013 // This shold not be possible.
2014 UNREACHABLE();
2015 context->handleError(
2016 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2017 return false;
2018 }
2019
2020 if (checkedOffsetDiff.ValueOrDie() < size)
2021 {
2022 context->handleError(Error(GL_INVALID_VALUE));
2023 return false;
2024 }
2025 }
2026
Jamie Madillb0817d12016-11-01 15:48:31 -04002027 return true;
2028}
2029
Geoff Langc339c4e2016-11-29 10:37:36 -05002030bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2031{
2032 if (context->getClientMajorVersion() < 3)
2033 {
2034 context->handleError(
2035 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2036 return false;
2037 }
2038
2039 switch (name)
2040 {
2041 case GL_EXTENSIONS:
2042 if (index >= context->getExtensionStringCount())
2043 {
2044 context->handleError(Error(
2045 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2046 return false;
2047 }
2048 break;
2049
2050 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2051 if (!context->getExtensions().requestExtension)
2052 {
2053 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2054 return false;
2055 }
2056 if (index >= context->getRequestableExtensionStringCount())
2057 {
2058 context->handleError(
2059 Error(GL_INVALID_VALUE,
2060 "index must be less than the number of requestable extension strings."));
2061 return false;
2062 }
2063 break;
2064
2065 default:
2066 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2067 return false;
2068 }
2069
2070 return true;
2071}
2072
Jamie Madille8fb6402017-02-14 17:56:40 -05002073bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2074 GLenum target,
2075 GLsizei samples,
2076 GLenum internalformat,
2077 GLsizei width,
2078 GLsizei height)
2079{
2080 if (context->getClientMajorVersion() < 3)
2081 {
2082 context->handleError(Error(GL_INVALID_OPERATION));
2083 return false;
2084 }
2085
2086 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2087 height))
2088 {
2089 return false;
2090 }
2091
2092 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2093 // format if samples is greater than zero.
2094 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2095 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2096 samples > 0)
2097 {
2098 context->handleError(Error(GL_INVALID_OPERATION));
2099 return false;
2100 }
2101
2102 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2103 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2104 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2105 {
2106 context->handleError(
2107 Error(GL_INVALID_OPERATION,
2108 "Samples must not be greater than maximum supported value for the format."));
2109 return false;
2110 }
2111
2112 return true;
2113}
2114
Jamie Madillc29968b2016-01-20 11:17:23 -05002115} // namespace gl