blob: 1b1961f817fb69c387ae16ebf3ebc50fd97892df [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,
Geoff Langca271392017-04-05 12:30:00 -040028 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +080029 GLenum internalFormat,
30 GLenum format,
31 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040032{
Geoff Lang5d601382014-07-22 15:14:06 -040033
34 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -040035 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -040036 {
Geoff Lang6d1ccf02017-04-24 14:09:58 -040037 context->handleError(Error(GL_INVALID_ENUM, "Invalid format."));
38 return false;
39 }
40
41 if (!ValidES3Type(type))
42 {
43 context->handleError(Error(GL_INVALID_ENUM, "Invalid type."));
44 return false;
45 }
46
47 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
48 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
49 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
50 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
51 if (!ValidES3InternalFormat(internalFormat))
52 {
53 context->handleError(Error(GL_INVALID_VALUE, "Invalid internalFormat."));
Geoff Langb1196682014-07-23 13:47:29 -040054 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040055 }
56
Geoff Langca271392017-04-05 12:30:00 -040057 // From the ES 3.0 spec section 3.8.3:
58 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
59 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
60 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
61 // INVALID_OPERATION error.
62 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
63 {
64 context->handleError(Error(
65 GL_INVALID_OPERATION,
66 "Format cannot be GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL if target is GL_TEXTURE_3D"));
67 return false;
68 }
69
Geoff Lang5d601382014-07-22 15:14:06 -040070 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040071 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040072 {
Geoff Lang6d1ccf02017-04-24 14:09:58 -040073 context->handleError(
74 Error(GL_INVALID_OPERATION, "Invalid combination of format, type and internalFormat."));
75 return false;
76 }
77
78 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
79 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
80 {
81 context->handleError(Error(GL_INVALID_VALUE, "Unsupported internal format."));
Geoff Langb1196682014-07-23 13:47:29 -040082 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040083 }
84
85 return true;
86}
87
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050088bool ValidateES3TexImageParametersBase(Context *context,
89 GLenum target,
90 GLint level,
91 GLenum internalformat,
92 bool isCompressed,
93 bool isSubImage,
94 GLint xoffset,
95 GLint yoffset,
96 GLint zoffset,
97 GLsizei width,
98 GLsizei height,
99 GLsizei depth,
100 GLint border,
101 GLenum format,
102 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400103 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500104 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400105{
106 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700107 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108 {
Jamie Madill437fa652016-05-03 15:13:24 -0400109 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400110 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400111 }
112
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400113 // Verify zero border
114 if (border != 0)
115 {
Jamie Madill437fa652016-05-03 15:13:24 -0400116 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 }
119
Jamie Madill6f38f822014-06-06 17:12:20 -0400120 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
121 std::numeric_limits<GLsizei>::max() - xoffset < width ||
122 std::numeric_limits<GLsizei>::max() - yoffset < height ||
123 std::numeric_limits<GLsizei>::max() - zoffset < depth)
124 {
Jamie Madill437fa652016-05-03 15:13:24 -0400125 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400126 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400127 }
128
Geoff Langaae65a42014-05-26 12:43:44 -0400129 const gl::Caps &caps = context->getCaps();
130
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400131 switch (target)
132 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800133 case GL_TEXTURE_2D:
134 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
135 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
136 {
137 context->handleError(Error(GL_INVALID_VALUE));
138 return false;
139 }
140 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400141
He Yunchaoced53ae2016-11-29 15:00:51 +0800142 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
143 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
144 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
145 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
146 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
147 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
148 if (!isSubImage && width != height)
149 {
150 context->handleError(Error(GL_INVALID_VALUE));
151 return false;
152 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400153
He Yunchaoced53ae2016-11-29 15:00:51 +0800154 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
155 {
156 context->handleError(Error(GL_INVALID_VALUE));
157 return false;
158 }
159 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160
He Yunchaoced53ae2016-11-29 15:00:51 +0800161 case GL_TEXTURE_3D:
162 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
163 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
164 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
165 {
166 context->handleError(Error(GL_INVALID_VALUE));
167 return false;
168 }
169 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400170
He Yunchaoced53ae2016-11-29 15:00:51 +0800171 case GL_TEXTURE_2D_ARRAY:
172 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
173 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
174 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
175 {
176 context->handleError(Error(GL_INVALID_VALUE));
177 return false;
178 }
179 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400180
He Yunchaoced53ae2016-11-29 15:00:51 +0800181 default:
182 context->handleError(Error(GL_INVALID_ENUM));
183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400184 }
185
He Yunchaoced53ae2016-11-29 15:00:51 +0800186 gl::Texture *texture =
187 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400188 if (!texture)
189 {
Jamie Madill437fa652016-05-03 15:13:24 -0400190 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400191 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400192 }
193
Geoff Lang69cce582015-09-17 13:20:36 -0400194 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400195 {
Jamie Madill437fa652016-05-03 15:13:24 -0400196 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400198 }
199
200 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400201 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400202 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500203 if (isSubImage && actualInternalFormat == GL_NONE)
204 {
205 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
206 return false;
207 }
208
Geoff Langca271392017-04-05 12:30:00 -0400209 const gl::InternalFormat &actualFormatInfo =
210 gl::GetSizedInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400211 if (isCompressed)
212 {
tmartino7c102692015-10-02 16:43:40 -0400213 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400214 {
Jamie Madill437fa652016-05-03 15:13:24 -0400215 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400216 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400217 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400218 }
219
Geoff Lang966c9402017-04-18 12:38:27 -0400220 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400221 {
Geoff Lang966c9402017-04-18 12:38:27 -0400222 if (!ValidCompressedSubImageSize(
223 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
224 texture->getWidth(target, level), texture->getHeight(target, level)))
225 {
226 context->handleError(
227 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
228 return false;
229 }
230
231 if (format != actualInternalFormat)
232 {
233 context->handleError(Error(
234 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
235 return false;
236 }
237 }
238 else
239 {
240 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
241 {
242 context->handleError(
243 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
244 return false;
245 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 }
247
Geoff Langeb66a6e2016-10-31 13:06:12 -0400248 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400249 {
Jamie Madill437fa652016-05-03 15:13:24 -0400250 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400251 return false;
252 }
253
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400254 if (target == GL_TEXTURE_3D)
255 {
Jamie Madill437fa652016-05-03 15:13:24 -0400256 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400257 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258 }
259 }
260 else
261 {
Geoff Langca271392017-04-05 12:30:00 -0400262 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400263 {
Geoff Lang5d601382014-07-22 15:14:06 -0400264 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400265 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400266 }
267
268 // Validate sub image parameters
269 if (isSubImage)
270 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500271 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400272 {
Jamie Madill437fa652016-05-03 15:13:24 -0400273 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400274 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400275 }
276
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400277 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
278 {
Jamie Madill437fa652016-05-03 15:13:24 -0400279 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400280 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400281 }
282
283 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
284 std::numeric_limits<GLsizei>::max() - yoffset < height ||
285 std::numeric_limits<GLsizei>::max() - zoffset < depth)
286 {
Jamie Madill437fa652016-05-03 15:13:24 -0400287 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400288 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400289 }
290
Geoff Langa9be0dc2014-12-17 12:34:40 -0500291 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
292 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
293 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400294 {
Jamie Madill437fa652016-05-03 15:13:24 -0400295 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400296 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 }
298 }
299
Geoff Langff5b2d52016-09-07 11:32:23 -0400300 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
301 imageSize))
302 {
303 return false;
304 }
305
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400306 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700307 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400308 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400309 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800310 // ...data is not evenly divisible into the number of bytes needed to store in memory a
311 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400312 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400313 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400314 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400315 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400316 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
317
Geoff Langff5b2d52016-09-07 11:32:23 -0400318 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400319 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400320 context->handleError(
321 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400322 return false;
323 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400324 }
325
Jamie Madill7a5f7382014-03-05 15:01:24 -0500326 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700327 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500328 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400329 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400330 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500331 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400332 }
333
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400334 return true;
335}
336
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500337bool ValidateES3TexImage2DParameters(Context *context,
338 GLenum target,
339 GLint level,
340 GLenum internalformat,
341 bool isCompressed,
342 bool isSubImage,
343 GLint xoffset,
344 GLint yoffset,
345 GLint zoffset,
346 GLsizei width,
347 GLsizei height,
348 GLsizei depth,
349 GLint border,
350 GLenum format,
351 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400352 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500353 const GLvoid *pixels)
354{
355 if (!ValidTexture2DDestinationTarget(context, target))
356 {
Jamie Madill437fa652016-05-03 15:13:24 -0400357 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500358 return false;
359 }
360
361 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
362 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400363 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500364}
365
366bool ValidateES3TexImage3DParameters(Context *context,
367 GLenum target,
368 GLint level,
369 GLenum internalformat,
370 bool isCompressed,
371 bool isSubImage,
372 GLint xoffset,
373 GLint yoffset,
374 GLint zoffset,
375 GLsizei width,
376 GLsizei height,
377 GLsizei depth,
378 GLint border,
379 GLenum format,
380 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400381 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500382 const GLvoid *pixels)
383{
384 if (!ValidTexture3DDestinationTarget(context, target))
385 {
Jamie Madill437fa652016-05-03 15:13:24 -0400386 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500387 return false;
388 }
389
390 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
391 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400392 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500393}
394
Geoff Lang5d601382014-07-22 15:14:06 -0400395struct EffectiveInternalFormatInfo
396{
Jamie Madill76648fe2016-10-05 17:01:41 -0400397 GLenum effectiveFormat;
398 GLenum destFormat;
399 GLuint minRedBits;
400 GLuint maxRedBits;
401 GLuint minGreenBits;
402 GLuint maxGreenBits;
403 GLuint minBlueBits;
404 GLuint maxBlueBits;
405 GLuint minAlphaBits;
406 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400407};
408
Jamie Madill76648fe2016-10-05 17:01:41 -0400409static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
410 GLenum targetFormat,
411 const EffectiveInternalFormatInfo *list,
412 size_t size,
413 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400414{
Jamie Madill76648fe2016-10-05 17:01:41 -0400415 for (size_t curFormat = 0; curFormat < size; ++curFormat)
416 {
417 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
418 if ((formatInfo.destFormat == targetFormat) &&
419 (formatInfo.minRedBits <= srcFormat.redBits &&
420 formatInfo.maxRedBits >= srcFormat.redBits) &&
421 (formatInfo.minGreenBits <= srcFormat.greenBits &&
422 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
423 (formatInfo.minBlueBits <= srcFormat.blueBits &&
424 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
425 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
426 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
427 {
428 *outEffectiveFormat = formatInfo.effectiveFormat;
429 return true;
430 }
431 }
Geoff Lang5d601382014-07-22 15:14:06 -0400432
Jamie Madill76648fe2016-10-05 17:01:41 -0400433 *outEffectiveFormat = GL_NONE;
434 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400435}
436
Jamie Madill76648fe2016-10-05 17:01:41 -0400437bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
438 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400439{
Jamie Madill76648fe2016-10-05 17:01:41 -0400440 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
441 // Effective internal format coresponding to destination internal format and linear source
442 // buffer component sizes.
443 // | Source channel min/max sizes |
444 // Effective Internal Format | N/A | R | G | B | A |
445 // clang-format off
446 constexpr EffectiveInternalFormatInfo list[] = {
447 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
448 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
449 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
450 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
451 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
452 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
453 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
454 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
455 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
456 };
457 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400458
Jamie Madill76648fe2016-10-05 17:01:41 -0400459 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
460}
Geoff Lang5d601382014-07-22 15:14:06 -0400461
Jamie Madill76648fe2016-10-05 17:01:41 -0400462bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
463 const InternalFormat &destFormat,
464 GLenum *outEffectiveFormat)
465{
466 constexpr GLuint umax = UINT_MAX;
467
468 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
469 // Effective internal format coresponding to destination internal format andlinear source buffer
470 // component sizes.
471 // | Source channel min/max sizes |
472 // Effective Internal Format | Dest Format | R | G | B | A |
473 // clang-format off
474 constexpr EffectiveInternalFormatInfo list[] = {
475 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
476 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
477 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
478 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
479 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
480 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
481 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
482 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
483 };
484 // clang-format on
485
486 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
487 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400488}
489
He Yunchaoced53ae2016-11-29 15:00:51 +0800490static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
491 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400492 GLenum *outEffectiveFormat)
493{
Geoff Langca271392017-04-05 12:30:00 -0400494 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400495 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400496 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400497 }
498 else
499 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400500 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400501 }
Geoff Lang5d601382014-07-22 15:14:06 -0400502}
503
Corentin Wallez76287682016-04-25 09:23:38 -0400504static bool EqualOrFirstZero(GLuint first, GLuint second)
505{
506 return first == 0 || first == second;
507}
508
Geoff Langca271392017-04-05 12:30:00 -0400509static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
510 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400511 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400512{
Jamie Madill21b786b2016-11-01 17:41:31 -0400513 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400514 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400515 return false;
516 }
Geoff Lang5d601382014-07-22 15:14:06 -0400517
Jamie Madill21b786b2016-11-01 17:41:31 -0400518 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
519 // must both be signed, unsigned, or fixed point and both source and destinations
520 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
521 // conversion between fixed and floating point.
522
523 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
524 (framebufferFormatInfo.colorEncoding == GL_SRGB))
525 {
526 return false;
527 }
528
529 if (((textureFormatInfo.componentType == GL_INT) !=
530 (framebufferFormatInfo.componentType == GL_INT)) ||
531 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
532 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
533 {
534 return false;
535 }
536
537 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
538 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
539 textureFormatInfo.componentType == GL_FLOAT) &&
540 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
541 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
542 framebufferFormatInfo.componentType == GL_FLOAT))
543 {
544 return false;
545 }
546
547 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
548 // The effective internal format of the source buffer is determined with the following rules
549 // applied in order:
550 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
551 // format then the effective internal format is the source buffer's sized internal format.
552 // * If the source buffer is a texture that was created with an unsized base internal format,
553 // then the effective internal format is the source image array's effective internal
554 // format, as specified by table 3.12, which is determined from the <format> and <type>
555 // that were used when the source image array was specified by TexImage*.
556 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
557 // where Destination Internal Format matches internalformat and where the [source channel
558 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
559 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
560 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800561 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400562 if (readBufferHandle != 0)
563 {
564 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
565 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400566 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400567 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400568 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400569 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400570 else
Geoff Lang5d601382014-07-22 15:14:06 -0400571 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400572 // Renderbuffers cannot be created with an unsized internal format, so this must be an
573 // unsized-format texture. We can use the same table we use when creating textures to
574 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400575 sourceEffectiveFormat =
576 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400577 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400578 }
579 else
580 {
581 // The effective internal format must be derived from the source framebuffer's channel
582 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
583 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400584 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400585 GLenum effectiveFormat;
586 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
587 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400588 {
Geoff Langca271392017-04-05 12:30:00 -0400589 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400590 }
591 else
592 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400593 return false;
594 }
595 }
596 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
597 {
598 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400599 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400600 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
601 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
602 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
603 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
604 {
Geoff Langca271392017-04-05 12:30:00 -0400605 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400606 }
607 else
608 {
609 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400610 }
611 }
612 else
613 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400614 UNREACHABLE();
615 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400616 }
Geoff Lang5d601382014-07-22 15:14:06 -0400617 }
618
Geoff Langca271392017-04-05 12:30:00 -0400619 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400620 {
621 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
622 // sized, component sizes of the source and destination formats must exactly match if the
623 // destination format exists.
624 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
625 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
626 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
627 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
628 {
629 return false;
630 }
631 }
632
633 return true; // A conversion function exists, and no rule in the specification has precluded
634 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400635}
636
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500637bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
638 GLenum target,
639 GLint level,
640 GLenum internalformat,
641 bool isSubImage,
642 GLint xoffset,
643 GLint yoffset,
644 GLint zoffset,
645 GLint x,
646 GLint y,
647 GLsizei width,
648 GLsizei height,
649 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400651 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400652 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400653 xoffset, yoffset, zoffset, x, y, width, height, border,
654 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400655 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400656 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400657 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400658 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400659
Jamie Madill51f40ec2016-06-15 14:06:00 -0400660 const auto &state = context->getGLState();
661 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
662 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400663
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400664 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400665 {
Jamie Madill437fa652016-05-03 15:13:24 -0400666 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400667 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400668 }
669
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400670 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400671 {
Jamie Madill437fa652016-05-03 15:13:24 -0400672 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400673 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400674 }
675
Jamie Madill0c8abca2016-07-22 20:21:26 -0400676 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400677
678 if (isSubImage)
679 {
Geoff Langca271392017-04-05 12:30:00 -0400680 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500681 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 {
Jamie Madill437fa652016-05-03 15:13:24 -0400683 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400684 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400685 }
686 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400687 else
688 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400689 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400690 const InternalFormat &framebufferFormat = *source->getFormat().info;
691 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400692 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400693 {
Jamie Madill437fa652016-05-03 15:13:24 -0400694 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400695 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400696 }
697 }
698
Geoff Lang784a8fd2013-09-24 12:33:16 -0400699 // If width or height is zero, it is a no-op. Return false without setting an error.
700 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701}
702
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500703bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
704 GLenum target,
705 GLint level,
706 GLenum internalformat,
707 bool isSubImage,
708 GLint xoffset,
709 GLint yoffset,
710 GLint zoffset,
711 GLint x,
712 GLint y,
713 GLsizei width,
714 GLsizei height,
715 GLint border)
716{
717 if (!ValidTexture2DDestinationTarget(context, target))
718 {
Jamie Madill437fa652016-05-03 15:13:24 -0400719 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500720 return false;
721 }
722
723 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
724 xoffset, yoffset, zoffset, x, y, width, height,
725 border);
726}
727
728bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
729 GLenum target,
730 GLint level,
731 GLenum internalformat,
732 bool isSubImage,
733 GLint xoffset,
734 GLint yoffset,
735 GLint zoffset,
736 GLint x,
737 GLint y,
738 GLsizei width,
739 GLsizei height,
740 GLint border)
741{
742 if (!ValidTexture3DDestinationTarget(context, target))
743 {
Jamie Madill437fa652016-05-03 15:13:24 -0400744 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500745 return false;
746 }
747
748 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
749 xoffset, yoffset, zoffset, x, y, width, height,
750 border);
751}
752
753bool ValidateES3TexStorageParametersBase(Context *context,
754 GLenum target,
755 GLsizei levels,
756 GLenum internalformat,
757 GLsizei width,
758 GLsizei height,
759 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760{
761 if (width < 1 || height < 1 || depth < 1 || levels < 1)
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 Langb92c1332015-09-04 12:54:55 -0400767 GLsizei maxDim = std::max(width, height);
768 if (target != GL_TEXTURE_2D_ARRAY)
769 {
770 maxDim = std::max(maxDim, depth);
771 }
772
773 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400774 {
Jamie Madill437fa652016-05-03 15:13:24 -0400775 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400776 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777 }
778
Geoff Langaae65a42014-05-26 12:43:44 -0400779 const gl::Caps &caps = context->getCaps();
780
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400781 switch (target)
782 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784 {
Geoff Langaae65a42014-05-26 12:43:44 -0400785 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
786 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 {
Jamie Madill437fa652016-05-03 15:13:24 -0400788 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 }
791 }
792 break;
793
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 if (width != height)
797 {
Jamie Madill437fa652016-05-03 15:13:24 -0400798 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400799 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400800 }
801
Geoff Langaae65a42014-05-26 12:43:44 -0400802 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 {
Jamie Madill437fa652016-05-03 15:13:24 -0400804 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400805 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 }
807 }
808 break;
809
He Yunchaoced53ae2016-11-29 15:00:51 +0800810 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 {
Geoff Langaae65a42014-05-26 12:43:44 -0400812 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
813 static_cast<GLuint>(height) > caps.max3DTextureSize ||
814 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 {
Jamie Madill437fa652016-05-03 15:13:24 -0400816 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400817 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 }
819 }
820 break;
821
He Yunchaoced53ae2016-11-29 15:00:51 +0800822 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400823 {
Geoff Langaae65a42014-05-26 12:43:44 -0400824 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
825 static_cast<GLuint>(height) > caps.max2DTextureSize ||
826 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 {
Jamie Madill437fa652016-05-03 15:13:24 -0400828 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 }
831 }
832 break;
833
He Yunchaoced53ae2016-11-29 15:00:51 +0800834 default:
835 UNREACHABLE();
836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 }
838
Geoff Lang691e58c2014-12-19 17:03:25 -0500839 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 if (!texture || texture->id() == 0)
841 {
Jamie Madill437fa652016-05-03 15:13:24 -0400842 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
845
Geoff Lang69cce582015-09-17 13:20:36 -0400846 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851
Geoff Langca271392017-04-05 12:30:00 -0400852 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400853 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 {
Jamie Madill437fa652016-05-03 15:13:24 -0400855 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858
Geoff Langca271392017-04-05 12:30:00 -0400859 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Jamie Madill437fa652016-05-03 15:13:24 -0400861 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 }
864
865 return true;
866}
867
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500868bool ValidateES3TexStorage2DParameters(Context *context,
869 GLenum target,
870 GLsizei levels,
871 GLenum internalformat,
872 GLsizei width,
873 GLsizei height,
874 GLsizei depth)
875{
876 if (!ValidTexture2DTarget(context, target))
877 {
Jamie Madill437fa652016-05-03 15:13:24 -0400878 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500879 return false;
880 }
881
882 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
883 height, depth);
884}
885
886bool ValidateES3TexStorage3DParameters(Context *context,
887 GLenum target,
888 GLsizei levels,
889 GLenum internalformat,
890 GLsizei width,
891 GLsizei height,
892 GLsizei depth)
893{
894 if (!ValidTexture3DTarget(context, target))
895 {
Jamie Madill437fa652016-05-03 15:13:24 -0400896 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500897 return false;
898 }
899
900 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
901 height, depth);
902}
903
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500904bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
905{
Martin Radev1be913c2016-07-11 17:59:16 +0300906 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500907 {
Jamie Madill437fa652016-05-03 15:13:24 -0400908 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500909 return false;
910 }
911
912 return ValidateBeginQueryBase(context, target, id);
913}
914
915bool ValidateEndQuery(gl::Context *context, GLenum target)
916{
Martin Radev1be913c2016-07-11 17:59:16 +0300917 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500918 {
Jamie Madill437fa652016-05-03 15:13:24 -0400919 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500920 return false;
921 }
922
923 return ValidateEndQueryBase(context, target);
924}
925
926bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
927{
Martin Radev1be913c2016-07-11 17:59:16 +0300928 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500929 {
Jamie Madill437fa652016-05-03 15:13:24 -0400930 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500931 return false;
932 }
933
Geoff Lang2186c382016-10-14 10:54:54 -0400934 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500935}
936
937bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
938{
Martin Radev1be913c2016-07-11 17:59:16 +0300939 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500940 {
Jamie Madill437fa652016-05-03 15:13:24 -0400941 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500942 return false;
943 }
944
Geoff Lang2186c382016-10-14 10:54:54 -0400945 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500946}
947
He Yunchaoced53ae2016-11-29 15:00:51 +0800948bool ValidateFramebufferTextureLayer(Context *context,
949 GLenum target,
950 GLenum attachment,
951 GLuint texture,
952 GLint level,
953 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400954{
Martin Radev1be913c2016-07-11 17:59:16 +0300955 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400956 {
Jamie Madill437fa652016-05-03 15:13:24 -0400957 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400958 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400959 }
960
Jamie Madill55ec3b12014-07-03 10:38:57 -0400961 if (layer < 0)
962 {
Jamie Madill437fa652016-05-03 15:13:24 -0400963 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400964 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400965 }
966
967 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
968 {
969 return false;
970 }
971
972 const gl::Caps &caps = context->getCaps();
973 if (texture != 0)
974 {
975 gl::Texture *tex = context->getTexture(texture);
976 ASSERT(tex);
977
978 switch (tex->getTarget())
979 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400981 {
982 if (level > gl::log2(caps.max2DTextureSize))
983 {
Jamie Madill437fa652016-05-03 15:13:24 -0400984 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400985 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400986 }
987
988 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
989 {
Jamie Madill437fa652016-05-03 15:13:24 -0400990 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400991 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400992 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400993 }
994 break;
995
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400997 {
998 if (level > gl::log2(caps.max3DTextureSize))
999 {
Jamie Madill437fa652016-05-03 15:13:24 -04001000 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001002 }
1003
1004 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1005 {
Jamie Madill437fa652016-05-03 15:13:24 -04001006 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001008 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001009 }
1010 break;
1011
He Yunchaoced53ae2016-11-29 15:00:51 +08001012 default:
1013 context->handleError(Error(GL_INVALID_OPERATION));
1014 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001015 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001016
Jamie Madilla3944d42016-07-22 22:13:26 -04001017 const auto &format = tex->getFormat(tex->getTarget(), level);
1018 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001019 {
Jamie Madill437fa652016-05-03 15:13:24 -04001020 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001021 return false;
1022 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001023 }
1024
1025 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001026}
1027
He Yunchaoced53ae2016-11-29 15:00:51 +08001028bool ValidateInvalidateFramebuffer(Context *context,
1029 GLenum target,
1030 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001031 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032{
Martin Radev1be913c2016-07-11 17:59:16 +03001033 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001034 {
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(
1036 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001037 return false;
1038 }
1039
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 bool defaultFramebuffer = false;
1041
1042 switch (target)
1043 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001044 case GL_DRAW_FRAMEBUFFER:
1045 case GL_FRAMEBUFFER:
1046 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1047 break;
1048 case GL_READ_FRAMEBUFFER:
1049 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1050 break;
1051 default:
1052 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 }
1055
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1057 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058}
1059
Jamie Madillc29968b2016-01-20 11:17:23 -05001060bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001061{
Martin Radev1be913c2016-07-11 17:59:16 +03001062 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001063 {
Jamie Madill437fa652016-05-03 15:13:24 -04001064 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001065 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001066 }
1067
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001068 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001069 {
Jamie Madill437fa652016-05-03 15:13:24 -04001070 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001071 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001072 }
1073
1074 return true;
1075}
1076
Olli Etuaho71dfb362016-03-10 14:04:27 +02001077bool ValidateDrawRangeElements(Context *context,
1078 GLenum mode,
1079 GLuint start,
1080 GLuint end,
1081 GLsizei count,
1082 GLenum type,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001083 const GLvoid *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001084{
Martin Radev1be913c2016-07-11 17:59:16 +03001085 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001086 {
Jamie Madill437fa652016-05-03 15:13:24 -04001087 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001088 return false;
1089 }
1090
1091 if (end < start)
1092 {
Jamie Madill437fa652016-05-03 15:13:24 -04001093 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001094 return false;
1095 }
1096
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001097 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001098 {
1099 return false;
1100 }
1101
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001102 // Use the parameter buffer to retrieve and cache the index range.
1103 const auto &params = context->getParams<HasIndexRange>();
1104 const auto &indexRangeOpt = params.getIndexRange();
1105 if (!indexRangeOpt.valid())
1106 {
1107 // Unexpected error.
1108 return false;
1109 }
1110
1111 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001112 {
1113 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001114 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001115 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1116 return false;
1117 }
1118 return true;
1119}
1120
He Yunchaoced53ae2016-11-29 15:00:51 +08001121bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001122{
Martin Radev1be913c2016-07-11 17:59:16 +03001123 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001124 {
Jamie Madill437fa652016-05-03 15:13:24 -04001125 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001126 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001127 }
1128
Jamie Madill78f41802014-08-25 15:47:55 -04001129 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001130}
1131
Jamie Madillb885e572015-02-03 16:16:04 -05001132bool ValidateReadBuffer(Context *context, GLenum src)
1133{
Martin Radev1be913c2016-07-11 17:59:16 +03001134 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001135 {
Jamie Madill437fa652016-05-03 15:13:24 -04001136 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001137 return false;
1138 }
1139
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001140 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001141
1142 if (readFBO == nullptr)
1143 {
Jamie Madill437fa652016-05-03 15:13:24 -04001144 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001145 return false;
1146 }
1147
1148 if (src == GL_NONE)
1149 {
1150 return true;
1151 }
1152
Olli Etuaho84c9f592016-03-09 14:37:25 +02001153 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001154 {
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001156 return false;
1157 }
1158
1159 if (readFBO->id() == 0)
1160 {
1161 if (src != GL_BACK)
1162 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 const char *errorMsg =
1164 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001166 return false;
1167 }
1168 }
1169 else
1170 {
1171 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1172
1173 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1174 {
1175 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001177 return false;
1178 }
1179 }
1180
1181 return true;
1182}
1183
Jamie Madill86af3d22015-07-21 15:14:07 -04001184bool ValidateCompressedTexImage3D(Context *context,
1185 GLenum target,
1186 GLint level,
1187 GLenum internalformat,
1188 GLsizei width,
1189 GLsizei height,
1190 GLsizei depth,
1191 GLint border,
1192 GLsizei imageSize,
1193 const GLvoid *data)
1194{
Martin Radev1be913c2016-07-11 17:59:16 +03001195 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001196 {
Jamie Madill437fa652016-05-03 15:13:24 -04001197 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001198 return false;
1199 }
1200
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001201 if (!ValidTextureTarget(context, target))
1202 {
1203 context->handleError(Error(GL_INVALID_ENUM));
1204 return false;
1205 }
1206
Jamie Madille2e406c2016-06-02 13:04:10 -04001207 // Validate image size
1208 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1209 {
1210 context->handleError(Error(GL_INVALID_VALUE));
1211 return false;
1212 }
1213
Geoff Langca271392017-04-05 12:30:00 -04001214 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001215 if (!formatInfo.compressed)
1216 {
1217 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1218 return false;
1219 }
1220
Jamie Madill513558d2016-06-02 13:04:11 -04001221 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001222 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001223 if (blockSizeOrErr.isError())
1224 {
Jamie Madill513558d2016-06-02 13:04:11 -04001225 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001226 return false;
1227 }
1228 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001231 return false;
1232 }
1233
1234 // 3D texture target validation
1235 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1236 {
Jamie Madill437fa652016-05-03 15:13:24 -04001237 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001238 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1239 return false;
1240 }
1241
1242 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001243 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001244 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1245 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001246 {
1247 return false;
1248 }
1249
1250 return true;
1251}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001252
Corentin Wallezb2931602017-04-11 15:58:57 -04001253bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1254 GLenum target,
1255 GLint level,
1256 GLenum internalformat,
1257 GLsizei width,
1258 GLsizei height,
1259 GLsizei depth,
1260 GLint border,
1261 GLsizei imageSize,
1262 GLsizei dataSize,
1263 const GLvoid *data)
1264{
1265 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1266 {
1267 return false;
1268 }
1269
1270 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1271 depth, border, imageSize, data);
1272}
1273
Austin Kinrossbc781f32015-10-26 09:27:38 -07001274bool ValidateBindVertexArray(Context *context, GLuint array)
1275{
Martin Radev1be913c2016-07-11 17:59:16 +03001276 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001277 {
Jamie Madill437fa652016-05-03 15:13:24 -04001278 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001279 return false;
1280 }
1281
1282 return ValidateBindVertexArrayBase(context, array);
1283}
1284
Austin Kinrossbc781f32015-10-26 09:27:38 -07001285bool ValidateIsVertexArray(Context *context)
1286{
Martin Radev1be913c2016-07-11 17:59:16 +03001287 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001288 {
Jamie Madill437fa652016-05-03 15:13:24 -04001289 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001290 return false;
1291 }
1292
1293 return true;
1294}
Geoff Langc5629752015-12-07 16:29:04 -05001295
Jiajia Qin6eafb042016-12-27 17:04:07 +08001296static bool ValidateBindBufferCommon(Context *context,
1297 GLenum target,
1298 GLuint index,
1299 GLuint buffer,
1300 GLintptr offset,
1301 GLsizeiptr size)
1302{
1303 if (context->getClientMajorVersion() < 3)
1304 {
1305 context->handleError(Error(GL_INVALID_OPERATION));
1306 return false;
1307 }
1308
1309 if (buffer != 0 && offset < 0)
1310 {
1311 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1312 return false;
1313 }
1314
1315 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1316 !context->isBufferGenerated(buffer))
1317 {
1318 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1319 return false;
1320 }
1321
1322 const Caps &caps = context->getCaps();
1323 switch (target)
1324 {
1325 case GL_TRANSFORM_FEEDBACK_BUFFER:
1326 {
1327 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1328 {
1329 context->handleError(Error(GL_INVALID_VALUE,
1330 "index is greater than or equal to the number of "
1331 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1332 return false;
1333 }
1334 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1335 {
1336 context->handleError(
1337 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1338 return false;
1339 }
1340
1341 TransformFeedback *curTransformFeedback =
1342 context->getGLState().getCurrentTransformFeedback();
1343 if (curTransformFeedback && curTransformFeedback->isActive())
1344 {
1345 context->handleError(Error(GL_INVALID_OPERATION,
1346 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1347 "feedback is currently active."));
1348 return false;
1349 }
1350 break;
1351 }
1352 case GL_UNIFORM_BUFFER:
1353 {
1354 if (index >= caps.maxUniformBufferBindings)
1355 {
1356 context->handleError(Error(GL_INVALID_VALUE,
1357 "index is greater than or equal to the number of "
1358 "UNIFORM_BUFFER indexed binding points."));
1359 return false;
1360 }
1361
1362 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1363 {
1364 context->handleError(
1365 Error(GL_INVALID_VALUE,
1366 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1367 return false;
1368 }
1369 break;
1370 }
1371 case GL_ATOMIC_COUNTER_BUFFER:
1372 {
1373 if (context->getClientVersion() < ES_3_1)
1374 {
Yunchao He61afff12017-03-14 15:34:03 +08001375 context->handleError(Error(
1376 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001377 return false;
1378 }
1379 if (index >= caps.maxAtomicCounterBufferBindings)
1380 {
1381 context->handleError(Error(GL_INVALID_VALUE,
1382 "index is greater than or equal to the number of "
1383 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1384 return false;
1385 }
1386 if (buffer != 0 && (offset % 4) != 0)
1387 {
1388 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1389 return false;
1390 }
1391 break;
1392 }
1393 case GL_SHADER_STORAGE_BUFFER:
1394 {
1395 if (context->getClientVersion() < ES_3_1)
1396 {
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001397 context->handleError(
1398 Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
1399 return false;
1400 }
1401 if (index >= caps.maxShaderStorageBufferBindings)
1402 {
1403 context->handleError(Error(GL_INVALID_VALUE,
1404 "index is greater than or equal to the number of "
1405 "SHADER_STORAGE_BUFFER indexed binding points."));
1406 return false;
1407 }
1408 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1409 {
Yunchao He61afff12017-03-14 15:34:03 +08001410 context->handleError(Error(
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001411 GL_INVALID_VALUE,
1412 "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001413 return false;
1414 }
1415 break;
1416 }
1417 default:
1418 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1419 return false;
1420 }
1421
1422 return true;
1423}
1424
1425bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1426{
1427 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1428}
1429
1430bool ValidateBindBufferRange(Context *context,
1431 GLenum target,
1432 GLuint index,
1433 GLuint buffer,
1434 GLintptr offset,
1435 GLsizeiptr size)
1436{
1437 if (buffer != 0 && size <= 0)
1438 {
1439 context->handleError(
1440 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1441 return false;
1442 }
1443 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1444}
1445
Geoff Langc5629752015-12-07 16:29:04 -05001446bool ValidateProgramBinary(Context *context,
1447 GLuint program,
1448 GLenum binaryFormat,
1449 const void *binary,
1450 GLint length)
1451{
Martin Radev1be913c2016-07-11 17:59:16 +03001452 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001453 {
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001455 return false;
1456 }
1457
1458 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1459}
1460
1461bool ValidateGetProgramBinary(Context *context,
1462 GLuint program,
1463 GLsizei bufSize,
1464 GLsizei *length,
1465 GLenum *binaryFormat,
1466 void *binary)
1467{
Martin Radev1be913c2016-07-11 17:59:16 +03001468 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001469 {
Jamie Madill437fa652016-05-03 15:13:24 -04001470 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001471 return false;
1472 }
1473
1474 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1475}
1476
Olli Etuahof0fee072016-03-30 15:11:58 +03001477bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001478{
Martin Radev1be913c2016-07-11 17:59:16 +03001479 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001480 {
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001482 return false;
1483 }
1484
1485 if (GetValidProgram(context, program) == nullptr)
1486 {
1487 return false;
1488 }
1489
1490 switch (pname)
1491 {
1492 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001493 if (value != GL_FALSE && value != GL_TRUE)
1494 {
Jamie Madill437fa652016-05-03 15:13:24 -04001495 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001496 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1497 return false;
1498 }
Geoff Langc5629752015-12-07 16:29:04 -05001499 break;
1500
Yunchao He61afff12017-03-14 15:34:03 +08001501 case GL_PROGRAM_SEPARABLE:
1502 if (context->getClientVersion() < ES_3_1)
1503 {
1504 context->handleError(
1505 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1506 return false;
1507 }
1508
1509 if (value != GL_FALSE && value != GL_TRUE)
1510 {
1511 context->handleError(Error(
1512 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1513 return false;
1514 }
1515 break;
1516
Geoff Langc5629752015-12-07 16:29:04 -05001517 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001518 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001519 return false;
1520 }
1521
1522 return true;
1523}
Jamie Madillc29968b2016-01-20 11:17:23 -05001524
1525bool ValidateBlitFramebuffer(Context *context,
1526 GLint srcX0,
1527 GLint srcY0,
1528 GLint srcX1,
1529 GLint srcY1,
1530 GLint dstX0,
1531 GLint dstY0,
1532 GLint dstX1,
1533 GLint dstY1,
1534 GLbitfield mask,
1535 GLenum filter)
1536{
Martin Radev1be913c2016-07-11 17:59:16 +03001537 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001538 {
Jamie Madill437fa652016-05-03 15:13:24 -04001539 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001540 return false;
1541 }
1542
1543 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1544 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545}
Jamie Madillc29968b2016-01-20 11:17:23 -05001546
1547bool ValidateClearBufferiv(ValidationContext *context,
1548 GLenum buffer,
1549 GLint drawbuffer,
1550 const GLint *value)
1551{
1552 switch (buffer)
1553 {
1554 case GL_COLOR:
1555 if (drawbuffer < 0 ||
1556 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1557 {
Jamie Madill437fa652016-05-03 15:13:24 -04001558 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001559 return false;
1560 }
Geoff Lang76e65652017-03-27 14:58:02 -04001561 if (context->getExtensions().webglCompatibility)
1562 {
1563 constexpr GLenum validComponentTypes[] = {GL_INT};
1564 if (ValidateWebGLFramebufferAttachmentClearType(
1565 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1566 {
1567 return false;
1568 }
1569 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001570 break;
1571
1572 case GL_STENCIL:
1573 if (drawbuffer != 0)
1574 {
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001576 return false;
1577 }
1578 break;
1579
1580 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001581 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001582 return false;
1583 }
1584
1585 return ValidateClearBuffer(context);
1586}
1587
1588bool ValidateClearBufferuiv(ValidationContext *context,
1589 GLenum buffer,
1590 GLint drawbuffer,
1591 const GLuint *value)
1592{
1593 switch (buffer)
1594 {
1595 case GL_COLOR:
1596 if (drawbuffer < 0 ||
1597 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001600 return false;
1601 }
Geoff Lang76e65652017-03-27 14:58:02 -04001602 if (context->getExtensions().webglCompatibility)
1603 {
1604 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1605 if (ValidateWebGLFramebufferAttachmentClearType(
1606 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1607 {
1608 return false;
1609 }
1610 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 break;
1612
1613 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001614 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001615 return false;
1616 }
1617
1618 return ValidateClearBuffer(context);
1619}
1620
1621bool ValidateClearBufferfv(ValidationContext *context,
1622 GLenum buffer,
1623 GLint drawbuffer,
1624 const GLfloat *value)
1625{
1626 switch (buffer)
1627 {
1628 case GL_COLOR:
1629 if (drawbuffer < 0 ||
1630 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001633 return false;
1634 }
Geoff Lang76e65652017-03-27 14:58:02 -04001635 if (context->getExtensions().webglCompatibility)
1636 {
1637 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1638 GL_SIGNED_NORMALIZED};
1639 if (ValidateWebGLFramebufferAttachmentClearType(
1640 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1641 {
1642 return false;
1643 }
1644 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001645 break;
1646
1647 case GL_DEPTH:
1648 if (drawbuffer != 0)
1649 {
Jamie Madill437fa652016-05-03 15:13:24 -04001650 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001651 return false;
1652 }
1653 break;
1654
1655 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001657 return false;
1658 }
1659
1660 return ValidateClearBuffer(context);
1661}
1662
1663bool ValidateClearBufferfi(ValidationContext *context,
1664 GLenum buffer,
1665 GLint drawbuffer,
1666 GLfloat depth,
1667 GLint stencil)
1668{
1669 switch (buffer)
1670 {
1671 case GL_DEPTH_STENCIL:
1672 if (drawbuffer != 0)
1673 {
Jamie Madill437fa652016-05-03 15:13:24 -04001674 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001675 return false;
1676 }
1677 break;
1678
1679 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001680 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001681 return false;
1682 }
1683
1684 return ValidateClearBuffer(context);
1685}
1686
1687bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1688{
Martin Radev1be913c2016-07-11 17:59:16 +03001689 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001690 {
Jamie Madill437fa652016-05-03 15:13:24 -04001691 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001692 return false;
1693 }
1694
1695 return ValidateDrawBuffersBase(context, n, bufs);
1696}
1697
1698bool ValidateCopyTexSubImage3D(Context *context,
1699 GLenum target,
1700 GLint level,
1701 GLint xoffset,
1702 GLint yoffset,
1703 GLint zoffset,
1704 GLint x,
1705 GLint y,
1706 GLsizei width,
1707 GLsizei height)
1708{
Martin Radev1be913c2016-07-11 17:59:16 +03001709 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001712 return false;
1713 }
1714
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001715 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1716 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001717}
1718
Jamie Madill73a84962016-02-12 09:27:23 -05001719bool ValidateTexImage3D(Context *context,
1720 GLenum target,
1721 GLint level,
1722 GLint internalformat,
1723 GLsizei width,
1724 GLsizei height,
1725 GLsizei depth,
1726 GLint border,
1727 GLenum format,
1728 GLenum type,
1729 const GLvoid *pixels)
1730{
Martin Radev1be913c2016-07-11 17:59:16 +03001731 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001732 {
Jamie Madill437fa652016-05-03 15:13:24 -04001733 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001734 return false;
1735 }
1736
1737 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001738 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001739 pixels);
1740}
1741
Geoff Langc52f6f12016-10-14 10:18:00 -04001742bool ValidateTexImage3DRobustANGLE(Context *context,
1743 GLenum target,
1744 GLint level,
1745 GLint internalformat,
1746 GLsizei width,
1747 GLsizei height,
1748 GLsizei depth,
1749 GLint border,
1750 GLenum format,
1751 GLenum type,
1752 GLsizei bufSize,
1753 const GLvoid *pixels)
1754{
1755 if (context->getClientMajorVersion() < 3)
1756 {
1757 context->handleError(Error(GL_INVALID_OPERATION));
1758 return false;
1759 }
1760
1761 if (!ValidateRobustEntryPoint(context, bufSize))
1762 {
1763 return false;
1764 }
1765
1766 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1767 0, 0, width, height, depth, border, format, type,
1768 bufSize, pixels);
1769}
1770
Jamie Madill73a84962016-02-12 09:27:23 -05001771bool ValidateTexSubImage3D(Context *context,
1772 GLenum target,
1773 GLint level,
1774 GLint xoffset,
1775 GLint yoffset,
1776 GLint zoffset,
1777 GLsizei width,
1778 GLsizei height,
1779 GLsizei depth,
1780 GLenum format,
1781 GLenum type,
1782 const GLvoid *pixels)
1783{
Martin Radev1be913c2016-07-11 17:59:16 +03001784 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001785 {
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001787 return false;
1788 }
1789
1790 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1791 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001792 -1, pixels);
1793}
1794
1795bool ValidateTexSubImage3DRobustANGLE(Context *context,
1796 GLenum target,
1797 GLint level,
1798 GLint xoffset,
1799 GLint yoffset,
1800 GLint zoffset,
1801 GLsizei width,
1802 GLsizei height,
1803 GLsizei depth,
1804 GLenum format,
1805 GLenum type,
1806 GLsizei bufSize,
1807 const GLvoid *pixels)
1808{
1809 if (context->getClientMajorVersion() < 3)
1810 {
1811 context->handleError(Error(GL_INVALID_OPERATION));
1812 return false;
1813 }
1814
1815 if (!ValidateRobustEntryPoint(context, bufSize))
1816 {
1817 return false;
1818 }
1819
1820 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1821 yoffset, zoffset, width, height, depth, 0, format, type,
1822 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001823}
1824
1825bool ValidateCompressedTexSubImage3D(Context *context,
1826 GLenum target,
1827 GLint level,
1828 GLint xoffset,
1829 GLint yoffset,
1830 GLint zoffset,
1831 GLsizei width,
1832 GLsizei height,
1833 GLsizei depth,
1834 GLenum format,
1835 GLsizei imageSize,
1836 const GLvoid *data)
1837{
Martin Radev1be913c2016-07-11 17:59:16 +03001838 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001839 {
Jamie Madill437fa652016-05-03 15:13:24 -04001840 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001841 return false;
1842 }
1843
Geoff Langca271392017-04-05 12:30:00 -04001844 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001845 if (!formatInfo.compressed)
1846 {
1847 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1848 return false;
1849 }
1850
Jamie Madill513558d2016-06-02 13:04:11 -04001851 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001852 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001853 if (blockSizeOrErr.isError())
1854 {
1855 context->handleError(blockSizeOrErr.getError());
1856 return false;
1857 }
1858 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001859 {
Jamie Madill437fa652016-05-03 15:13:24 -04001860 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001861 return false;
1862 }
1863
1864 if (!data)
1865 {
Jamie Madill437fa652016-05-03 15:13:24 -04001866 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001867 return false;
1868 }
1869
1870 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001871 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001872}
Corentin Wallezb2931602017-04-11 15:58:57 -04001873bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1874 GLenum target,
1875 GLint level,
1876 GLint xoffset,
1877 GLint yoffset,
1878 GLint zoffset,
1879 GLsizei width,
1880 GLsizei height,
1881 GLsizei depth,
1882 GLenum format,
1883 GLsizei imageSize,
1884 GLsizei dataSize,
1885 const GLvoid *data)
1886{
1887 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1888 {
1889 return false;
1890 }
1891
1892 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1893 height, depth, format, imageSize, data);
1894}
Jamie Madill73a84962016-02-12 09:27:23 -05001895
Olli Etuaho41997e72016-03-10 13:38:39 +02001896bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1897{
1898 return ValidateGenOrDeleteES3(context, n);
1899}
1900
1901bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1902{
1903 return ValidateGenOrDeleteES3(context, n);
1904}
1905
1906bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1907{
1908 return ValidateGenOrDeleteCountES3(context, count);
1909}
1910
1911bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1912{
1913 return ValidateGenOrDeleteCountES3(context, count);
1914}
1915
1916bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1917{
1918 return ValidateGenOrDeleteES3(context, n);
1919}
1920
1921bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1922{
1923 if (!ValidateGenOrDeleteES3(context, n))
1924 {
1925 return false;
1926 }
1927 for (GLint i = 0; i < n; ++i)
1928 {
1929 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1930 if (transformFeedback != nullptr && transformFeedback->isActive())
1931 {
1932 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001934 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1935 return false;
1936 }
1937 }
1938 return true;
1939}
1940
1941bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1942{
1943 return ValidateGenOrDeleteES3(context, n);
1944}
1945
1946bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1947{
1948 return ValidateGenOrDeleteES3(context, n);
1949}
1950
1951bool ValidateGenOrDeleteES3(Context *context, GLint n)
1952{
Martin Radev1be913c2016-07-11 17:59:16 +03001953 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001956 return false;
1957 }
1958 return ValidateGenOrDelete(context, n);
1959}
1960
1961bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1962{
Martin Radev1be913c2016-07-11 17:59:16 +03001963 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001964 {
Jamie Madill437fa652016-05-03 15:13:24 -04001965 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001966 return false;
1967 }
1968 if (count < 0)
1969 {
Jamie Madill437fa652016-05-03 15:13:24 -04001970 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001971 return false;
1972 }
1973 return true;
1974}
1975
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001976bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1977{
Martin Radev1be913c2016-07-11 17:59:16 +03001978 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001979 {
Jamie Madill437fa652016-05-03 15:13:24 -04001980 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001981 return false;
1982 }
1983 switch (primitiveMode)
1984 {
1985 case GL_TRIANGLES:
1986 case GL_LINES:
1987 case GL_POINTS:
1988 break;
1989
1990 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001992 return false;
1993 }
1994
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001995 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001996 ASSERT(transformFeedback != nullptr);
1997
1998 if (transformFeedback->isActive())
1999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002001 return false;
2002 }
2003 return true;
2004}
2005
Olli Etuaho4f667482016-03-30 15:56:35 +03002006bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
2007{
Geoff Lang496c02d2016-10-20 11:38:11 -07002008 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2009}
2010
2011bool ValidateGetBufferPointervRobustANGLE(Context *context,
2012 GLenum target,
2013 GLenum pname,
2014 GLsizei bufSize,
2015 GLsizei *length,
2016 GLvoid **params)
2017{
2018 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002019 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002020 return false;
2021 }
2022
Geoff Lang496c02d2016-10-20 11:38:11 -07002023 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2024 {
2025 return false;
2026 }
2027
2028 if (!ValidateRobustBufferSize(context, bufSize, *length))
2029 {
2030 return false;
2031 }
2032
2033 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002034}
2035
2036bool ValidateUnmapBuffer(Context *context, GLenum target)
2037{
Martin Radev1be913c2016-07-11 17:59:16 +03002038 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002039 {
Jamie Madill437fa652016-05-03 15:13:24 -04002040 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002041 return false;
2042 }
2043
2044 return ValidateUnmapBufferBase(context, target);
2045}
2046
2047bool ValidateMapBufferRange(Context *context,
2048 GLenum target,
2049 GLintptr offset,
2050 GLsizeiptr length,
2051 GLbitfield access)
2052{
Martin Radev1be913c2016-07-11 17:59:16 +03002053 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002054 {
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002056 return false;
2057 }
2058
2059 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2060}
2061
2062bool ValidateFlushMappedBufferRange(Context *context,
2063 GLenum target,
2064 GLintptr offset,
2065 GLsizeiptr length)
2066{
Martin Radev1be913c2016-07-11 17:59:16 +03002067 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002068 {
Jamie Madill437fa652016-05-03 15:13:24 -04002069 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002070 return false;
2071 }
2072
2073 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2074}
2075
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002076bool ValidateIndexedStateQuery(ValidationContext *context,
2077 GLenum pname,
2078 GLuint index,
2079 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002080{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002081 if (length)
2082 {
2083 *length = 0;
2084 }
2085
Martin Radev66fb8202016-07-28 11:45:20 +03002086 GLenum nativeType;
2087 unsigned int numParams;
2088 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2089 {
2090 context->handleError(Error(GL_INVALID_ENUM));
2091 return false;
2092 }
2093
2094 const Caps &caps = context->getCaps();
2095 switch (pname)
2096 {
2097 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2098 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2099 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2100 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2101 {
2102 context->handleError(Error(GL_INVALID_VALUE));
2103 return false;
2104 }
2105 break;
2106
2107 case GL_UNIFORM_BUFFER_START:
2108 case GL_UNIFORM_BUFFER_SIZE:
2109 case GL_UNIFORM_BUFFER_BINDING:
2110 if (index >= caps.maxUniformBufferBindings)
2111 {
2112 context->handleError(Error(GL_INVALID_VALUE));
2113 return false;
2114 }
2115 break;
Shao80957d92017-02-20 21:25:59 +08002116
Martin Radev66fb8202016-07-28 11:45:20 +03002117 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2118 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2119 if (index >= 3u)
2120 {
2121 context->handleError(Error(GL_INVALID_VALUE));
2122 return false;
2123 }
2124 break;
Shao80957d92017-02-20 21:25:59 +08002125
Jiajia Qin6eafb042016-12-27 17:04:07 +08002126 case GL_ATOMIC_COUNTER_BUFFER_START:
2127 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2128 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2129 if (context->getClientVersion() < ES_3_1)
2130 {
2131 context->handleError(
2132 Error(GL_INVALID_ENUM,
2133 "Atomic Counter buffers are not supported in this version of GL"));
2134 return false;
2135 }
2136 if (index >= caps.maxAtomicCounterBufferBindings)
2137 {
2138 context->handleError(
2139 Error(GL_INVALID_VALUE,
2140 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2141 return false;
2142 }
2143 break;
Shao80957d92017-02-20 21:25:59 +08002144
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002145 case GL_SHADER_STORAGE_BUFFER_START:
2146 case GL_SHADER_STORAGE_BUFFER_SIZE:
2147 case GL_SHADER_STORAGE_BUFFER_BINDING:
2148 if (context->getClientVersion() < ES_3_1)
2149 {
2150 context->handleError(
2151 Error(GL_INVALID_ENUM,
2152 "Shader storage buffers are not supported in this version of GL"));
2153 return false;
2154 }
2155 if (index >= caps.maxShaderStorageBufferBindings)
2156 {
2157 context->handleError(
2158 Error(GL_INVALID_VALUE,
2159 "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
2160 return false;
2161 }
2162 break;
2163
Shao80957d92017-02-20 21:25:59 +08002164 case GL_VERTEX_BINDING_BUFFER:
2165 case GL_VERTEX_BINDING_DIVISOR:
2166 case GL_VERTEX_BINDING_OFFSET:
2167 case GL_VERTEX_BINDING_STRIDE:
2168 if (context->getClientVersion() < ES_3_1)
2169 {
2170 context->handleError(
2171 Error(GL_INVALID_ENUM,
2172 "Vertex Attrib Bindings are not supported in this version of GL"));
2173 return false;
2174 }
2175 if (index >= caps.maxVertexAttribBindings)
2176 {
2177 context->handleError(
2178 Error(GL_INVALID_VALUE,
2179 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2180 return false;
2181 }
2182 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002183 default:
2184 context->handleError(Error(GL_INVALID_ENUM));
2185 return false;
2186 }
2187
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002188 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002189 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002190 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002191 }
2192
2193 return true;
2194}
2195
2196bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2197{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002198 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002199 {
2200 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2201 return false;
2202 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002203 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002204}
2205
Geoff Langcf255ea2016-10-20 11:39:09 -07002206bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2207 GLenum target,
2208 GLuint index,
2209 GLsizei bufSize,
2210 GLsizei *length,
2211 GLint *data)
2212{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002213 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002214 {
2215 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2216 return false;
2217 }
2218
2219 if (!ValidateRobustEntryPoint(context, bufSize))
2220 {
2221 return false;
2222 }
2223
2224 if (!ValidateIndexedStateQuery(context, target, index, length))
2225 {
2226 return false;
2227 }
2228
2229 if (!ValidateRobustBufferSize(context, bufSize, *length))
2230 {
2231 return false;
2232 }
2233
2234 return true;
2235}
2236
Martin Radev66fb8202016-07-28 11:45:20 +03002237bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2238{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002239 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002240 {
2241 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2242 return false;
2243 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002244 return ValidateIndexedStateQuery(context, target, index, nullptr);
2245}
2246
2247bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2248 GLenum target,
2249 GLuint index,
2250 GLsizei bufSize,
2251 GLsizei *length,
2252 GLint64 *data)
2253{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002254 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002255 {
2256 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2257 return false;
2258 }
2259
2260 if (!ValidateRobustEntryPoint(context, bufSize))
2261 {
2262 return false;
2263 }
2264
2265 if (!ValidateIndexedStateQuery(context, target, index, length))
2266 {
2267 return false;
2268 }
2269
2270 if (!ValidateRobustBufferSize(context, bufSize, *length))
2271 {
2272 return false;
2273 }
2274
2275 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002276}
2277
Jamie Madillb0817d12016-11-01 15:48:31 -04002278bool ValidateCopyBufferSubData(ValidationContext *context,
2279 GLenum readTarget,
2280 GLenum writeTarget,
2281 GLintptr readOffset,
2282 GLintptr writeOffset,
2283 GLsizeiptr size)
2284{
2285 if (context->getClientMajorVersion() < 3)
2286 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002287 context->handleError(
2288 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002289 return false;
2290 }
2291
2292 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2293 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002294 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002295 return false;
2296 }
2297
2298 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2299 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2300
2301 if (!readBuffer || !writeBuffer)
2302 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002303 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002304 return false;
2305 }
2306
2307 // Verify that readBuffer and writeBuffer are not currently mapped
2308 if (readBuffer->isMapped() || writeBuffer->isMapped())
2309 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002310 context->handleError(
2311 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002312 return false;
2313 }
2314
Jamie Madilld2f0c742016-11-02 10:34:41 -04002315 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2316 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2317 CheckedNumeric<GLintptr> checkedSize(size);
2318
2319 auto checkedReadSum = checkedReadOffset + checkedSize;
2320 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2321
2322 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2323 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2324 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002325 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002326 context->handleError(
2327 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002328 return false;
2329 }
2330
Jamie Madilld2f0c742016-11-02 10:34:41 -04002331 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002332 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002333 context->handleError(
2334 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002335 return false;
2336 }
2337
Jamie Madilld2f0c742016-11-02 10:34:41 -04002338 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2339 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2340 {
2341 context->handleError(
2342 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2343 return false;
2344 }
2345
2346 if (readBuffer == writeBuffer)
2347 {
2348 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2349 if (!checkedOffsetDiff.IsValid())
2350 {
2351 // This shold not be possible.
2352 UNREACHABLE();
2353 context->handleError(
2354 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2355 return false;
2356 }
2357
2358 if (checkedOffsetDiff.ValueOrDie() < size)
2359 {
2360 context->handleError(Error(GL_INVALID_VALUE));
2361 return false;
2362 }
2363 }
2364
Jamie Madillb0817d12016-11-01 15:48:31 -04002365 return true;
2366}
2367
Geoff Langc339c4e2016-11-29 10:37:36 -05002368bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2369{
2370 if (context->getClientMajorVersion() < 3)
2371 {
2372 context->handleError(
2373 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2374 return false;
2375 }
2376
2377 switch (name)
2378 {
2379 case GL_EXTENSIONS:
2380 if (index >= context->getExtensionStringCount())
2381 {
2382 context->handleError(Error(
2383 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2384 return false;
2385 }
2386 break;
2387
2388 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2389 if (!context->getExtensions().requestExtension)
2390 {
2391 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2392 return false;
2393 }
2394 if (index >= context->getRequestableExtensionStringCount())
2395 {
2396 context->handleError(
2397 Error(GL_INVALID_VALUE,
2398 "index must be less than the number of requestable extension strings."));
2399 return false;
2400 }
2401 break;
2402
2403 default:
2404 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2405 return false;
2406 }
2407
2408 return true;
2409}
2410
Jamie Madille8fb6402017-02-14 17:56:40 -05002411bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2412 GLenum target,
2413 GLsizei samples,
2414 GLenum internalformat,
2415 GLsizei width,
2416 GLsizei height)
2417{
2418 if (context->getClientMajorVersion() < 3)
2419 {
2420 context->handleError(Error(GL_INVALID_OPERATION));
2421 return false;
2422 }
2423
2424 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2425 height))
2426 {
2427 return false;
2428 }
2429
2430 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2431 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002432 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002433 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2434 samples > 0)
2435 {
2436 context->handleError(Error(GL_INVALID_OPERATION));
2437 return false;
2438 }
2439
2440 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2441 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2442 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2443 {
2444 context->handleError(
2445 Error(GL_INVALID_OPERATION,
2446 "Samples must not be greater than maximum supported value for the format."));
2447 return false;
2448 }
2449
2450 return true;
2451}
2452
Geoff Langaa086d62017-03-23 16:47:21 -04002453bool ValidateVertexAttribIPointer(ValidationContext *context,
2454 GLuint index,
2455 GLint size,
2456 GLenum type,
2457 GLsizei stride,
2458 const GLvoid *pointer)
2459{
2460 if (context->getClientMajorVersion() < 3)
2461 {
Geoff Langaa086d62017-03-23 16:47:21 -04002462 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002463 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002464 return false;
2465 }
2466
Shao80957d92017-02-20 21:25:59 +08002467 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002468 {
Geoff Langaa086d62017-03-23 16:47:21 -04002469 return false;
2470 }
2471
Geoff Langaa086d62017-03-23 16:47:21 -04002472 if (stride < 0)
2473 {
Shao80957d92017-02-20 21:25:59 +08002474 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002475 return false;
2476 }
2477
Shao80957d92017-02-20 21:25:59 +08002478 const Caps &caps = context->getCaps();
2479 if (context->getClientVersion() >= ES_3_1)
2480 {
2481 if (stride > caps.maxVertexAttribStride)
2482 {
2483 context->handleError(
2484 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2485 return false;
2486 }
2487
2488 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2489 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2490 // validation should be inherited.
2491 if (index >= caps.maxVertexAttribBindings)
2492 {
2493 context->handleError(
2494 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2495 return false;
2496 }
2497 }
2498
Geoff Langaa086d62017-03-23 16:47:21 -04002499 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2500 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2501 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2502 // and the pointer argument is not NULL.
2503 if (context->getGLState().getVertexArrayId() != 0 &&
2504 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2505 {
2506 context->handleError(
2507 Error(GL_INVALID_OPERATION,
2508 "Client data cannot be used with a non-default vertex array object."));
2509 return false;
2510 }
2511
Geoff Lang2d62ab72017-03-23 16:54:40 -04002512 if (context->getExtensions().webglCompatibility)
2513 {
2514 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2515 {
2516 return false;
2517 }
2518 }
2519
Geoff Langaa086d62017-03-23 16:47:21 -04002520 return true;
2521}
2522
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002523bool ValidateGetSynciv(Context *context,
2524 GLsync sync,
2525 GLenum pname,
2526 GLsizei bufSize,
2527 GLsizei *length,
2528 GLint *values)
2529{
2530 if (context->getClientMajorVersion() < 3)
2531 {
2532 context->handleError(
2533 Error(GL_INVALID_OPERATION, "GetSynciv requires OpenGL ES 3.0 or higher."));
2534 return false;
2535 }
2536
2537 if (bufSize < 0)
2538 {
2539 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
2540 return false;
2541 }
2542
2543 FenceSync *fenceSync = context->getFenceSync(sync);
2544 if (!fenceSync)
2545 {
2546 context->handleError(Error(GL_INVALID_VALUE, "Invalid sync object."));
2547 return false;
2548 }
2549
2550 switch (pname)
2551 {
2552 case GL_OBJECT_TYPE:
2553 case GL_SYNC_CONDITION:
2554 case GL_SYNC_FLAGS:
2555 case GL_SYNC_STATUS:
2556 break;
2557
2558 default:
2559 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
2560 return false;
2561 }
2562
2563 return true;
2564}
2565
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002566bool ValidateDrawElementsInstanced(ValidationContext *context,
2567 GLenum mode,
2568 GLsizei count,
2569 GLenum type,
2570 const GLvoid *indices,
2571 GLsizei instanceCount)
2572{
2573 if (context->getClientMajorVersion() < 3)
2574 {
2575 context->handleError(Error(GL_INVALID_OPERATION, "Requires a GLES 3.0 or higher context."));
2576 return false;
2577 }
2578
2579 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2580}
2581
Jamie Madillc29968b2016-01-20 11:17:23 -05002582} // namespace gl