blob: 18b554e6d4509a22b5a72279df5e76b3fc74835b [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 Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040017#include "libANGLE/Renderbuffer.h"
18#include "libANGLE/Texture.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/validationES.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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050037 context->handleError(InvalidEnum() << "Invalid format.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -040038 return false;
39 }
40
41 if (!ValidES3Type(type))
42 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050043 context->handleError(InvalidEnum() << "Invalid type.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -040044 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050053 context->handleError(InvalidValue() << "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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050064 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
65 "GL_DEPTH_STENCIL if target is "
66 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -040067 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050073 context->handleError(InvalidOperation()
74 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -040075 return false;
76 }
77
78 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
79 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
80 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050081 context->handleError(InvalidOperation() << "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,
Jamie Madill876429b2017-04-20 15:46:24 -0400104 const void *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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500109 context->handleError(InvalidValue());
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500116 context->handleError(InvalidValue());
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500125 context->handleError(InvalidValue());
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500137 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800138 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500150 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800151 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500156 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800157 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500166 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800167 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800177 return false;
178 }
179 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400180
He Yunchaoced53ae2016-11-29 15:00:51 +0800181 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500182 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800183 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500190 context->handleError(InvalidOperation());
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500196 context->handleError(InvalidOperation());
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 Langc4e93662017-05-01 10:45:59 -0400202 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500203 if (isSubImage && actualInternalFormat == GL_NONE)
204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500205 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500206 return false;
207 }
208
Geoff Langc4e93662017-05-01 10:45:59 -0400209 const gl::InternalFormat &actualFormatInfo = isSubImage
210 ? *texture->getFormat(target, level).info
211 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400212 if (isCompressed)
213 {
tmartino7c102692015-10-02 16:43:40 -0400214 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500216 context->handleError(
217 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400218 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400219 }
220
Geoff Lang966c9402017-04-18 12:38:27 -0400221 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400222 {
Geoff Lang966c9402017-04-18 12:38:27 -0400223 if (!ValidCompressedSubImageSize(
224 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
225 texture->getWidth(target, level), texture->getHeight(target, level)))
226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500227 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400228 return false;
229 }
230
231 if (format != actualInternalFormat)
232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500233 context->handleError(InvalidOperation()
234 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400235 return false;
236 }
237 }
238 else
239 {
240 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500242 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400243 return false;
244 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400245 }
246
Geoff Langeb66a6e2016-10-31 13:06:12 -0400247 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400250 return false;
251 }
252
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400253 if (target == GL_TEXTURE_3D)
254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500255 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400257 }
258 }
259 else
260 {
Geoff Langca271392017-04-05 12:30:00 -0400261 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400262 {
Geoff Lang5d601382014-07-22 15:14:06 -0400263 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400264 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400265 }
266
267 // Validate sub image parameters
268 if (isSubImage)
269 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500270 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500272 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400273 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400274 }
275
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400276 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500278 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400279 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400280 }
281
282 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
283 std::numeric_limits<GLsizei>::max() - yoffset < height ||
284 std::numeric_limits<GLsizei>::max() - zoffset < depth)
285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500286 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400287 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400288 }
289
Geoff Langa9be0dc2014-12-17 12:34:40 -0500290 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
291 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
292 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500294 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400295 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400296 }
297 }
298
Corentin Wallezd2627992017-04-28 17:17:03 -0400299 if (!ValidImageDataSize(context, target, width, height, depth, actualInternalFormat, type,
300 pixels, imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400301 {
302 return false;
303 }
304
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400305 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700306 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400307 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400308 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800309 // ...data is not evenly divisible into the number of bytes needed to store in memory a
310 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400311 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400312 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400313 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400314 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400315 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
316
Geoff Langff5b2d52016-09-07 11:32:23 -0400317 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500319 context->handleError(InvalidOperation()
320 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400321 return false;
322 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400323 }
324
Jamie Madill7a5f7382014-03-05 15:01:24 -0500325 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700326 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500328 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400329 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500330 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400331 }
332
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 return true;
334}
335
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500336bool ValidateES3TexImage2DParameters(Context *context,
337 GLenum target,
338 GLint level,
339 GLenum internalformat,
340 bool isCompressed,
341 bool isSubImage,
342 GLint xoffset,
343 GLint yoffset,
344 GLint zoffset,
345 GLsizei width,
346 GLsizei height,
347 GLsizei depth,
348 GLint border,
349 GLenum format,
350 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400351 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400352 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500353{
354 if (!ValidTexture2DDestinationTarget(context, target))
355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500356 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500357 return false;
358 }
359
360 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
361 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400362 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500363}
364
365bool ValidateES3TexImage3DParameters(Context *context,
366 GLenum target,
367 GLint level,
368 GLenum internalformat,
369 bool isCompressed,
370 bool isSubImage,
371 GLint xoffset,
372 GLint yoffset,
373 GLint zoffset,
374 GLsizei width,
375 GLsizei height,
376 GLsizei depth,
377 GLint border,
378 GLenum format,
379 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400380 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400381 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500382{
383 if (!ValidTexture3DDestinationTarget(context, target))
384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500385 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500386 return false;
387 }
388
389 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
390 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400391 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500392}
393
Geoff Lang5d601382014-07-22 15:14:06 -0400394struct EffectiveInternalFormatInfo
395{
Jamie Madill76648fe2016-10-05 17:01:41 -0400396 GLenum effectiveFormat;
397 GLenum destFormat;
398 GLuint minRedBits;
399 GLuint maxRedBits;
400 GLuint minGreenBits;
401 GLuint maxGreenBits;
402 GLuint minBlueBits;
403 GLuint maxBlueBits;
404 GLuint minAlphaBits;
405 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400406};
407
Jamie Madill76648fe2016-10-05 17:01:41 -0400408static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
409 GLenum targetFormat,
410 const EffectiveInternalFormatInfo *list,
411 size_t size,
412 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400413{
Jamie Madill76648fe2016-10-05 17:01:41 -0400414 for (size_t curFormat = 0; curFormat < size; ++curFormat)
415 {
416 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
417 if ((formatInfo.destFormat == targetFormat) &&
418 (formatInfo.minRedBits <= srcFormat.redBits &&
419 formatInfo.maxRedBits >= srcFormat.redBits) &&
420 (formatInfo.minGreenBits <= srcFormat.greenBits &&
421 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
422 (formatInfo.minBlueBits <= srcFormat.blueBits &&
423 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
424 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
425 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
426 {
427 *outEffectiveFormat = formatInfo.effectiveFormat;
428 return true;
429 }
430 }
Geoff Lang5d601382014-07-22 15:14:06 -0400431
Jamie Madill76648fe2016-10-05 17:01:41 -0400432 *outEffectiveFormat = GL_NONE;
433 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400434}
435
Jamie Madill76648fe2016-10-05 17:01:41 -0400436bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
437 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400438{
Jamie Madill76648fe2016-10-05 17:01:41 -0400439 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
440 // Effective internal format coresponding to destination internal format and linear source
441 // buffer component sizes.
442 // | Source channel min/max sizes |
443 // Effective Internal Format | N/A | R | G | B | A |
444 // clang-format off
445 constexpr EffectiveInternalFormatInfo list[] = {
446 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
447 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
448 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
449 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
450 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
451 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
452 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
453 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
454 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
455 };
456 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400457
Jamie Madill76648fe2016-10-05 17:01:41 -0400458 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
459}
Geoff Lang5d601382014-07-22 15:14:06 -0400460
Jamie Madill76648fe2016-10-05 17:01:41 -0400461bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
462 const InternalFormat &destFormat,
463 GLenum *outEffectiveFormat)
464{
465 constexpr GLuint umax = UINT_MAX;
466
467 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
468 // Effective internal format coresponding to destination internal format andlinear source buffer
469 // component sizes.
470 // | Source channel min/max sizes |
471 // Effective Internal Format | Dest Format | R | G | B | A |
472 // clang-format off
473 constexpr EffectiveInternalFormatInfo list[] = {
474 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
475 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
476 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
477 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
478 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
479 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
480 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
481 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
482 };
483 // clang-format on
484
485 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
486 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400487}
488
He Yunchaoced53ae2016-11-29 15:00:51 +0800489static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
490 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400491 GLenum *outEffectiveFormat)
492{
Geoff Langca271392017-04-05 12:30:00 -0400493 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400494 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400495 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400496 }
497 else
498 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400499 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400500 }
Geoff Lang5d601382014-07-22 15:14:06 -0400501}
502
Corentin Wallez76287682016-04-25 09:23:38 -0400503static bool EqualOrFirstZero(GLuint first, GLuint second)
504{
505 return first == 0 || first == second;
506}
507
Geoff Langca271392017-04-05 12:30:00 -0400508static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
509 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400510 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400511{
Jamie Madill21b786b2016-11-01 17:41:31 -0400512 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400513 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400514 return false;
515 }
Geoff Lang5d601382014-07-22 15:14:06 -0400516
Jamie Madill21b786b2016-11-01 17:41:31 -0400517 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
518 // must both be signed, unsigned, or fixed point and both source and destinations
519 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
520 // conversion between fixed and floating point.
521
522 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
523 (framebufferFormatInfo.colorEncoding == GL_SRGB))
524 {
525 return false;
526 }
527
528 if (((textureFormatInfo.componentType == GL_INT) !=
529 (framebufferFormatInfo.componentType == GL_INT)) ||
530 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
531 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
532 {
533 return false;
534 }
535
536 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
537 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
538 textureFormatInfo.componentType == GL_FLOAT) &&
539 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
540 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
541 framebufferFormatInfo.componentType == GL_FLOAT))
542 {
543 return false;
544 }
545
546 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
547 // The effective internal format of the source buffer is determined with the following rules
548 // applied in order:
549 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
550 // format then the effective internal format is the source buffer's sized internal format.
551 // * If the source buffer is a texture that was created with an unsized base internal format,
552 // then the effective internal format is the source image array's effective internal
553 // format, as specified by table 3.12, which is determined from the <format> and <type>
554 // that were used when the source image array was specified by TexImage*.
555 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
556 // where Destination Internal Format matches internalformat and where the [source channel
557 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
558 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
559 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800560 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400561 if (readBufferHandle != 0)
562 {
563 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
564 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400565 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400566 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400567 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400568 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400569 else
Geoff Lang5d601382014-07-22 15:14:06 -0400570 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400571 // Renderbuffers cannot be created with an unsized internal format, so this must be an
572 // unsized-format texture. We can use the same table we use when creating textures to
573 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400574 sourceEffectiveFormat =
575 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400576 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400577 }
578 else
579 {
580 // The effective internal format must be derived from the source framebuffer's channel
581 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
582 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400583 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400584 GLenum effectiveFormat;
585 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
586 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400587 {
Geoff Langca271392017-04-05 12:30:00 -0400588 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400589 }
590 else
591 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400592 return false;
593 }
594 }
595 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
596 {
597 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400598 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400599 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
600 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
601 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
602 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
603 {
Geoff Langca271392017-04-05 12:30:00 -0400604 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400605 }
606 else
607 {
608 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400609 }
610 }
611 else
612 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400613 UNREACHABLE();
614 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400615 }
Geoff Lang5d601382014-07-22 15:14:06 -0400616 }
617
Geoff Langca271392017-04-05 12:30:00 -0400618 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400619 {
620 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
621 // sized, component sizes of the source and destination formats must exactly match if the
622 // destination format exists.
623 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
624 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
625 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
626 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
627 {
628 return false;
629 }
630 }
631
632 return true; // A conversion function exists, and no rule in the specification has precluded
633 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400634}
635
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500636bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
637 GLenum target,
638 GLint level,
639 GLenum internalformat,
640 bool isSubImage,
641 GLint xoffset,
642 GLint yoffset,
643 GLint zoffset,
644 GLint x,
645 GLint y,
646 GLsizei width,
647 GLsizei height,
648 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400649{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400650 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400651 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400652 xoffset, yoffset, zoffset, x, y, width, height, border,
653 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400654 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400657 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400658
Jamie Madill51f40ec2016-06-15 14:06:00 -0400659 const auto &state = context->getGLState();
660 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
661 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400662
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400663 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500665 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400666 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400667 }
668
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400669 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500671 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400672 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400673 }
674
Jamie Madill0c8abca2016-07-22 20:21:26 -0400675 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400676
677 if (isSubImage)
678 {
Geoff Langca271392017-04-05 12:30:00 -0400679 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500680 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500682 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400683 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400684 }
685 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400686 else
687 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400688 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400689 const InternalFormat &framebufferFormat = *source->getFormat().info;
690 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400691 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500693 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400694 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400695 }
696 }
697
Geoff Lang784a8fd2013-09-24 12:33:16 -0400698 // If width or height is zero, it is a no-op. Return false without setting an error.
699 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700}
701
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500702bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
703 GLenum target,
704 GLint level,
705 GLenum internalformat,
706 bool isSubImage,
707 GLint xoffset,
708 GLint yoffset,
709 GLint zoffset,
710 GLint x,
711 GLint y,
712 GLsizei width,
713 GLsizei height,
714 GLint border)
715{
716 if (!ValidTexture2DDestinationTarget(context, target))
717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500718 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500719 return false;
720 }
721
722 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
723 xoffset, yoffset, zoffset, x, y, width, height,
724 border);
725}
726
727bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
728 GLenum target,
729 GLint level,
730 GLenum internalformat,
731 bool isSubImage,
732 GLint xoffset,
733 GLint yoffset,
734 GLint zoffset,
735 GLint x,
736 GLint y,
737 GLsizei width,
738 GLsizei height,
739 GLint border)
740{
741 if (!ValidTexture3DDestinationTarget(context, target))
742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500743 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500744 return false;
745 }
746
747 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
748 xoffset, yoffset, zoffset, x, y, width, height,
749 border);
750}
751
752bool ValidateES3TexStorageParametersBase(Context *context,
753 GLenum target,
754 GLsizei levels,
755 GLenum internalformat,
756 GLsizei width,
757 GLsizei height,
758 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759{
760 if (width < 1 || height < 1 || depth < 1 || levels < 1)
761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500762 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400763 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 }
765
Geoff Langb92c1332015-09-04 12:54:55 -0400766 GLsizei maxDim = std::max(width, height);
767 if (target != GL_TEXTURE_2D_ARRAY)
768 {
769 maxDim = std::max(maxDim, depth);
770 }
771
772 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500774 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400775 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 }
777
Geoff Langaae65a42014-05-26 12:43:44 -0400778 const gl::Caps &caps = context->getCaps();
779
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 switch (target)
781 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800782 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 {
Geoff Langaae65a42014-05-26 12:43:44 -0400784 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
785 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500787 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 }
790 }
791 break;
792
He Yunchaoced53ae2016-11-29 15:00:51 +0800793 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 if (width != height)
796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500797 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400798 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400799 }
800
Geoff Langaae65a42014-05-26 12:43:44 -0400801 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500803 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400804 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400805 }
806 }
807 break;
808
He Yunchaoced53ae2016-11-29 15:00:51 +0800809 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400810 {
Geoff Langaae65a42014-05-26 12:43:44 -0400811 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
812 static_cast<GLuint>(height) > caps.max3DTextureSize ||
813 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500815 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400816 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400817 }
818 }
819 break;
820
He Yunchaoced53ae2016-11-29 15:00:51 +0800821 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400822 {
Geoff Langaae65a42014-05-26 12:43:44 -0400823 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
824 static_cast<GLuint>(height) > caps.max2DTextureSize ||
825 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500827 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400828 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 }
830 }
831 break;
832
He Yunchaoced53ae2016-11-29 15:00:51 +0800833 default:
834 UNREACHABLE();
835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
837
Geoff Lang691e58c2014-12-19 17:03:25 -0500838 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 if (!texture || texture->id() == 0)
840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500841 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 }
844
Geoff Lang69cce582015-09-17 13:20:36 -0400845 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500847 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 }
850
Geoff Langca271392017-04-05 12:30:00 -0400851 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400852 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500854 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400855 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400856 }
857
Geoff Langca271392017-04-05 12:30:00 -0400858 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500860 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400861 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400862 }
863
864 return true;
865}
866
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500867bool ValidateES3TexStorage2DParameters(Context *context,
868 GLenum target,
869 GLsizei levels,
870 GLenum internalformat,
871 GLsizei width,
872 GLsizei height,
873 GLsizei depth)
874{
875 if (!ValidTexture2DTarget(context, target))
876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500877 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500878 return false;
879 }
880
881 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
882 height, depth);
883}
884
885bool ValidateES3TexStorage3DParameters(Context *context,
886 GLenum target,
887 GLsizei levels,
888 GLenum internalformat,
889 GLsizei width,
890 GLsizei height,
891 GLsizei depth)
892{
893 if (!ValidTexture3DTarget(context, target))
894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500895 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500896 return false;
897 }
898
899 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
900 height, depth);
901}
902
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500903bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
904{
Martin Radev1be913c2016-07-11 17:59:16 +0300905 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500907 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500908 return false;
909 }
910
911 return ValidateBeginQueryBase(context, target, id);
912}
913
914bool ValidateEndQuery(gl::Context *context, GLenum target)
915{
Martin Radev1be913c2016-07-11 17:59:16 +0300916 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500918 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500919 return false;
920 }
921
922 return ValidateEndQueryBase(context, target);
923}
924
925bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
926{
Martin Radev1be913c2016-07-11 17:59:16 +0300927 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500929 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500930 return false;
931 }
932
Geoff Lang2186c382016-10-14 10:54:54 -0400933 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500934}
935
936bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
937{
Martin Radev1be913c2016-07-11 17:59:16 +0300938 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500940 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500941 return false;
942 }
943
Geoff Lang2186c382016-10-14 10:54:54 -0400944 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500945}
946
He Yunchaoced53ae2016-11-29 15:00:51 +0800947bool ValidateFramebufferTextureLayer(Context *context,
948 GLenum target,
949 GLenum attachment,
950 GLuint texture,
951 GLint level,
952 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400953{
Martin Radev1be913c2016-07-11 17:59:16 +0300954 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500956 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400958 }
959
Jamie Madill55ec3b12014-07-03 10:38:57 -0400960 if (layer < 0)
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400964 }
965
966 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
967 {
968 return false;
969 }
970
971 const gl::Caps &caps = context->getCaps();
972 if (texture != 0)
973 {
974 gl::Texture *tex = context->getTexture(texture);
975 ASSERT(tex);
976
977 switch (tex->getTarget())
978 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800979 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400980 {
981 if (level > gl::log2(caps.max2DTextureSize))
982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500983 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400984 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400985 }
986
987 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500989 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400990 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400991 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400992 }
993 break;
994
He Yunchaoced53ae2016-11-29 15:00:51 +0800995 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400996 {
997 if (level > gl::log2(caps.max3DTextureSize))
998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500999 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001000 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001001 }
1002
1003 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001005 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001006 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001007 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001008 }
1009 break;
1010
He Yunchaoced53ae2016-11-29 15:00:51 +08001011 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001013 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001014 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001015
Jamie Madilla3944d42016-07-22 22:13:26 -04001016 const auto &format = tex->getFormat(tex->getTarget(), level);
1017 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001020 return false;
1021 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001022 }
1023
1024 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001025}
1026
He Yunchaoced53ae2016-11-29 15:00:51 +08001027bool ValidateInvalidateFramebuffer(Context *context,
1028 GLenum target,
1029 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001030 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031{
Martin Radev1be913c2016-07-11 17:59:16 +03001032 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001034 context->handleError(InvalidOperation() << "Operation only supported on ES 3.0 and above");
Austin Kinross08332632015-05-05 13:35:47 -07001035 return false;
1036 }
1037
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 bool defaultFramebuffer = false;
1039
1040 switch (target)
1041 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001042 case GL_DRAW_FRAMEBUFFER:
1043 case GL_FRAMEBUFFER:
1044 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1045 break;
1046 case GL_READ_FRAMEBUFFER:
1047 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1048 break;
1049 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001050 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053
He Yunchaoced53ae2016-11-29 15:00:51 +08001054 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1055 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056}
1057
Jamie Madillc29968b2016-01-20 11:17:23 -05001058bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001059{
Martin Radev1be913c2016-07-11 17:59:16 +03001060 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001062 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001063 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001064 }
1065
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001066 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001068 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001069 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001070 }
1071
1072 return true;
1073}
1074
Olli Etuaho71dfb362016-03-10 14:04:27 +02001075bool ValidateDrawRangeElements(Context *context,
1076 GLenum mode,
1077 GLuint start,
1078 GLuint end,
1079 GLsizei count,
1080 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001081 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001082{
Martin Radev1be913c2016-07-11 17:59:16 +03001083 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001085 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001086 return false;
1087 }
1088
1089 if (end < start)
1090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001091 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001092 return false;
1093 }
1094
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001095 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001096 {
1097 return false;
1098 }
1099
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001100 // Use the parameter buffer to retrieve and cache the index range.
1101 const auto &params = context->getParams<HasIndexRange>();
1102 const auto &indexRangeOpt = params.getIndexRange();
1103 if (!indexRangeOpt.valid())
1104 {
1105 // Unexpected error.
1106 return false;
1107 }
1108
1109 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001110 {
1111 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001112 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001113 return false;
1114 }
1115 return true;
1116}
1117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001119{
Martin Radev1be913c2016-07-11 17:59:16 +03001120 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001122 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001123 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001124 }
1125
Jamie Madill78f41802014-08-25 15:47:55 -04001126 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001127}
1128
Jamie Madillb885e572015-02-03 16:16:04 -05001129bool ValidateReadBuffer(Context *context, GLenum src)
1130{
Martin Radev1be913c2016-07-11 17:59:16 +03001131 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001133 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001134 return false;
1135 }
1136
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001137 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001138
1139 if (readFBO == nullptr)
1140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001142 return false;
1143 }
1144
1145 if (src == GL_NONE)
1146 {
1147 return true;
1148 }
1149
Olli Etuaho84c9f592016-03-09 14:37:25 +02001150 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001152 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001153 return false;
1154 }
1155
1156 if (readFBO->id() == 0)
1157 {
1158 if (src != GL_BACK)
1159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001160 context->handleError(
1161 InvalidOperation()
1162 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001163 return false;
1164 }
1165 }
1166 else
1167 {
1168 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1169
1170 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001172 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001173 return false;
1174 }
1175 }
1176
1177 return true;
1178}
1179
Jamie Madill86af3d22015-07-21 15:14:07 -04001180bool ValidateCompressedTexImage3D(Context *context,
1181 GLenum target,
1182 GLint level,
1183 GLenum internalformat,
1184 GLsizei width,
1185 GLsizei height,
1186 GLsizei depth,
1187 GLint border,
1188 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001189 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001190{
Martin Radev1be913c2016-07-11 17:59:16 +03001191 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001194 return false;
1195 }
1196
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001197 if (!ValidTextureTarget(context, target))
1198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001199 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001200 return false;
1201 }
1202
Jamie Madille2e406c2016-06-02 13:04:10 -04001203 // Validate image size
1204 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001206 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001207 return false;
1208 }
1209
Geoff Langca271392017-04-05 12:30:00 -04001210 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001211 if (!formatInfo.compressed)
1212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001213 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001214 return false;
1215 }
1216
Jamie Madill513558d2016-06-02 13:04:11 -04001217 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001218 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001219 if (blockSizeOrErr.isError())
1220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001222 return false;
1223 }
1224 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001226 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001227 return false;
1228 }
1229
1230 // 3D texture target validation
1231 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001234 return false;
1235 }
1236
1237 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001238 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001239 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1240 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001241 {
1242 return false;
1243 }
1244
1245 return true;
1246}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001247
Corentin Wallezb2931602017-04-11 15:58:57 -04001248bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1249 GLenum target,
1250 GLint level,
1251 GLenum internalformat,
1252 GLsizei width,
1253 GLsizei height,
1254 GLsizei depth,
1255 GLint border,
1256 GLsizei imageSize,
1257 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001258 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001259{
1260 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1261 {
1262 return false;
1263 }
1264
1265 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1266 depth, border, imageSize, data);
1267}
1268
Austin Kinrossbc781f32015-10-26 09:27:38 -07001269bool ValidateBindVertexArray(Context *context, GLuint array)
1270{
Martin Radev1be913c2016-07-11 17:59:16 +03001271 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001273 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001274 return false;
1275 }
1276
1277 return ValidateBindVertexArrayBase(context, array);
1278}
1279
Austin Kinrossbc781f32015-10-26 09:27:38 -07001280bool ValidateIsVertexArray(Context *context)
1281{
Martin Radev1be913c2016-07-11 17:59:16 +03001282 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001284 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001285 return false;
1286 }
1287
1288 return true;
1289}
Geoff Langc5629752015-12-07 16:29:04 -05001290
Jiajia Qin6eafb042016-12-27 17:04:07 +08001291static bool ValidateBindBufferCommon(Context *context,
1292 GLenum target,
1293 GLuint index,
1294 GLuint buffer,
1295 GLintptr offset,
1296 GLsizeiptr size)
1297{
1298 if (context->getClientMajorVersion() < 3)
1299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001300 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001301 return false;
1302 }
1303
1304 if (buffer != 0 && offset < 0)
1305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001306 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001307 return false;
1308 }
1309
1310 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1311 !context->isBufferGenerated(buffer))
1312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001313 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001314 return false;
1315 }
1316
1317 const Caps &caps = context->getCaps();
1318 switch (target)
1319 {
1320 case GL_TRANSFORM_FEEDBACK_BUFFER:
1321 {
1322 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(InvalidValue() << "index is greater than or equal to the "
1325 "number of TRANSFORM_FEEDBACK_BUFFER "
1326 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001327 return false;
1328 }
1329 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001332 return false;
1333 }
1334
1335 TransformFeedback *curTransformFeedback =
1336 context->getGLState().getCurrentTransformFeedback();
1337 if (curTransformFeedback && curTransformFeedback->isActive())
1338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 context->handleError(InvalidOperation()
1340 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1341 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001342 return false;
1343 }
1344 break;
1345 }
1346 case GL_UNIFORM_BUFFER:
1347 {
1348 if (index >= caps.maxUniformBufferBindings)
1349 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001350 context->handleError(InvalidValue() << "index is greater than or equal to the "
1351 "number of UNIFORM_BUFFER indexed "
1352 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001353 return false;
1354 }
1355
1356 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1357 {
1358 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 InvalidValue()
1360 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001361 return false;
1362 }
1363 break;
1364 }
1365 case GL_ATOMIC_COUNTER_BUFFER:
1366 {
1367 if (context->getClientVersion() < ES_3_1)
1368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidEnum()
1370 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001371 return false;
1372 }
1373 if (index >= caps.maxAtomicCounterBufferBindings)
1374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(InvalidValue() << "index is greater than or equal to the "
1376 "number of ATOMIC_COUNTER_BUFFER "
1377 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001378 return false;
1379 }
1380 if (buffer != 0 && (offset % 4) != 0)
1381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001383 return false;
1384 }
1385 break;
1386 }
1387 case GL_SHADER_STORAGE_BUFFER:
1388 {
1389 if (context->getClientVersion() < ES_3_1)
1390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidEnum()
1392 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001393 return false;
1394 }
1395 if (index >= caps.maxShaderStorageBufferBindings)
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidValue() << "index is greater than or equal to the "
1398 "number of SHADER_STORAGE_BUFFER "
1399 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001400 return false;
1401 }
1402 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidValue() << "offset must be multiple of value of "
1405 "SHADER_STORAGE_BUFFER_OFFSET_"
1406 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001407 return false;
1408 }
1409 break;
1410 }
1411 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001413 return false;
1414 }
1415
1416 return true;
1417}
1418
1419bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1420{
1421 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1422}
1423
1424bool ValidateBindBufferRange(Context *context,
1425 GLenum target,
1426 GLuint index,
1427 GLuint buffer,
1428 GLintptr offset,
1429 GLsizeiptr size)
1430{
1431 if (buffer != 0 && size <= 0)
1432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidValue()
1434 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001435 return false;
1436 }
1437 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1438}
1439
Geoff Langc5629752015-12-07 16:29:04 -05001440bool ValidateProgramBinary(Context *context,
1441 GLuint program,
1442 GLenum binaryFormat,
1443 const void *binary,
1444 GLint length)
1445{
Martin Radev1be913c2016-07-11 17:59:16 +03001446 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001449 return false;
1450 }
1451
1452 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1453}
1454
1455bool ValidateGetProgramBinary(Context *context,
1456 GLuint program,
1457 GLsizei bufSize,
1458 GLsizei *length,
1459 GLenum *binaryFormat,
1460 void *binary)
1461{
Martin Radev1be913c2016-07-11 17:59:16 +03001462 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001464 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001465 return false;
1466 }
1467
1468 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1469}
1470
Olli Etuahof0fee072016-03-30 15:11:58 +03001471bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001472{
Martin Radev1be913c2016-07-11 17:59:16 +03001473 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001475 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Geoff Langc5629752015-12-07 16:29:04 -05001476 return false;
1477 }
1478
1479 if (GetValidProgram(context, program) == nullptr)
1480 {
1481 return false;
1482 }
1483
1484 switch (pname)
1485 {
1486 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001487 if (value != GL_FALSE && value != GL_TRUE)
1488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(InvalidValue()
1490 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001491 return false;
1492 }
Geoff Langc5629752015-12-07 16:29:04 -05001493 break;
1494
Yunchao He61afff12017-03-14 15:34:03 +08001495 case GL_PROGRAM_SEPARABLE:
1496 if (context->getClientVersion() < ES_3_1)
1497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001498 context->handleError(InvalidEnum()
1499 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001500 return false;
1501 }
1502
1503 if (value != GL_FALSE && value != GL_TRUE)
1504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001505 context->handleError(InvalidValue()
1506 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001507 return false;
1508 }
1509 break;
1510
Geoff Langc5629752015-12-07 16:29:04 -05001511 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001512 context->handleError(InvalidEnum()
1513 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001514 return false;
1515 }
1516
1517 return true;
1518}
Jamie Madillc29968b2016-01-20 11:17:23 -05001519
1520bool ValidateBlitFramebuffer(Context *context,
1521 GLint srcX0,
1522 GLint srcY0,
1523 GLint srcX1,
1524 GLint srcY1,
1525 GLint dstX0,
1526 GLint dstY0,
1527 GLint dstX1,
1528 GLint dstY1,
1529 GLbitfield mask,
1530 GLenum filter)
1531{
Martin Radev1be913c2016-07-11 17:59:16 +03001532 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001534 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001535 return false;
1536 }
1537
1538 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1539 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001540}
Jamie Madillc29968b2016-01-20 11:17:23 -05001541
1542bool ValidateClearBufferiv(ValidationContext *context,
1543 GLenum buffer,
1544 GLint drawbuffer,
1545 const GLint *value)
1546{
1547 switch (buffer)
1548 {
1549 case GL_COLOR:
1550 if (drawbuffer < 0 ||
1551 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001554 return false;
1555 }
Geoff Lang76e65652017-03-27 14:58:02 -04001556 if (context->getExtensions().webglCompatibility)
1557 {
1558 constexpr GLenum validComponentTypes[] = {GL_INT};
1559 if (ValidateWebGLFramebufferAttachmentClearType(
1560 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1561 {
1562 return false;
1563 }
1564 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001565 break;
1566
1567 case GL_STENCIL:
1568 if (drawbuffer != 0)
1569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001571 return false;
1572 }
1573 break;
1574
1575 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001577 return false;
1578 }
1579
1580 return ValidateClearBuffer(context);
1581}
1582
1583bool ValidateClearBufferuiv(ValidationContext *context,
1584 GLenum buffer,
1585 GLint drawbuffer,
1586 const GLuint *value)
1587{
1588 switch (buffer)
1589 {
1590 case GL_COLOR:
1591 if (drawbuffer < 0 ||
1592 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001595 return false;
1596 }
Geoff Lang76e65652017-03-27 14:58:02 -04001597 if (context->getExtensions().webglCompatibility)
1598 {
1599 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1600 if (ValidateWebGLFramebufferAttachmentClearType(
1601 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1602 {
1603 return false;
1604 }
1605 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001606 break;
1607
1608 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001610 return false;
1611 }
1612
1613 return ValidateClearBuffer(context);
1614}
1615
1616bool ValidateClearBufferfv(ValidationContext *context,
1617 GLenum buffer,
1618 GLint drawbuffer,
1619 const GLfloat *value)
1620{
1621 switch (buffer)
1622 {
1623 case GL_COLOR:
1624 if (drawbuffer < 0 ||
1625 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001627 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001628 return false;
1629 }
Geoff Lang76e65652017-03-27 14:58:02 -04001630 if (context->getExtensions().webglCompatibility)
1631 {
1632 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1633 GL_SIGNED_NORMALIZED};
1634 if (ValidateWebGLFramebufferAttachmentClearType(
1635 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1636 {
1637 return false;
1638 }
1639 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001640 break;
1641
1642 case GL_DEPTH:
1643 if (drawbuffer != 0)
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001646 return false;
1647 }
1648 break;
1649
1650 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001651 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001652 return false;
1653 }
1654
1655 return ValidateClearBuffer(context);
1656}
1657
1658bool ValidateClearBufferfi(ValidationContext *context,
1659 GLenum buffer,
1660 GLint drawbuffer,
1661 GLfloat depth,
1662 GLint stencil)
1663{
1664 switch (buffer)
1665 {
1666 case GL_DEPTH_STENCIL:
1667 if (drawbuffer != 0)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001670 return false;
1671 }
1672 break;
1673
1674 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001675 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001676 return false;
1677 }
1678
1679 return ValidateClearBuffer(context);
1680}
1681
1682bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1683{
Martin Radev1be913c2016-07-11 17:59:16 +03001684 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001686 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Jamie Madillc29968b2016-01-20 11:17:23 -05001687 return false;
1688 }
1689
1690 return ValidateDrawBuffersBase(context, n, bufs);
1691}
1692
1693bool ValidateCopyTexSubImage3D(Context *context,
1694 GLenum target,
1695 GLint level,
1696 GLint xoffset,
1697 GLint yoffset,
1698 GLint zoffset,
1699 GLint x,
1700 GLint y,
1701 GLsizei width,
1702 GLsizei height)
1703{
Martin Radev1be913c2016-07-11 17:59:16 +03001704 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001706 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001707 return false;
1708 }
1709
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001710 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1711 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001712}
1713
Jamie Madill73a84962016-02-12 09:27:23 -05001714bool ValidateTexImage3D(Context *context,
1715 GLenum target,
1716 GLint level,
1717 GLint internalformat,
1718 GLsizei width,
1719 GLsizei height,
1720 GLsizei depth,
1721 GLint border,
1722 GLenum format,
1723 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001724 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001725{
Martin Radev1be913c2016-07-11 17:59:16 +03001726 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001729 return false;
1730 }
1731
1732 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001733 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001734 pixels);
1735}
1736
Geoff Langc52f6f12016-10-14 10:18:00 -04001737bool ValidateTexImage3DRobustANGLE(Context *context,
1738 GLenum target,
1739 GLint level,
1740 GLint internalformat,
1741 GLsizei width,
1742 GLsizei height,
1743 GLsizei depth,
1744 GLint border,
1745 GLenum format,
1746 GLenum type,
1747 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001748 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001749{
1750 if (context->getClientMajorVersion() < 3)
1751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001752 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001753 return false;
1754 }
1755
1756 if (!ValidateRobustEntryPoint(context, bufSize))
1757 {
1758 return false;
1759 }
1760
1761 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1762 0, 0, width, height, depth, border, format, type,
1763 bufSize, pixels);
1764}
1765
Jamie Madill73a84962016-02-12 09:27:23 -05001766bool ValidateTexSubImage3D(Context *context,
1767 GLenum target,
1768 GLint level,
1769 GLint xoffset,
1770 GLint yoffset,
1771 GLint zoffset,
1772 GLsizei width,
1773 GLsizei height,
1774 GLsizei depth,
1775 GLenum format,
1776 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001777 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001778{
Martin Radev1be913c2016-07-11 17:59:16 +03001779 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001781 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001782 return false;
1783 }
1784
1785 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1786 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001787 -1, pixels);
1788}
1789
1790bool ValidateTexSubImage3DRobustANGLE(Context *context,
1791 GLenum target,
1792 GLint level,
1793 GLint xoffset,
1794 GLint yoffset,
1795 GLint zoffset,
1796 GLsizei width,
1797 GLsizei height,
1798 GLsizei depth,
1799 GLenum format,
1800 GLenum type,
1801 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001802 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001803{
1804 if (context->getClientMajorVersion() < 3)
1805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001806 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001807 return false;
1808 }
1809
1810 if (!ValidateRobustEntryPoint(context, bufSize))
1811 {
1812 return false;
1813 }
1814
1815 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1816 yoffset, zoffset, width, height, depth, 0, format, type,
1817 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001818}
1819
1820bool ValidateCompressedTexSubImage3D(Context *context,
1821 GLenum target,
1822 GLint level,
1823 GLint xoffset,
1824 GLint yoffset,
1825 GLint zoffset,
1826 GLsizei width,
1827 GLsizei height,
1828 GLsizei depth,
1829 GLenum format,
1830 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001831 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001832{
Martin Radev1be913c2016-07-11 17:59:16 +03001833 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001836 return false;
1837 }
1838
Geoff Langca271392017-04-05 12:30:00 -04001839 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001840 if (!formatInfo.compressed)
1841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001842 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001843 return false;
1844 }
1845
Jamie Madill513558d2016-06-02 13:04:11 -04001846 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001847 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001848 if (blockSizeOrErr.isError())
1849 {
1850 context->handleError(blockSizeOrErr.getError());
1851 return false;
1852 }
1853 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001855 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001856 return false;
1857 }
1858
1859 if (!data)
1860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001861 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001862 return false;
1863 }
1864
1865 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001866 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001867}
Corentin Wallezb2931602017-04-11 15:58:57 -04001868bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1869 GLenum target,
1870 GLint level,
1871 GLint xoffset,
1872 GLint yoffset,
1873 GLint zoffset,
1874 GLsizei width,
1875 GLsizei height,
1876 GLsizei depth,
1877 GLenum format,
1878 GLsizei imageSize,
1879 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001880 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001881{
1882 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1883 {
1884 return false;
1885 }
1886
1887 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1888 height, depth, format, imageSize, data);
1889}
Jamie Madill73a84962016-02-12 09:27:23 -05001890
Olli Etuaho41997e72016-03-10 13:38:39 +02001891bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1892{
1893 return ValidateGenOrDeleteES3(context, n);
1894}
1895
1896bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1897{
1898 return ValidateGenOrDeleteES3(context, n);
1899}
1900
1901bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1902{
1903 return ValidateGenOrDeleteCountES3(context, count);
1904}
1905
1906bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1907{
1908 return ValidateGenOrDeleteCountES3(context, count);
1909}
1910
1911bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1912{
1913 return ValidateGenOrDeleteES3(context, n);
1914}
1915
1916bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1917{
1918 if (!ValidateGenOrDeleteES3(context, n))
1919 {
1920 return false;
1921 }
1922 for (GLint i = 0; i < n; ++i)
1923 {
1924 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1925 if (transformFeedback != nullptr && transformFeedback->isActive())
1926 {
1927 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001928 context->handleError(InvalidOperation()
1929 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001930 return false;
1931 }
1932 }
1933 return true;
1934}
1935
1936bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1937{
1938 return ValidateGenOrDeleteES3(context, n);
1939}
1940
1941bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1942{
1943 return ValidateGenOrDeleteES3(context, n);
1944}
1945
1946bool ValidateGenOrDeleteES3(Context *context, GLint n)
1947{
Martin Radev1be913c2016-07-11 17:59:16 +03001948 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001950 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001951 return false;
1952 }
1953 return ValidateGenOrDelete(context, n);
1954}
1955
1956bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1957{
Martin Radev1be913c2016-07-11 17:59:16 +03001958 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001960 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001961 return false;
1962 }
1963 if (count < 0)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02001966 return false;
1967 }
1968 return true;
1969}
1970
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001971bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1972{
Martin Radev1be913c2016-07-11 17:59:16 +03001973 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001976 return false;
1977 }
1978 switch (primitiveMode)
1979 {
1980 case GL_TRIANGLES:
1981 case GL_LINES:
1982 case GL_POINTS:
1983 break;
1984
1985 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001986 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001987 return false;
1988 }
1989
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001990 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001991 ASSERT(transformFeedback != nullptr);
1992
1993 if (transformFeedback->isActive())
1994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001995 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001996 return false;
1997 }
1998 return true;
1999}
2000
Jamie Madill876429b2017-04-20 15:46:24 -04002001bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002002{
Geoff Lang496c02d2016-10-20 11:38:11 -07002003 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2004}
2005
2006bool ValidateGetBufferPointervRobustANGLE(Context *context,
2007 GLenum target,
2008 GLenum pname,
2009 GLsizei bufSize,
2010 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002011 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002012{
2013 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002014 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002015 return false;
2016 }
2017
Geoff Lang496c02d2016-10-20 11:38:11 -07002018 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2019 {
2020 return false;
2021 }
2022
2023 if (!ValidateRobustBufferSize(context, bufSize, *length))
2024 {
2025 return false;
2026 }
2027
2028 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002029}
2030
2031bool ValidateUnmapBuffer(Context *context, GLenum target)
2032{
Martin Radev1be913c2016-07-11 17:59:16 +03002033 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002035 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002036 return false;
2037 }
2038
2039 return ValidateUnmapBufferBase(context, target);
2040}
2041
2042bool ValidateMapBufferRange(Context *context,
2043 GLenum target,
2044 GLintptr offset,
2045 GLsizeiptr length,
2046 GLbitfield access)
2047{
Martin Radev1be913c2016-07-11 17:59:16 +03002048 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002050 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002051 return false;
2052 }
2053
2054 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2055}
2056
2057bool ValidateFlushMappedBufferRange(Context *context,
2058 GLenum target,
2059 GLintptr offset,
2060 GLsizeiptr length)
2061{
Martin Radev1be913c2016-07-11 17:59:16 +03002062 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002064 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002065 return false;
2066 }
2067
2068 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2069}
2070
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002071bool ValidateIndexedStateQuery(ValidationContext *context,
2072 GLenum pname,
2073 GLuint index,
2074 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002075{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002076 if (length)
2077 {
2078 *length = 0;
2079 }
2080
Martin Radev66fb8202016-07-28 11:45:20 +03002081 GLenum nativeType;
2082 unsigned int numParams;
2083 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002085 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002086 return false;
2087 }
2088
2089 const Caps &caps = context->getCaps();
2090 switch (pname)
2091 {
2092 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2093 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2094 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2095 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002097 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002098 return false;
2099 }
2100 break;
2101
2102 case GL_UNIFORM_BUFFER_START:
2103 case GL_UNIFORM_BUFFER_SIZE:
2104 case GL_UNIFORM_BUFFER_BINDING:
2105 if (index >= caps.maxUniformBufferBindings)
2106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002107 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002108 return false;
2109 }
2110 break;
Shao80957d92017-02-20 21:25:59 +08002111
Martin Radev66fb8202016-07-28 11:45:20 +03002112 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2113 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2114 if (index >= 3u)
2115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002116 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002117 return false;
2118 }
2119 break;
Shao80957d92017-02-20 21:25:59 +08002120
Jiajia Qin6eafb042016-12-27 17:04:07 +08002121 case GL_ATOMIC_COUNTER_BUFFER_START:
2122 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2123 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2124 if (context->getClientVersion() < ES_3_1)
2125 {
2126 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002127 InvalidEnum()
2128 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002129 return false;
2130 }
2131 if (index >= caps.maxAtomicCounterBufferBindings)
2132 {
2133 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002134 InvalidValue()
2135 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002136 return false;
2137 }
2138 break;
Shao80957d92017-02-20 21:25:59 +08002139
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002140 case GL_SHADER_STORAGE_BUFFER_START:
2141 case GL_SHADER_STORAGE_BUFFER_SIZE:
2142 case GL_SHADER_STORAGE_BUFFER_BINDING:
2143 if (context->getClientVersion() < ES_3_1)
2144 {
2145 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 InvalidEnum()
2147 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002148 return false;
2149 }
2150 if (index >= caps.maxShaderStorageBufferBindings)
2151 {
2152 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002153 InvalidValue()
2154 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002155 return false;
2156 }
2157 break;
2158
Shao80957d92017-02-20 21:25:59 +08002159 case GL_VERTEX_BINDING_BUFFER:
2160 case GL_VERTEX_BINDING_DIVISOR:
2161 case GL_VERTEX_BINDING_OFFSET:
2162 case GL_VERTEX_BINDING_STRIDE:
2163 if (context->getClientVersion() < ES_3_1)
2164 {
2165 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002166 InvalidEnum()
2167 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002168 return false;
2169 }
2170 if (index >= caps.maxVertexAttribBindings)
2171 {
2172 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002173 InvalidValue()
2174 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002175 return false;
2176 }
2177 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002178 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002180 return false;
2181 }
2182
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002183 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002184 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002185 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002186 }
2187
2188 return true;
2189}
2190
2191bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2192{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002193 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002196 return false;
2197 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002198 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002199}
2200
Geoff Langcf255ea2016-10-20 11:39:09 -07002201bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2202 GLenum target,
2203 GLuint index,
2204 GLsizei bufSize,
2205 GLsizei *length,
2206 GLint *data)
2207{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002208 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Langcf255ea2016-10-20 11:39:09 -07002211 return false;
2212 }
2213
2214 if (!ValidateRobustEntryPoint(context, bufSize))
2215 {
2216 return false;
2217 }
2218
2219 if (!ValidateIndexedStateQuery(context, target, index, length))
2220 {
2221 return false;
2222 }
2223
2224 if (!ValidateRobustBufferSize(context, bufSize, *length))
2225 {
2226 return false;
2227 }
2228
2229 return true;
2230}
2231
Martin Radev66fb8202016-07-28 11:45:20 +03002232bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2233{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002234 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002237 return false;
2238 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002239 return ValidateIndexedStateQuery(context, target, index, nullptr);
2240}
2241
2242bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2243 GLenum target,
2244 GLuint index,
2245 GLsizei bufSize,
2246 GLsizei *length,
2247 GLint64 *data)
2248{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002249 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002251 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002252 return false;
2253 }
2254
2255 if (!ValidateRobustEntryPoint(context, bufSize))
2256 {
2257 return false;
2258 }
2259
2260 if (!ValidateIndexedStateQuery(context, target, index, length))
2261 {
2262 return false;
2263 }
2264
2265 if (!ValidateRobustBufferSize(context, bufSize, *length))
2266 {
2267 return false;
2268 }
2269
2270 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002271}
2272
Jamie Madillb0817d12016-11-01 15:48:31 -04002273bool ValidateCopyBufferSubData(ValidationContext *context,
2274 GLenum readTarget,
2275 GLenum writeTarget,
2276 GLintptr readOffset,
2277 GLintptr writeOffset,
2278 GLsizeiptr size)
2279{
2280 if (context->getClientMajorVersion() < 3)
2281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002282 context->handleError(InvalidOperation() << "CopyBufferSubData requires ES 3 or greater");
Jamie Madillb0817d12016-11-01 15:48:31 -04002283 return false;
2284 }
2285
2286 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002288 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002289 return false;
2290 }
2291
2292 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2293 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2294
2295 if (!readBuffer || !writeBuffer)
2296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002298 return false;
2299 }
2300
2301 // Verify that readBuffer and writeBuffer are not currently mapped
2302 if (readBuffer->isMapped() || writeBuffer->isMapped())
2303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002304 context->handleError(InvalidOperation()
2305 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002306 return false;
2307 }
2308
Jamie Madilld2f0c742016-11-02 10:34:41 -04002309 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2310 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2311 CheckedNumeric<GLintptr> checkedSize(size);
2312
2313 auto checkedReadSum = checkedReadOffset + checkedSize;
2314 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2315
2316 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2317 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2318 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002320 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002321 return false;
2322 }
2323
Jamie Madilld2f0c742016-11-02 10:34:41 -04002324 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002326 context->handleError(InvalidValue()
2327 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002328 return false;
2329 }
2330
Jamie Madilld2f0c742016-11-02 10:34:41 -04002331 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2332 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002334 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002335 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();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 context->handleError(InvalidValue()
2346 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002347 return false;
2348 }
2349
2350 if (checkedOffsetDiff.ValueOrDie() < size)
2351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002352 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002353 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidOperation()
2365 << "glGetStringi requires OpenGL ES 3.0 or higher.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002366 return false;
2367 }
2368
2369 switch (name)
2370 {
2371 case GL_EXTENSIONS:
2372 if (index >= context->getExtensionStringCount())
2373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002374 context->handleError(InvalidValue()
2375 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002376 return false;
2377 }
2378 break;
2379
2380 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2381 if (!context->getExtensions().requestExtension)
2382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002383 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002384 return false;
2385 }
2386 if (index >= context->getRequestableExtensionStringCount())
2387 {
2388 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002389 InvalidValue()
2390 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002391 return false;
2392 }
2393 break;
2394
2395 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002397 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002412 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002413 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002428 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002429 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(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002437 InvalidOperation()
2438 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002439 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,
Jamie Madill876429b2017-04-20 15:46:24 -04002450 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002451{
2452 if (context->getClientMajorVersion() < 3)
2453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002454 context->handleError(InvalidOperation()
2455 << "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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002466 context->handleError(InvalidValue() << "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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002475 context->handleError(InvalidValue()
2476 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002477 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002485 context->handleError(InvalidValue()
2486 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002487 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context
2499 ->handleError(InvalidOperation()
2500 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002501 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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002524 context->handleError(InvalidOperation() << "GetSynciv requires OpenGL ES 3.0 or higher.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002525 return false;
2526 }
2527
2528 if (bufSize < 0)
2529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002530 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002531 return false;
2532 }
2533
2534 FenceSync *fenceSync = context->getFenceSync(sync);
2535 if (!fenceSync)
2536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002537 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002538 return false;
2539 }
2540
2541 switch (pname)
2542 {
2543 case GL_OBJECT_TYPE:
2544 case GL_SYNC_CONDITION:
2545 case GL_SYNC_FLAGS:
2546 case GL_SYNC_STATUS:
2547 break;
2548
2549 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002550 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002551 return false;
2552 }
2553
2554 return true;
2555}
2556
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002557bool ValidateDrawElementsInstanced(ValidationContext *context,
2558 GLenum mode,
2559 GLsizei count,
2560 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002561 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002562 GLsizei instanceCount)
2563{
2564 if (context->getClientMajorVersion() < 3)
2565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002566 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002567 return false;
2568 }
2569
2570 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2571}
2572
Jamie Madillc29968b2016-01-20 11:17:23 -05002573} // namespace gl