blob: 7460d8d546f5bfe0a192d3bb4aa4f0a4f1306f46 [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,
1083 const GLvoid *indices,
1084 IndexRange *indexRange)
1085{
Martin Radev1be913c2016-07-11 17:59:16 +03001086 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001089 return false;
1090 }
1091
1092 if (end < start)
1093 {
Jamie Madill437fa652016-05-03 15:13:24 -04001094 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001095 return false;
1096 }
1097
1098 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1099 {
1100 return false;
1101 }
1102
1103 if (indexRange->end > end || indexRange->start < start)
1104 {
1105 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001106 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001107 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1108 return false;
1109 }
1110 return true;
1111}
1112
He Yunchaoced53ae2016-11-29 15:00:51 +08001113bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001114{
Martin Radev1be913c2016-07-11 17:59:16 +03001115 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001116 {
Jamie Madill437fa652016-05-03 15:13:24 -04001117 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001118 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001119 }
1120
Jamie Madill78f41802014-08-25 15:47:55 -04001121 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001122}
1123
Jamie Madillb885e572015-02-03 16:16:04 -05001124bool ValidateReadBuffer(Context *context, GLenum src)
1125{
Martin Radev1be913c2016-07-11 17:59:16 +03001126 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001127 {
Jamie Madill437fa652016-05-03 15:13:24 -04001128 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001129 return false;
1130 }
1131
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001132 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001133
1134 if (readFBO == nullptr)
1135 {
Jamie Madill437fa652016-05-03 15:13:24 -04001136 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001137 return false;
1138 }
1139
1140 if (src == GL_NONE)
1141 {
1142 return true;
1143 }
1144
Olli Etuaho84c9f592016-03-09 14:37:25 +02001145 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001146 {
Jamie Madill437fa652016-05-03 15:13:24 -04001147 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001148 return false;
1149 }
1150
1151 if (readFBO->id() == 0)
1152 {
1153 if (src != GL_BACK)
1154 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001155 const char *errorMsg =
1156 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001157 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001158 return false;
1159 }
1160 }
1161 else
1162 {
1163 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1164
1165 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1166 {
1167 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001168 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001169 return false;
1170 }
1171 }
1172
1173 return true;
1174}
1175
Jamie Madill86af3d22015-07-21 15:14:07 -04001176bool ValidateCompressedTexImage3D(Context *context,
1177 GLenum target,
1178 GLint level,
1179 GLenum internalformat,
1180 GLsizei width,
1181 GLsizei height,
1182 GLsizei depth,
1183 GLint border,
1184 GLsizei imageSize,
1185 const GLvoid *data)
1186{
Martin Radev1be913c2016-07-11 17:59:16 +03001187 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001188 {
Jamie Madill437fa652016-05-03 15:13:24 -04001189 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001190 return false;
1191 }
1192
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001193 if (!ValidTextureTarget(context, target))
1194 {
1195 context->handleError(Error(GL_INVALID_ENUM));
1196 return false;
1197 }
1198
Jamie Madille2e406c2016-06-02 13:04:10 -04001199 // Validate image size
1200 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1201 {
1202 context->handleError(Error(GL_INVALID_VALUE));
1203 return false;
1204 }
1205
Geoff Langca271392017-04-05 12:30:00 -04001206 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001207 if (!formatInfo.compressed)
1208 {
1209 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1210 return false;
1211 }
1212
Jamie Madill513558d2016-06-02 13:04:11 -04001213 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001214 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001215 if (blockSizeOrErr.isError())
1216 {
Jamie Madill513558d2016-06-02 13:04:11 -04001217 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001218 return false;
1219 }
1220 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001221 {
Jamie Madill437fa652016-05-03 15:13:24 -04001222 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001223 return false;
1224 }
1225
1226 // 3D texture target validation
1227 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1228 {
Jamie Madill437fa652016-05-03 15:13:24 -04001229 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001230 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1231 return false;
1232 }
1233
1234 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001235 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001236 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1237 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001238 {
1239 return false;
1240 }
1241
1242 return true;
1243}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001244
Corentin Wallezb2931602017-04-11 15:58:57 -04001245bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1246 GLenum target,
1247 GLint level,
1248 GLenum internalformat,
1249 GLsizei width,
1250 GLsizei height,
1251 GLsizei depth,
1252 GLint border,
1253 GLsizei imageSize,
1254 GLsizei dataSize,
1255 const GLvoid *data)
1256{
1257 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1258 {
1259 return false;
1260 }
1261
1262 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1263 depth, border, imageSize, data);
1264}
1265
Austin Kinrossbc781f32015-10-26 09:27:38 -07001266bool ValidateBindVertexArray(Context *context, GLuint array)
1267{
Martin Radev1be913c2016-07-11 17:59:16 +03001268 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001269 {
Jamie Madill437fa652016-05-03 15:13:24 -04001270 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001271 return false;
1272 }
1273
1274 return ValidateBindVertexArrayBase(context, array);
1275}
1276
Austin Kinrossbc781f32015-10-26 09:27:38 -07001277bool ValidateIsVertexArray(Context *context)
1278{
Martin Radev1be913c2016-07-11 17:59:16 +03001279 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001280 {
Jamie Madill437fa652016-05-03 15:13:24 -04001281 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001282 return false;
1283 }
1284
1285 return true;
1286}
Geoff Langc5629752015-12-07 16:29:04 -05001287
Jiajia Qin6eafb042016-12-27 17:04:07 +08001288static bool ValidateBindBufferCommon(Context *context,
1289 GLenum target,
1290 GLuint index,
1291 GLuint buffer,
1292 GLintptr offset,
1293 GLsizeiptr size)
1294{
1295 if (context->getClientMajorVersion() < 3)
1296 {
1297 context->handleError(Error(GL_INVALID_OPERATION));
1298 return false;
1299 }
1300
1301 if (buffer != 0 && offset < 0)
1302 {
1303 context->handleError(Error(GL_INVALID_VALUE, "buffer is non-zero and offset is negative."));
1304 return false;
1305 }
1306
1307 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1308 !context->isBufferGenerated(buffer))
1309 {
1310 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated."));
1311 return false;
1312 }
1313
1314 const Caps &caps = context->getCaps();
1315 switch (target)
1316 {
1317 case GL_TRANSFORM_FEEDBACK_BUFFER:
1318 {
1319 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1320 {
1321 context->handleError(Error(GL_INVALID_VALUE,
1322 "index is greater than or equal to the number of "
1323 "TRANSFORM_FEEDBACK_BUFFER indexed binding points."));
1324 return false;
1325 }
1326 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1327 {
1328 context->handleError(
1329 Error(GL_INVALID_VALUE, "offset and size must be multiple of 4."));
1330 return false;
1331 }
1332
1333 TransformFeedback *curTransformFeedback =
1334 context->getGLState().getCurrentTransformFeedback();
1335 if (curTransformFeedback && curTransformFeedback->isActive())
1336 {
1337 context->handleError(Error(GL_INVALID_OPERATION,
1338 "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1339 "feedback is currently active."));
1340 return false;
1341 }
1342 break;
1343 }
1344 case GL_UNIFORM_BUFFER:
1345 {
1346 if (index >= caps.maxUniformBufferBindings)
1347 {
1348 context->handleError(Error(GL_INVALID_VALUE,
1349 "index is greater than or equal to the number of "
1350 "UNIFORM_BUFFER indexed binding points."));
1351 return false;
1352 }
1353
1354 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1355 {
1356 context->handleError(
1357 Error(GL_INVALID_VALUE,
1358 "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT."));
1359 return false;
1360 }
1361 break;
1362 }
1363 case GL_ATOMIC_COUNTER_BUFFER:
1364 {
1365 if (context->getClientVersion() < ES_3_1)
1366 {
Yunchao He61afff12017-03-14 15:34:03 +08001367 context->handleError(Error(
1368 GL_INVALID_ENUM, "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1"));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001369 return false;
1370 }
1371 if (index >= caps.maxAtomicCounterBufferBindings)
1372 {
1373 context->handleError(Error(GL_INVALID_VALUE,
1374 "index is greater than or equal to the number of "
1375 "ATOMIC_COUNTER_BUFFER indexed binding points."));
1376 return false;
1377 }
1378 if (buffer != 0 && (offset % 4) != 0)
1379 {
1380 context->handleError(Error(GL_INVALID_VALUE, "offset must be a multiple of 4."));
1381 return false;
1382 }
1383 break;
1384 }
1385 case GL_SHADER_STORAGE_BUFFER:
1386 {
1387 if (context->getClientVersion() < ES_3_1)
1388 {
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001389 context->handleError(
1390 Error(GL_INVALID_ENUM, "SHADER_STORAGE_BUFFER is not supported in GLES3."));
1391 return false;
1392 }
1393 if (index >= caps.maxShaderStorageBufferBindings)
1394 {
1395 context->handleError(Error(GL_INVALID_VALUE,
1396 "index is greater than or equal to the number of "
1397 "SHADER_STORAGE_BUFFER indexed binding points."));
1398 return false;
1399 }
1400 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1401 {
Yunchao He61afff12017-03-14 15:34:03 +08001402 context->handleError(Error(
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001403 GL_INVALID_VALUE,
1404 "offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."));
Jiajia Qin6eafb042016-12-27 17:04:07 +08001405 return false;
1406 }
1407 break;
1408 }
1409 default:
1410 context->handleError(Error(GL_INVALID_ENUM, "the target is not supported."));
1411 return false;
1412 }
1413
1414 return true;
1415}
1416
1417bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1418{
1419 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1420}
1421
1422bool ValidateBindBufferRange(Context *context,
1423 GLenum target,
1424 GLuint index,
1425 GLuint buffer,
1426 GLintptr offset,
1427 GLsizeiptr size)
1428{
1429 if (buffer != 0 && size <= 0)
1430 {
1431 context->handleError(
1432 Error(GL_INVALID_VALUE, "buffer is non-zero and size is less than or equal to zero."));
1433 return false;
1434 }
1435 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1436}
1437
Geoff Langc5629752015-12-07 16:29:04 -05001438bool ValidateProgramBinary(Context *context,
1439 GLuint program,
1440 GLenum binaryFormat,
1441 const void *binary,
1442 GLint length)
1443{
Martin Radev1be913c2016-07-11 17:59:16 +03001444 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001447 return false;
1448 }
1449
1450 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1451}
1452
1453bool ValidateGetProgramBinary(Context *context,
1454 GLuint program,
1455 GLsizei bufSize,
1456 GLsizei *length,
1457 GLenum *binaryFormat,
1458 void *binary)
1459{
Martin Radev1be913c2016-07-11 17:59:16 +03001460 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001461 {
Jamie Madill437fa652016-05-03 15:13:24 -04001462 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001463 return false;
1464 }
1465
1466 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1467}
1468
Olli Etuahof0fee072016-03-30 15:11:58 +03001469bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001470{
Martin Radev1be913c2016-07-11 17:59:16 +03001471 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001472 {
Jamie Madill437fa652016-05-03 15:13:24 -04001473 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001474 return false;
1475 }
1476
1477 if (GetValidProgram(context, program) == nullptr)
1478 {
1479 return false;
1480 }
1481
1482 switch (pname)
1483 {
1484 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001485 if (value != GL_FALSE && value != GL_TRUE)
1486 {
Jamie Madill437fa652016-05-03 15:13:24 -04001487 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001488 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1489 return false;
1490 }
Geoff Langc5629752015-12-07 16:29:04 -05001491 break;
1492
Yunchao He61afff12017-03-14 15:34:03 +08001493 case GL_PROGRAM_SEPARABLE:
1494 if (context->getClientVersion() < ES_3_1)
1495 {
1496 context->handleError(
1497 Error(GL_INVALID_ENUM, "PROGRAM_SEPARABLE is not supported before GLES 3.1"));
1498 return false;
1499 }
1500
1501 if (value != GL_FALSE && value != GL_TRUE)
1502 {
1503 context->handleError(Error(
1504 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1505 return false;
1506 }
1507 break;
1508
Geoff Langc5629752015-12-07 16:29:04 -05001509 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001510 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001511 return false;
1512 }
1513
1514 return true;
1515}
Jamie Madillc29968b2016-01-20 11:17:23 -05001516
1517bool ValidateBlitFramebuffer(Context *context,
1518 GLint srcX0,
1519 GLint srcY0,
1520 GLint srcX1,
1521 GLint srcY1,
1522 GLint dstX0,
1523 GLint dstY0,
1524 GLint dstX1,
1525 GLint dstY1,
1526 GLbitfield mask,
1527 GLenum filter)
1528{
Martin Radev1be913c2016-07-11 17:59:16 +03001529 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001532 return false;
1533 }
1534
1535 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1536 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537}
Jamie Madillc29968b2016-01-20 11:17:23 -05001538
1539bool ValidateClearBufferiv(ValidationContext *context,
1540 GLenum buffer,
1541 GLint drawbuffer,
1542 const GLint *value)
1543{
1544 switch (buffer)
1545 {
1546 case GL_COLOR:
1547 if (drawbuffer < 0 ||
1548 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1549 {
Jamie Madill437fa652016-05-03 15:13:24 -04001550 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001551 return false;
1552 }
Geoff Lang76e65652017-03-27 14:58:02 -04001553 if (context->getExtensions().webglCompatibility)
1554 {
1555 constexpr GLenum validComponentTypes[] = {GL_INT};
1556 if (ValidateWebGLFramebufferAttachmentClearType(
1557 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1558 {
1559 return false;
1560 }
1561 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001562 break;
1563
1564 case GL_STENCIL:
1565 if (drawbuffer != 0)
1566 {
Jamie Madill437fa652016-05-03 15:13:24 -04001567 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001568 return false;
1569 }
1570 break;
1571
1572 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001573 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001574 return false;
1575 }
1576
1577 return ValidateClearBuffer(context);
1578}
1579
1580bool ValidateClearBufferuiv(ValidationContext *context,
1581 GLenum buffer,
1582 GLint drawbuffer,
1583 const GLuint *value)
1584{
1585 switch (buffer)
1586 {
1587 case GL_COLOR:
1588 if (drawbuffer < 0 ||
1589 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001592 return false;
1593 }
Geoff Lang76e65652017-03-27 14:58:02 -04001594 if (context->getExtensions().webglCompatibility)
1595 {
1596 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1597 if (ValidateWebGLFramebufferAttachmentClearType(
1598 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1599 {
1600 return false;
1601 }
1602 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001603 break;
1604
1605 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001607 return false;
1608 }
1609
1610 return ValidateClearBuffer(context);
1611}
1612
1613bool ValidateClearBufferfv(ValidationContext *context,
1614 GLenum buffer,
1615 GLint drawbuffer,
1616 const GLfloat *value)
1617{
1618 switch (buffer)
1619 {
1620 case GL_COLOR:
1621 if (drawbuffer < 0 ||
1622 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1623 {
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001625 return false;
1626 }
Geoff Lang76e65652017-03-27 14:58:02 -04001627 if (context->getExtensions().webglCompatibility)
1628 {
1629 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1630 GL_SIGNED_NORMALIZED};
1631 if (ValidateWebGLFramebufferAttachmentClearType(
1632 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1633 {
1634 return false;
1635 }
1636 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001637 break;
1638
1639 case GL_DEPTH:
1640 if (drawbuffer != 0)
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001643 return false;
1644 }
1645 break;
1646
1647 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001649 return false;
1650 }
1651
1652 return ValidateClearBuffer(context);
1653}
1654
1655bool ValidateClearBufferfi(ValidationContext *context,
1656 GLenum buffer,
1657 GLint drawbuffer,
1658 GLfloat depth,
1659 GLint stencil)
1660{
1661 switch (buffer)
1662 {
1663 case GL_DEPTH_STENCIL:
1664 if (drawbuffer != 0)
1665 {
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001667 return false;
1668 }
1669 break;
1670
1671 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001672 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001673 return false;
1674 }
1675
1676 return ValidateClearBuffer(context);
1677}
1678
1679bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1680{
Martin Radev1be913c2016-07-11 17:59:16 +03001681 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001682 {
Jamie Madill437fa652016-05-03 15:13:24 -04001683 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001684 return false;
1685 }
1686
1687 return ValidateDrawBuffersBase(context, n, bufs);
1688}
1689
1690bool ValidateCopyTexSubImage3D(Context *context,
1691 GLenum target,
1692 GLint level,
1693 GLint xoffset,
1694 GLint yoffset,
1695 GLint zoffset,
1696 GLint x,
1697 GLint y,
1698 GLsizei width,
1699 GLsizei height)
1700{
Martin Radev1be913c2016-07-11 17:59:16 +03001701 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001702 {
Jamie Madill437fa652016-05-03 15:13:24 -04001703 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001704 return false;
1705 }
1706
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001707 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1708 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001709}
1710
Jamie Madill73a84962016-02-12 09:27:23 -05001711bool ValidateTexImage3D(Context *context,
1712 GLenum target,
1713 GLint level,
1714 GLint internalformat,
1715 GLsizei width,
1716 GLsizei height,
1717 GLsizei depth,
1718 GLint border,
1719 GLenum format,
1720 GLenum type,
1721 const GLvoid *pixels)
1722{
Martin Radev1be913c2016-07-11 17:59:16 +03001723 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001726 return false;
1727 }
1728
1729 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001730 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001731 pixels);
1732}
1733
Geoff Langc52f6f12016-10-14 10:18:00 -04001734bool ValidateTexImage3DRobustANGLE(Context *context,
1735 GLenum target,
1736 GLint level,
1737 GLint internalformat,
1738 GLsizei width,
1739 GLsizei height,
1740 GLsizei depth,
1741 GLint border,
1742 GLenum format,
1743 GLenum type,
1744 GLsizei bufSize,
1745 const GLvoid *pixels)
1746{
1747 if (context->getClientMajorVersion() < 3)
1748 {
1749 context->handleError(Error(GL_INVALID_OPERATION));
1750 return false;
1751 }
1752
1753 if (!ValidateRobustEntryPoint(context, bufSize))
1754 {
1755 return false;
1756 }
1757
1758 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1759 0, 0, width, height, depth, border, format, type,
1760 bufSize, pixels);
1761}
1762
Jamie Madill73a84962016-02-12 09:27:23 -05001763bool ValidateTexSubImage3D(Context *context,
1764 GLenum target,
1765 GLint level,
1766 GLint xoffset,
1767 GLint yoffset,
1768 GLint zoffset,
1769 GLsizei width,
1770 GLsizei height,
1771 GLsizei depth,
1772 GLenum format,
1773 GLenum type,
1774 const GLvoid *pixels)
1775{
Martin Radev1be913c2016-07-11 17:59:16 +03001776 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001779 return false;
1780 }
1781
1782 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1783 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001784 -1, pixels);
1785}
1786
1787bool ValidateTexSubImage3DRobustANGLE(Context *context,
1788 GLenum target,
1789 GLint level,
1790 GLint xoffset,
1791 GLint yoffset,
1792 GLint zoffset,
1793 GLsizei width,
1794 GLsizei height,
1795 GLsizei depth,
1796 GLenum format,
1797 GLenum type,
1798 GLsizei bufSize,
1799 const GLvoid *pixels)
1800{
1801 if (context->getClientMajorVersion() < 3)
1802 {
1803 context->handleError(Error(GL_INVALID_OPERATION));
1804 return false;
1805 }
1806
1807 if (!ValidateRobustEntryPoint(context, bufSize))
1808 {
1809 return false;
1810 }
1811
1812 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1813 yoffset, zoffset, width, height, depth, 0, format, type,
1814 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001815}
1816
1817bool ValidateCompressedTexSubImage3D(Context *context,
1818 GLenum target,
1819 GLint level,
1820 GLint xoffset,
1821 GLint yoffset,
1822 GLint zoffset,
1823 GLsizei width,
1824 GLsizei height,
1825 GLsizei depth,
1826 GLenum format,
1827 GLsizei imageSize,
1828 const GLvoid *data)
1829{
Martin Radev1be913c2016-07-11 17:59:16 +03001830 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001831 {
Jamie Madill437fa652016-05-03 15:13:24 -04001832 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001833 return false;
1834 }
1835
Geoff Langca271392017-04-05 12:30:00 -04001836 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001837 if (!formatInfo.compressed)
1838 {
1839 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1840 return false;
1841 }
1842
Jamie Madill513558d2016-06-02 13:04:11 -04001843 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001844 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001845 if (blockSizeOrErr.isError())
1846 {
1847 context->handleError(blockSizeOrErr.getError());
1848 return false;
1849 }
1850 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001851 {
Jamie Madill437fa652016-05-03 15:13:24 -04001852 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001853 return false;
1854 }
1855
1856 if (!data)
1857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001859 return false;
1860 }
1861
1862 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001863 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001864}
Corentin Wallezb2931602017-04-11 15:58:57 -04001865bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1866 GLenum target,
1867 GLint level,
1868 GLint xoffset,
1869 GLint yoffset,
1870 GLint zoffset,
1871 GLsizei width,
1872 GLsizei height,
1873 GLsizei depth,
1874 GLenum format,
1875 GLsizei imageSize,
1876 GLsizei dataSize,
1877 const GLvoid *data)
1878{
1879 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1880 {
1881 return false;
1882 }
1883
1884 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1885 height, depth, format, imageSize, data);
1886}
Jamie Madill73a84962016-02-12 09:27:23 -05001887
Olli Etuaho41997e72016-03-10 13:38:39 +02001888bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1889{
1890 return ValidateGenOrDeleteES3(context, n);
1891}
1892
1893bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1894{
1895 return ValidateGenOrDeleteES3(context, n);
1896}
1897
1898bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1899{
1900 return ValidateGenOrDeleteCountES3(context, count);
1901}
1902
1903bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1904{
1905 return ValidateGenOrDeleteCountES3(context, count);
1906}
1907
1908bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1909{
1910 return ValidateGenOrDeleteES3(context, n);
1911}
1912
1913bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1914{
1915 if (!ValidateGenOrDeleteES3(context, n))
1916 {
1917 return false;
1918 }
1919 for (GLint i = 0; i < n; ++i)
1920 {
1921 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1922 if (transformFeedback != nullptr && transformFeedback->isActive())
1923 {
1924 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001926 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1927 return false;
1928 }
1929 }
1930 return true;
1931}
1932
1933bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1934{
1935 return ValidateGenOrDeleteES3(context, n);
1936}
1937
1938bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1939{
1940 return ValidateGenOrDeleteES3(context, n);
1941}
1942
1943bool ValidateGenOrDeleteES3(Context *context, GLint n)
1944{
Martin Radev1be913c2016-07-11 17:59:16 +03001945 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001946 {
Jamie Madill437fa652016-05-03 15:13:24 -04001947 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001948 return false;
1949 }
1950 return ValidateGenOrDelete(context, n);
1951}
1952
1953bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1954{
Martin Radev1be913c2016-07-11 17:59:16 +03001955 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001956 {
Jamie Madill437fa652016-05-03 15:13:24 -04001957 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001958 return false;
1959 }
1960 if (count < 0)
1961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001963 return false;
1964 }
1965 return true;
1966}
1967
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001968bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1969{
Martin Radev1be913c2016-07-11 17:59:16 +03001970 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001973 return false;
1974 }
1975 switch (primitiveMode)
1976 {
1977 case GL_TRIANGLES:
1978 case GL_LINES:
1979 case GL_POINTS:
1980 break;
1981
1982 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001983 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001984 return false;
1985 }
1986
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001987 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001988 ASSERT(transformFeedback != nullptr);
1989
1990 if (transformFeedback->isActive())
1991 {
Jamie Madill437fa652016-05-03 15:13:24 -04001992 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001993 return false;
1994 }
1995 return true;
1996}
1997
Olli Etuaho4f667482016-03-30 15:56:35 +03001998bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1999{
Geoff Lang496c02d2016-10-20 11:38:11 -07002000 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2001}
2002
2003bool ValidateGetBufferPointervRobustANGLE(Context *context,
2004 GLenum target,
2005 GLenum pname,
2006 GLsizei bufSize,
2007 GLsizei *length,
2008 GLvoid **params)
2009{
2010 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002011 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002012 return false;
2013 }
2014
Geoff Lang496c02d2016-10-20 11:38:11 -07002015 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2016 {
2017 return false;
2018 }
2019
2020 if (!ValidateRobustBufferSize(context, bufSize, *length))
2021 {
2022 return false;
2023 }
2024
2025 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002026}
2027
2028bool ValidateUnmapBuffer(Context *context, GLenum target)
2029{
Martin Radev1be913c2016-07-11 17:59:16 +03002030 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002031 {
Jamie Madill437fa652016-05-03 15:13:24 -04002032 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03002033 return false;
2034 }
2035
2036 return ValidateUnmapBufferBase(context, target);
2037}
2038
2039bool ValidateMapBufferRange(Context *context,
2040 GLenum target,
2041 GLintptr offset,
2042 GLsizeiptr length,
2043 GLbitfield access)
2044{
Martin Radev1be913c2016-07-11 17:59:16 +03002045 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002046 {
Jamie Madill437fa652016-05-03 15:13:24 -04002047 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002048 return false;
2049 }
2050
2051 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2052}
2053
2054bool ValidateFlushMappedBufferRange(Context *context,
2055 GLenum target,
2056 GLintptr offset,
2057 GLsizeiptr length)
2058{
Martin Radev1be913c2016-07-11 17:59:16 +03002059 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002060 {
Jamie Madill437fa652016-05-03 15:13:24 -04002061 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002062 return false;
2063 }
2064
2065 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2066}
2067
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002068bool ValidateIndexedStateQuery(ValidationContext *context,
2069 GLenum pname,
2070 GLuint index,
2071 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002072{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002073 if (length)
2074 {
2075 *length = 0;
2076 }
2077
Martin Radev66fb8202016-07-28 11:45:20 +03002078 GLenum nativeType;
2079 unsigned int numParams;
2080 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2081 {
2082 context->handleError(Error(GL_INVALID_ENUM));
2083 return false;
2084 }
2085
2086 const Caps &caps = context->getCaps();
2087 switch (pname)
2088 {
2089 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2090 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2091 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2092 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2093 {
2094 context->handleError(Error(GL_INVALID_VALUE));
2095 return false;
2096 }
2097 break;
2098
2099 case GL_UNIFORM_BUFFER_START:
2100 case GL_UNIFORM_BUFFER_SIZE:
2101 case GL_UNIFORM_BUFFER_BINDING:
2102 if (index >= caps.maxUniformBufferBindings)
2103 {
2104 context->handleError(Error(GL_INVALID_VALUE));
2105 return false;
2106 }
2107 break;
Shao80957d92017-02-20 21:25:59 +08002108
Martin Radev66fb8202016-07-28 11:45:20 +03002109 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2110 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2111 if (index >= 3u)
2112 {
2113 context->handleError(Error(GL_INVALID_VALUE));
2114 return false;
2115 }
2116 break;
Shao80957d92017-02-20 21:25:59 +08002117
Jiajia Qin6eafb042016-12-27 17:04:07 +08002118 case GL_ATOMIC_COUNTER_BUFFER_START:
2119 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2120 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2121 if (context->getClientVersion() < ES_3_1)
2122 {
2123 context->handleError(
2124 Error(GL_INVALID_ENUM,
2125 "Atomic Counter buffers are not supported in this version of GL"));
2126 return false;
2127 }
2128 if (index >= caps.maxAtomicCounterBufferBindings)
2129 {
2130 context->handleError(
2131 Error(GL_INVALID_VALUE,
2132 "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING"));
2133 return false;
2134 }
2135 break;
Shao80957d92017-02-20 21:25:59 +08002136
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002137 case GL_SHADER_STORAGE_BUFFER_START:
2138 case GL_SHADER_STORAGE_BUFFER_SIZE:
2139 case GL_SHADER_STORAGE_BUFFER_BINDING:
2140 if (context->getClientVersion() < ES_3_1)
2141 {
2142 context->handleError(
2143 Error(GL_INVALID_ENUM,
2144 "Shader storage buffers are not supported in this version of GL"));
2145 return false;
2146 }
2147 if (index >= caps.maxShaderStorageBufferBindings)
2148 {
2149 context->handleError(
2150 Error(GL_INVALID_VALUE,
2151 "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING"));
2152 return false;
2153 }
2154 break;
2155
Shao80957d92017-02-20 21:25:59 +08002156 case GL_VERTEX_BINDING_BUFFER:
2157 case GL_VERTEX_BINDING_DIVISOR:
2158 case GL_VERTEX_BINDING_OFFSET:
2159 case GL_VERTEX_BINDING_STRIDE:
2160 if (context->getClientVersion() < ES_3_1)
2161 {
2162 context->handleError(
2163 Error(GL_INVALID_ENUM,
2164 "Vertex Attrib Bindings are not supported in this version of GL"));
2165 return false;
2166 }
2167 if (index >= caps.maxVertexAttribBindings)
2168 {
2169 context->handleError(
2170 Error(GL_INVALID_VALUE,
2171 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2172 return false;
2173 }
2174 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002175 default:
2176 context->handleError(Error(GL_INVALID_ENUM));
2177 return false;
2178 }
2179
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002180 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002181 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002182 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002183 }
2184
2185 return true;
2186}
2187
2188bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2189{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002190 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002191 {
2192 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2193 return false;
2194 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002195 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002196}
2197
Geoff Langcf255ea2016-10-20 11:39:09 -07002198bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2199 GLenum target,
2200 GLuint index,
2201 GLsizei bufSize,
2202 GLsizei *length,
2203 GLint *data)
2204{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002205 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002206 {
2207 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2208 return false;
2209 }
2210
2211 if (!ValidateRobustEntryPoint(context, bufSize))
2212 {
2213 return false;
2214 }
2215
2216 if (!ValidateIndexedStateQuery(context, target, index, length))
2217 {
2218 return false;
2219 }
2220
2221 if (!ValidateRobustBufferSize(context, bufSize, *length))
2222 {
2223 return false;
2224 }
2225
2226 return true;
2227}
2228
Martin Radev66fb8202016-07-28 11:45:20 +03002229bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2230{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002231 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002232 {
2233 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2234 return false;
2235 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002236 return ValidateIndexedStateQuery(context, target, index, nullptr);
2237}
2238
2239bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2240 GLenum target,
2241 GLuint index,
2242 GLsizei bufSize,
2243 GLsizei *length,
2244 GLint64 *data)
2245{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002246 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002247 {
2248 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
2249 return false;
2250 }
2251
2252 if (!ValidateRobustEntryPoint(context, bufSize))
2253 {
2254 return false;
2255 }
2256
2257 if (!ValidateIndexedStateQuery(context, target, index, length))
2258 {
2259 return false;
2260 }
2261
2262 if (!ValidateRobustBufferSize(context, bufSize, *length))
2263 {
2264 return false;
2265 }
2266
2267 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002268}
2269
Jamie Madillb0817d12016-11-01 15:48:31 -04002270bool ValidateCopyBufferSubData(ValidationContext *context,
2271 GLenum readTarget,
2272 GLenum writeTarget,
2273 GLintptr readOffset,
2274 GLintptr writeOffset,
2275 GLsizeiptr size)
2276{
2277 if (context->getClientMajorVersion() < 3)
2278 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002279 context->handleError(
2280 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002281 return false;
2282 }
2283
2284 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2285 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002286 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002287 return false;
2288 }
2289
2290 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2291 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2292
2293 if (!readBuffer || !writeBuffer)
2294 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002295 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002296 return false;
2297 }
2298
2299 // Verify that readBuffer and writeBuffer are not currently mapped
2300 if (readBuffer->isMapped() || writeBuffer->isMapped())
2301 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002302 context->handleError(
2303 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002304 return false;
2305 }
2306
Jamie Madilld2f0c742016-11-02 10:34:41 -04002307 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2308 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2309 CheckedNumeric<GLintptr> checkedSize(size);
2310
2311 auto checkedReadSum = checkedReadOffset + checkedSize;
2312 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2313
2314 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2315 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2316 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002317 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002318 context->handleError(
2319 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002320 return false;
2321 }
2322
Jamie Madilld2f0c742016-11-02 10:34:41 -04002323 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002324 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002325 context->handleError(
2326 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002327 return false;
2328 }
2329
Jamie Madilld2f0c742016-11-02 10:34:41 -04002330 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2331 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2332 {
2333 context->handleError(
2334 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2335 return false;
2336 }
2337
2338 if (readBuffer == writeBuffer)
2339 {
2340 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2341 if (!checkedOffsetDiff.IsValid())
2342 {
2343 // This shold not be possible.
2344 UNREACHABLE();
2345 context->handleError(
2346 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2347 return false;
2348 }
2349
2350 if (checkedOffsetDiff.ValueOrDie() < size)
2351 {
2352 context->handleError(Error(GL_INVALID_VALUE));
2353 return false;
2354 }
2355 }
2356
Jamie Madillb0817d12016-11-01 15:48:31 -04002357 return true;
2358}
2359
Geoff Langc339c4e2016-11-29 10:37:36 -05002360bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2361{
2362 if (context->getClientMajorVersion() < 3)
2363 {
2364 context->handleError(
2365 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2366 return false;
2367 }
2368
2369 switch (name)
2370 {
2371 case GL_EXTENSIONS:
2372 if (index >= context->getExtensionStringCount())
2373 {
2374 context->handleError(Error(
2375 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2376 return false;
2377 }
2378 break;
2379
2380 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2381 if (!context->getExtensions().requestExtension)
2382 {
2383 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2384 return false;
2385 }
2386 if (index >= context->getRequestableExtensionStringCount())
2387 {
2388 context->handleError(
2389 Error(GL_INVALID_VALUE,
2390 "index must be less than the number of requestable extension strings."));
2391 return false;
2392 }
2393 break;
2394
2395 default:
2396 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2397 return false;
2398 }
2399
2400 return true;
2401}
2402
Jamie Madille8fb6402017-02-14 17:56:40 -05002403bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2404 GLenum target,
2405 GLsizei samples,
2406 GLenum internalformat,
2407 GLsizei width,
2408 GLsizei height)
2409{
2410 if (context->getClientMajorVersion() < 3)
2411 {
2412 context->handleError(Error(GL_INVALID_OPERATION));
2413 return false;
2414 }
2415
2416 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2417 height))
2418 {
2419 return false;
2420 }
2421
2422 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2423 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002424 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002425 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2426 samples > 0)
2427 {
2428 context->handleError(Error(GL_INVALID_OPERATION));
2429 return false;
2430 }
2431
2432 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2433 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2434 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2435 {
2436 context->handleError(
2437 Error(GL_INVALID_OPERATION,
2438 "Samples must not be greater than maximum supported value for the format."));
2439 return false;
2440 }
2441
2442 return true;
2443}
2444
Geoff Langaa086d62017-03-23 16:47:21 -04002445bool ValidateVertexAttribIPointer(ValidationContext *context,
2446 GLuint index,
2447 GLint size,
2448 GLenum type,
2449 GLsizei stride,
2450 const GLvoid *pointer)
2451{
2452 if (context->getClientMajorVersion() < 3)
2453 {
Geoff Langaa086d62017-03-23 16:47:21 -04002454 context->handleError(
Shao80957d92017-02-20 21:25:59 +08002455 Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
Geoff Langaa086d62017-03-23 16:47:21 -04002456 return false;
2457 }
2458
Shao80957d92017-02-20 21:25:59 +08002459 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002460 {
Geoff Langaa086d62017-03-23 16:47:21 -04002461 return false;
2462 }
2463
Geoff Langaa086d62017-03-23 16:47:21 -04002464 if (stride < 0)
2465 {
Shao80957d92017-02-20 21:25:59 +08002466 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Geoff Langaa086d62017-03-23 16:47:21 -04002467 return false;
2468 }
2469
Shao80957d92017-02-20 21:25:59 +08002470 const Caps &caps = context->getCaps();
2471 if (context->getClientVersion() >= ES_3_1)
2472 {
2473 if (stride > caps.maxVertexAttribStride)
2474 {
2475 context->handleError(
2476 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
2477 return false;
2478 }
2479
2480 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2481 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2482 // validation should be inherited.
2483 if (index >= caps.maxVertexAttribBindings)
2484 {
2485 context->handleError(
2486 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
2487 return false;
2488 }
2489 }
2490
Geoff Langaa086d62017-03-23 16:47:21 -04002491 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2492 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2493 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2494 // and the pointer argument is not NULL.
2495 if (context->getGLState().getVertexArrayId() != 0 &&
2496 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2497 {
2498 context->handleError(
2499 Error(GL_INVALID_OPERATION,
2500 "Client data cannot be used with a non-default vertex array object."));
2501 return false;
2502 }
2503
Geoff Lang2d62ab72017-03-23 16:54:40 -04002504 if (context->getExtensions().webglCompatibility)
2505 {
2506 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2507 {
2508 return false;
2509 }
2510 }
2511
Geoff Langaa086d62017-03-23 16:47:21 -04002512 return true;
2513}
2514
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002515bool ValidateGetSynciv(Context *context,
2516 GLsync sync,
2517 GLenum pname,
2518 GLsizei bufSize,
2519 GLsizei *length,
2520 GLint *values)
2521{
2522 if (context->getClientMajorVersion() < 3)
2523 {
2524 context->handleError(
2525 Error(GL_INVALID_OPERATION, "GetSynciv requires OpenGL ES 3.0 or higher."));
2526 return false;
2527 }
2528
2529 if (bufSize < 0)
2530 {
2531 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
2532 return false;
2533 }
2534
2535 FenceSync *fenceSync = context->getFenceSync(sync);
2536 if (!fenceSync)
2537 {
2538 context->handleError(Error(GL_INVALID_VALUE, "Invalid sync object."));
2539 return false;
2540 }
2541
2542 switch (pname)
2543 {
2544 case GL_OBJECT_TYPE:
2545 case GL_SYNC_CONDITION:
2546 case GL_SYNC_FLAGS:
2547 case GL_SYNC_STATUS:
2548 break;
2549
2550 default:
2551 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
2552 return false;
2553 }
2554
2555 return true;
2556}
2557
Jamie Madillc29968b2016-01-20 11:17:23 -05002558} // namespace gl