blob: 44012b052bb41a92c802bb50c81b6b890bf9bf4a [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
Geoff Langdbcced82017-06-06 15:55:54 -0400299 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
300 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
301 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400302 {
303 return false;
304 }
305
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400306 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700307 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400308 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400309 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800310 // ...data is not evenly divisible into the number of bytes needed to store in memory a
311 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400312 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400313 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400314 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400315 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400316 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
317
Geoff Langff5b2d52016-09-07 11:32:23 -0400318 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidOperation()
321 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400322 return false;
323 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400324 }
325
Jamie Madill7a5f7382014-03-05 15:01:24 -0500326 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700327 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400330 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500331 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400332 }
333
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400334 return true;
335}
336
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500337bool ValidateES3TexImage2DParameters(Context *context,
338 GLenum target,
339 GLint level,
340 GLenum internalformat,
341 bool isCompressed,
342 bool isSubImage,
343 GLint xoffset,
344 GLint yoffset,
345 GLint zoffset,
346 GLsizei width,
347 GLsizei height,
348 GLsizei depth,
349 GLint border,
350 GLenum format,
351 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400352 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400353 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500354{
355 if (!ValidTexture2DDestinationTarget(context, target))
356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500357 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500358 return false;
359 }
360
361 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
362 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400363 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500364}
365
366bool ValidateES3TexImage3DParameters(Context *context,
367 GLenum target,
368 GLint level,
369 GLenum internalformat,
370 bool isCompressed,
371 bool isSubImage,
372 GLint xoffset,
373 GLint yoffset,
374 GLint zoffset,
375 GLsizei width,
376 GLsizei height,
377 GLsizei depth,
378 GLint border,
379 GLenum format,
380 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400381 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400382 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500383{
384 if (!ValidTexture3DDestinationTarget(context, target))
385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500386 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500387 return false;
388 }
389
390 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
391 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400392 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500393}
394
Geoff Lang5d601382014-07-22 15:14:06 -0400395struct EffectiveInternalFormatInfo
396{
Jamie Madill76648fe2016-10-05 17:01:41 -0400397 GLenum effectiveFormat;
398 GLenum destFormat;
399 GLuint minRedBits;
400 GLuint maxRedBits;
401 GLuint minGreenBits;
402 GLuint maxGreenBits;
403 GLuint minBlueBits;
404 GLuint maxBlueBits;
405 GLuint minAlphaBits;
406 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400407};
408
Jamie Madill76648fe2016-10-05 17:01:41 -0400409static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
410 GLenum targetFormat,
411 const EffectiveInternalFormatInfo *list,
412 size_t size,
413 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400414{
Jamie Madill76648fe2016-10-05 17:01:41 -0400415 for (size_t curFormat = 0; curFormat < size; ++curFormat)
416 {
417 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
418 if ((formatInfo.destFormat == targetFormat) &&
419 (formatInfo.minRedBits <= srcFormat.redBits &&
420 formatInfo.maxRedBits >= srcFormat.redBits) &&
421 (formatInfo.minGreenBits <= srcFormat.greenBits &&
422 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
423 (formatInfo.minBlueBits <= srcFormat.blueBits &&
424 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
425 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
426 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
427 {
428 *outEffectiveFormat = formatInfo.effectiveFormat;
429 return true;
430 }
431 }
Geoff Lang5d601382014-07-22 15:14:06 -0400432
Jamie Madill76648fe2016-10-05 17:01:41 -0400433 *outEffectiveFormat = GL_NONE;
434 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400435}
436
Jamie Madill76648fe2016-10-05 17:01:41 -0400437bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
438 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400439{
Jamie Madill76648fe2016-10-05 17:01:41 -0400440 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
441 // Effective internal format coresponding to destination internal format and linear source
442 // buffer component sizes.
443 // | Source channel min/max sizes |
444 // Effective Internal Format | N/A | R | G | B | A |
445 // clang-format off
446 constexpr EffectiveInternalFormatInfo list[] = {
447 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
448 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
449 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
450 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
451 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
452 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
453 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
454 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
455 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
456 };
457 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400458
Jamie Madill76648fe2016-10-05 17:01:41 -0400459 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
460}
Geoff Lang5d601382014-07-22 15:14:06 -0400461
Jamie Madill76648fe2016-10-05 17:01:41 -0400462bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
463 const InternalFormat &destFormat,
464 GLenum *outEffectiveFormat)
465{
466 constexpr GLuint umax = UINT_MAX;
467
468 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
469 // Effective internal format coresponding to destination internal format andlinear source buffer
470 // component sizes.
471 // | Source channel min/max sizes |
472 // Effective Internal Format | Dest Format | R | G | B | A |
473 // clang-format off
474 constexpr EffectiveInternalFormatInfo list[] = {
475 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
476 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
477 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
478 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
479 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
480 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
481 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
482 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
483 };
484 // clang-format on
485
486 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
487 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400488}
489
He Yunchaoced53ae2016-11-29 15:00:51 +0800490static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
491 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400492 GLenum *outEffectiveFormat)
493{
Geoff Langca271392017-04-05 12:30:00 -0400494 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400495 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400496 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400497 }
498 else
499 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400500 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400501 }
Geoff Lang5d601382014-07-22 15:14:06 -0400502}
503
Corentin Wallez76287682016-04-25 09:23:38 -0400504static bool EqualOrFirstZero(GLuint first, GLuint second)
505{
506 return first == 0 || first == second;
507}
508
Geoff Langca271392017-04-05 12:30:00 -0400509static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
510 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400511 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400512{
Jamie Madill21b786b2016-11-01 17:41:31 -0400513 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400514 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400515 return false;
516 }
Geoff Lang5d601382014-07-22 15:14:06 -0400517
Jamie Madill21b786b2016-11-01 17:41:31 -0400518 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
519 // must both be signed, unsigned, or fixed point and both source and destinations
520 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
521 // conversion between fixed and floating point.
522
523 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
524 (framebufferFormatInfo.colorEncoding == GL_SRGB))
525 {
526 return false;
527 }
528
529 if (((textureFormatInfo.componentType == GL_INT) !=
530 (framebufferFormatInfo.componentType == GL_INT)) ||
531 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
532 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
533 {
534 return false;
535 }
536
537 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
538 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
539 textureFormatInfo.componentType == GL_FLOAT) &&
540 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
541 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
542 framebufferFormatInfo.componentType == GL_FLOAT))
543 {
544 return false;
545 }
546
547 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
548 // The effective internal format of the source buffer is determined with the following rules
549 // applied in order:
550 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
551 // format then the effective internal format is the source buffer's sized internal format.
552 // * If the source buffer is a texture that was created with an unsized base internal format,
553 // then the effective internal format is the source image array's effective internal
554 // format, as specified by table 3.12, which is determined from the <format> and <type>
555 // that were used when the source image array was specified by TexImage*.
556 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
557 // where Destination Internal Format matches internalformat and where the [source channel
558 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
559 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
560 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800561 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400562 if (readBufferHandle != 0)
563 {
564 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
565 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400566 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400567 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400568 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400569 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400570 else
Geoff Lang5d601382014-07-22 15:14:06 -0400571 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400572 // Renderbuffers cannot be created with an unsized internal format, so this must be an
573 // unsized-format texture. We can use the same table we use when creating textures to
574 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400575 sourceEffectiveFormat =
576 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400577 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400578 }
579 else
580 {
581 // The effective internal format must be derived from the source framebuffer's channel
582 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
583 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400584 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400585 GLenum effectiveFormat;
586 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
587 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400588 {
Geoff Langca271392017-04-05 12:30:00 -0400589 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400590 }
591 else
592 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400593 return false;
594 }
595 }
596 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
597 {
598 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400599 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400600 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
601 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
602 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
603 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
604 {
Geoff Langca271392017-04-05 12:30:00 -0400605 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400606 }
607 else
608 {
609 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400610 }
611 }
612 else
613 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400614 UNREACHABLE();
615 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400616 }
Geoff Lang5d601382014-07-22 15:14:06 -0400617 }
618
Geoff Langca271392017-04-05 12:30:00 -0400619 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400620 {
621 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
622 // sized, component sizes of the source and destination formats must exactly match if the
623 // destination format exists.
624 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
625 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
626 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
627 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
628 {
629 return false;
630 }
631 }
632
633 return true; // A conversion function exists, and no rule in the specification has precluded
634 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400635}
636
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500637bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
638 GLenum target,
639 GLint level,
640 GLenum internalformat,
641 bool isSubImage,
642 GLint xoffset,
643 GLint yoffset,
644 GLint zoffset,
645 GLint x,
646 GLint y,
647 GLsizei width,
648 GLsizei height,
649 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400651 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400652 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400653 xoffset, yoffset, zoffset, x, y, width, height, border,
654 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400655 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400656 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400657 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400658 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400659
Jamie Madill51f40ec2016-06-15 14:06:00 -0400660 const auto &state = context->getGLState();
661 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
662 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400663
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400664 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500666 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400667 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400668 }
669
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400670 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500672 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400673 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400674 }
675
Jamie Madill0c8abca2016-07-22 20:21:26 -0400676 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400677
678 if (isSubImage)
679 {
Geoff Langca271392017-04-05 12:30:00 -0400680 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500681 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500683 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400684 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400685 }
686 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400687 else
688 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400689 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400690 const InternalFormat &framebufferFormat = *source->getFormat().info;
691 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400692 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500694 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400695 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400696 }
697 }
698
Geoff Lang784a8fd2013-09-24 12:33:16 -0400699 // If width or height is zero, it is a no-op. Return false without setting an error.
700 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701}
702
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500703bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
704 GLenum target,
705 GLint level,
706 GLenum internalformat,
707 bool isSubImage,
708 GLint xoffset,
709 GLint yoffset,
710 GLint zoffset,
711 GLint x,
712 GLint y,
713 GLsizei width,
714 GLsizei height,
715 GLint border)
716{
717 if (!ValidTexture2DDestinationTarget(context, target))
718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500719 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500720 return false;
721 }
722
723 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
724 xoffset, yoffset, zoffset, x, y, width, height,
725 border);
726}
727
728bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
729 GLenum target,
730 GLint level,
731 GLenum internalformat,
732 bool isSubImage,
733 GLint xoffset,
734 GLint yoffset,
735 GLint zoffset,
736 GLint x,
737 GLint y,
738 GLsizei width,
739 GLsizei height,
740 GLint border)
741{
742 if (!ValidTexture3DDestinationTarget(context, target))
743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500744 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500745 return false;
746 }
747
748 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
749 xoffset, yoffset, zoffset, x, y, width, height,
750 border);
751}
752
753bool ValidateES3TexStorageParametersBase(Context *context,
754 GLenum target,
755 GLsizei levels,
756 GLenum internalformat,
757 GLsizei width,
758 GLsizei height,
759 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760{
761 if (width < 1 || height < 1 || depth < 1 || levels < 1)
762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500763 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400764 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400765 }
766
Geoff Langb92c1332015-09-04 12:54:55 -0400767 GLsizei maxDim = std::max(width, height);
768 if (target != GL_TEXTURE_2D_ARRAY)
769 {
770 maxDim = std::max(maxDim, depth);
771 }
772
773 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500775 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400776 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777 }
778
Geoff Langaae65a42014-05-26 12:43:44 -0400779 const gl::Caps &caps = context->getCaps();
780
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400781 switch (target)
782 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784 {
Geoff Langaae65a42014-05-26 12:43:44 -0400785 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
786 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500788 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 }
791 }
792 break;
793
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 if (width != height)
797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500798 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400799 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400800 }
801
Geoff Langaae65a42014-05-26 12:43:44 -0400802 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500804 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400805 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 }
807 }
808 break;
809
He Yunchaoced53ae2016-11-29 15:00:51 +0800810 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 {
Geoff Langaae65a42014-05-26 12:43:44 -0400812 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
813 static_cast<GLuint>(height) > caps.max3DTextureSize ||
814 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500816 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400817 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 }
819 }
820 break;
821
He Yunchaoced53ae2016-11-29 15:00:51 +0800822 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400823 {
Geoff Langaae65a42014-05-26 12:43:44 -0400824 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
825 static_cast<GLuint>(height) > caps.max2DTextureSize ||
826 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500828 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 }
831 }
832 break;
833
He Yunchaoced53ae2016-11-29 15:00:51 +0800834 default:
835 UNREACHABLE();
836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 }
838
Geoff Lang691e58c2014-12-19 17:03:25 -0500839 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 if (!texture || texture->id() == 0)
841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500842 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
845
Geoff Lang69cce582015-09-17 13:20:36 -0400846 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500848 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851
Geoff Langca271392017-04-05 12:30:00 -0400852 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400853 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500855 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858
Geoff Langca271392017-04-05 12:30:00 -0400859 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500861 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 }
864
865 return true;
866}
867
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500868bool ValidateES3TexStorage2DParameters(Context *context,
869 GLenum target,
870 GLsizei levels,
871 GLenum internalformat,
872 GLsizei width,
873 GLsizei height,
874 GLsizei depth)
875{
876 if (!ValidTexture2DTarget(context, target))
877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500879 return false;
880 }
881
882 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
883 height, depth);
884}
885
886bool ValidateES3TexStorage3DParameters(Context *context,
887 GLenum target,
888 GLsizei levels,
889 GLenum internalformat,
890 GLsizei width,
891 GLsizei height,
892 GLsizei depth)
893{
894 if (!ValidTexture3DTarget(context, target))
895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500897 return false;
898 }
899
900 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
901 height, depth);
902}
903
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500904bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
905{
Martin Radev1be913c2016-07-11 17:59:16 +0300906 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500908 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500909 return false;
910 }
911
912 return ValidateBeginQueryBase(context, target, id);
913}
914
915bool ValidateEndQuery(gl::Context *context, GLenum target)
916{
Martin Radev1be913c2016-07-11 17:59:16 +0300917 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500919 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500920 return false;
921 }
922
923 return ValidateEndQueryBase(context, target);
924}
925
926bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
927{
Martin Radev1be913c2016-07-11 17:59:16 +0300928 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500930 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500931 return false;
932 }
933
Geoff Lang2186c382016-10-14 10:54:54 -0400934 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500935}
936
937bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
938{
Martin Radev1be913c2016-07-11 17:59:16 +0300939 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500942 return false;
943 }
944
Geoff Lang2186c382016-10-14 10:54:54 -0400945 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500946}
947
He Yunchaoced53ae2016-11-29 15:00:51 +0800948bool ValidateFramebufferTextureLayer(Context *context,
949 GLenum target,
950 GLenum attachment,
951 GLuint texture,
952 GLint level,
953 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400954{
Martin Radev1be913c2016-07-11 17:59:16 +0300955 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500957 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400958 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400959 }
960
Jamie Madill55ec3b12014-07-03 10:38:57 -0400961 if (layer < 0)
962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500963 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400964 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400965 }
966
967 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
968 {
969 return false;
970 }
971
972 const gl::Caps &caps = context->getCaps();
973 if (texture != 0)
974 {
975 gl::Texture *tex = context->getTexture(texture);
976 ASSERT(tex);
977
978 switch (tex->getTarget())
979 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400981 {
982 if (level > gl::log2(caps.max2DTextureSize))
983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500984 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400985 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400986 }
987
988 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500990 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400991 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400992 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400993 }
994 break;
995
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400997 {
998 if (level > gl::log2(caps.max3DTextureSize))
999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001001 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001002 }
1003
1004 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001008 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001009 }
1010 break;
1011
He Yunchaoced53ae2016-11-29 15:00:51 +08001012 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001014 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001015 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001016
Jamie Madilla3944d42016-07-22 22:13:26 -04001017 const auto &format = tex->getFormat(tex->getTarget(), level);
1018 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001020 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001021 return false;
1022 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001023 }
1024
1025 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001026}
1027
He Yunchaoced53ae2016-11-29 15:00:51 +08001028bool ValidateInvalidateFramebuffer(Context *context,
1029 GLenum target,
1030 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001031 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032{
Martin Radev1be913c2016-07-11 17:59:16 +03001033 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001035 context->handleError(InvalidOperation() << "Operation only supported on ES 3.0 and above");
Austin Kinross08332632015-05-05 13:35:47 -07001036 return false;
1037 }
1038
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 bool defaultFramebuffer = false;
1040
1041 switch (target)
1042 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001043 case GL_DRAW_FRAMEBUFFER:
1044 case GL_FRAMEBUFFER:
1045 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1046 break;
1047 case GL_READ_FRAMEBUFFER:
1048 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1049 break;
1050 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001051 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001052 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 }
1054
He Yunchaoced53ae2016-11-29 15:00:51 +08001055 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1056 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057}
1058
Jamie Madillc29968b2016-01-20 11:17:23 -05001059bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001060{
Martin Radev1be913c2016-07-11 17:59:16 +03001061 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001063 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001065 }
1066
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001067 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001069 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001070 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001071 }
1072
1073 return true;
1074}
1075
Olli Etuaho71dfb362016-03-10 14:04:27 +02001076bool ValidateDrawRangeElements(Context *context,
1077 GLenum mode,
1078 GLuint start,
1079 GLuint end,
1080 GLsizei count,
1081 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001082 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001083{
Martin Radev1be913c2016-07-11 17:59:16 +03001084 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001086 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001087 return false;
1088 }
1089
1090 if (end < start)
1091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001092 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001093 return false;
1094 }
1095
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001096 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001097 {
1098 return false;
1099 }
1100
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001101 // Use the parameter buffer to retrieve and cache the index range.
1102 const auto &params = context->getParams<HasIndexRange>();
1103 const auto &indexRangeOpt = params.getIndexRange();
1104 if (!indexRangeOpt.valid())
1105 {
1106 // Unexpected error.
1107 return false;
1108 }
1109
1110 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001111 {
1112 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001113 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001114 return false;
1115 }
1116 return true;
1117}
1118
He Yunchaoced53ae2016-11-29 15:00:51 +08001119bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001120{
Martin Radev1be913c2016-07-11 17:59:16 +03001121 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001123 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001125 }
1126
Jamie Madill78f41802014-08-25 15:47:55 -04001127 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001128}
1129
Jamie Madillb885e572015-02-03 16:16:04 -05001130bool ValidateReadBuffer(Context *context, GLenum src)
1131{
Martin Radev1be913c2016-07-11 17:59:16 +03001132 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001135 return false;
1136 }
1137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001138 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001139
1140 if (readFBO == nullptr)
1141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001142 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001143 return false;
1144 }
1145
1146 if (src == GL_NONE)
1147 {
1148 return true;
1149 }
1150
Olli Etuaho84c9f592016-03-09 14:37:25 +02001151 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001153 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001154 return false;
1155 }
1156
1157 if (readFBO->id() == 0)
1158 {
1159 if (src != GL_BACK)
1160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001161 context->handleError(
1162 InvalidOperation()
1163 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001164 return false;
1165 }
1166 }
1167 else
1168 {
1169 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1170
1171 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001173 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001174 return false;
1175 }
1176 }
1177
1178 return true;
1179}
1180
Jamie Madill86af3d22015-07-21 15:14:07 -04001181bool ValidateCompressedTexImage3D(Context *context,
1182 GLenum target,
1183 GLint level,
1184 GLenum internalformat,
1185 GLsizei width,
1186 GLsizei height,
1187 GLsizei depth,
1188 GLint border,
1189 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001190 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001191{
Martin Radev1be913c2016-07-11 17:59:16 +03001192 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001194 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001195 return false;
1196 }
1197
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001198 if (!ValidTextureTarget(context, target))
1199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001200 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001201 return false;
1202 }
1203
Jamie Madille2e406c2016-06-02 13:04:10 -04001204 // Validate image size
1205 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001207 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001208 return false;
1209 }
1210
Geoff Langca271392017-04-05 12:30:00 -04001211 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001212 if (!formatInfo.compressed)
1213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001214 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001215 return false;
1216 }
1217
Jamie Madill513558d2016-06-02 13:04:11 -04001218 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001219 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001220 if (blockSizeOrErr.isError())
1221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001222 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001223 return false;
1224 }
1225 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001227 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001228 return false;
1229 }
1230
1231 // 3D texture target validation
1232 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001235 return false;
1236 }
1237
1238 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001239 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001240 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1241 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001242 {
1243 return false;
1244 }
1245
1246 return true;
1247}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001248
Corentin Wallezb2931602017-04-11 15:58:57 -04001249bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1250 GLenum target,
1251 GLint level,
1252 GLenum internalformat,
1253 GLsizei width,
1254 GLsizei height,
1255 GLsizei depth,
1256 GLint border,
1257 GLsizei imageSize,
1258 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001259 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001260{
1261 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1262 {
1263 return false;
1264 }
1265
1266 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1267 depth, border, imageSize, data);
1268}
1269
Austin Kinrossbc781f32015-10-26 09:27:38 -07001270bool ValidateBindVertexArray(Context *context, GLuint array)
1271{
Martin Radev1be913c2016-07-11 17:59:16 +03001272 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001275 return false;
1276 }
1277
1278 return ValidateBindVertexArrayBase(context, array);
1279}
1280
Austin Kinrossbc781f32015-10-26 09:27:38 -07001281bool ValidateIsVertexArray(Context *context)
1282{
Martin Radev1be913c2016-07-11 17:59:16 +03001283 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001285 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001286 return false;
1287 }
1288
1289 return true;
1290}
Geoff Langc5629752015-12-07 16:29:04 -05001291
Jiajia Qin6eafb042016-12-27 17:04:07 +08001292static bool ValidateBindBufferCommon(Context *context,
1293 GLenum target,
1294 GLuint index,
1295 GLuint buffer,
1296 GLintptr offset,
1297 GLsizeiptr size)
1298{
1299 if (context->getClientMajorVersion() < 3)
1300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001301 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001302 return false;
1303 }
1304
1305 if (buffer != 0 && offset < 0)
1306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001307 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001308 return false;
1309 }
1310
1311 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1312 !context->isBufferGenerated(buffer))
1313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001314 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001315 return false;
1316 }
1317
1318 const Caps &caps = context->getCaps();
1319 switch (target)
1320 {
1321 case GL_TRANSFORM_FEEDBACK_BUFFER:
1322 {
1323 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidValue() << "index is greater than or equal to the "
1326 "number of TRANSFORM_FEEDBACK_BUFFER "
1327 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001328 return false;
1329 }
1330 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001333 return false;
1334 }
1335
1336 TransformFeedback *curTransformFeedback =
1337 context->getGLState().getCurrentTransformFeedback();
1338 if (curTransformFeedback && curTransformFeedback->isActive())
1339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001340 context->handleError(InvalidOperation()
1341 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1342 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001343 return false;
1344 }
1345 break;
1346 }
1347 case GL_UNIFORM_BUFFER:
1348 {
1349 if (index >= caps.maxUniformBufferBindings)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(InvalidValue() << "index is greater than or equal to the "
1352 "number of UNIFORM_BUFFER indexed "
1353 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001354 return false;
1355 }
1356
1357 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1358 {
1359 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001360 InvalidValue()
1361 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001362 return false;
1363 }
1364 break;
1365 }
1366 case GL_ATOMIC_COUNTER_BUFFER:
1367 {
1368 if (context->getClientVersion() < ES_3_1)
1369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidEnum()
1371 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001372 return false;
1373 }
1374 if (index >= caps.maxAtomicCounterBufferBindings)
1375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 context->handleError(InvalidValue() << "index is greater than or equal to the "
1377 "number of ATOMIC_COUNTER_BUFFER "
1378 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001379 return false;
1380 }
1381 if (buffer != 0 && (offset % 4) != 0)
1382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001384 return false;
1385 }
1386 break;
1387 }
1388 case GL_SHADER_STORAGE_BUFFER:
1389 {
1390 if (context->getClientVersion() < ES_3_1)
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidEnum()
1393 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001394 return false;
1395 }
1396 if (index >= caps.maxShaderStorageBufferBindings)
1397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001398 context->handleError(InvalidValue() << "index is greater than or equal to the "
1399 "number of SHADER_STORAGE_BUFFER "
1400 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001401 return false;
1402 }
1403 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidValue() << "offset must be multiple of value of "
1406 "SHADER_STORAGE_BUFFER_OFFSET_"
1407 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001408 return false;
1409 }
1410 break;
1411 }
1412 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001413 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001414 return false;
1415 }
1416
1417 return true;
1418}
1419
1420bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1421{
1422 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1423}
1424
1425bool ValidateBindBufferRange(Context *context,
1426 GLenum target,
1427 GLuint index,
1428 GLuint buffer,
1429 GLintptr offset,
1430 GLsizeiptr size)
1431{
1432 if (buffer != 0 && size <= 0)
1433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidValue()
1435 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001436 return false;
1437 }
1438 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1439}
1440
Geoff Langc5629752015-12-07 16:29:04 -05001441bool ValidateProgramBinary(Context *context,
1442 GLuint program,
1443 GLenum binaryFormat,
1444 const void *binary,
1445 GLint length)
1446{
Martin Radev1be913c2016-07-11 17:59:16 +03001447 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001450 return false;
1451 }
1452
1453 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1454}
1455
1456bool ValidateGetProgramBinary(Context *context,
1457 GLuint program,
1458 GLsizei bufSize,
1459 GLsizei *length,
1460 GLenum *binaryFormat,
1461 void *binary)
1462{
Martin Radev1be913c2016-07-11 17:59:16 +03001463 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001465 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001466 return false;
1467 }
1468
1469 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1470}
1471
Olli Etuahof0fee072016-03-30 15:11:58 +03001472bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001473{
Martin Radev1be913c2016-07-11 17:59:16 +03001474 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001476 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Geoff Langc5629752015-12-07 16:29:04 -05001477 return false;
1478 }
1479
1480 if (GetValidProgram(context, program) == nullptr)
1481 {
1482 return false;
1483 }
1484
1485 switch (pname)
1486 {
1487 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001488 if (value != GL_FALSE && value != GL_TRUE)
1489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001490 context->handleError(InvalidValue()
1491 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001492 return false;
1493 }
Geoff Langc5629752015-12-07 16:29:04 -05001494 break;
1495
Yunchao He61afff12017-03-14 15:34:03 +08001496 case GL_PROGRAM_SEPARABLE:
1497 if (context->getClientVersion() < ES_3_1)
1498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001499 context->handleError(InvalidEnum()
1500 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001501 return false;
1502 }
1503
1504 if (value != GL_FALSE && value != GL_TRUE)
1505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidValue()
1507 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001508 return false;
1509 }
1510 break;
1511
Geoff Langc5629752015-12-07 16:29:04 -05001512 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidEnum()
1514 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001515 return false;
1516 }
1517
1518 return true;
1519}
Jamie Madillc29968b2016-01-20 11:17:23 -05001520
1521bool ValidateBlitFramebuffer(Context *context,
1522 GLint srcX0,
1523 GLint srcY0,
1524 GLint srcX1,
1525 GLint srcY1,
1526 GLint dstX0,
1527 GLint dstY0,
1528 GLint dstX1,
1529 GLint dstY1,
1530 GLbitfield mask,
1531 GLenum filter)
1532{
Martin Radev1be913c2016-07-11 17:59:16 +03001533 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001536 return false;
1537 }
1538
1539 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1540 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001541}
Jamie Madillc29968b2016-01-20 11:17:23 -05001542
1543bool ValidateClearBufferiv(ValidationContext *context,
1544 GLenum buffer,
1545 GLint drawbuffer,
1546 const GLint *value)
1547{
1548 switch (buffer)
1549 {
1550 case GL_COLOR:
1551 if (drawbuffer < 0 ||
1552 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001554 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001555 return false;
1556 }
Geoff Lang76e65652017-03-27 14:58:02 -04001557 if (context->getExtensions().webglCompatibility)
1558 {
1559 constexpr GLenum validComponentTypes[] = {GL_INT};
1560 if (ValidateWebGLFramebufferAttachmentClearType(
1561 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1562 {
1563 return false;
1564 }
1565 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001566 break;
1567
1568 case GL_STENCIL:
1569 if (drawbuffer != 0)
1570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001571 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001572 return false;
1573 }
1574 break;
1575
1576 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001577 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001578 return false;
1579 }
1580
1581 return ValidateClearBuffer(context);
1582}
1583
1584bool ValidateClearBufferuiv(ValidationContext *context,
1585 GLenum buffer,
1586 GLint drawbuffer,
1587 const GLuint *value)
1588{
1589 switch (buffer)
1590 {
1591 case GL_COLOR:
1592 if (drawbuffer < 0 ||
1593 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001595 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001596 return false;
1597 }
Geoff Lang76e65652017-03-27 14:58:02 -04001598 if (context->getExtensions().webglCompatibility)
1599 {
1600 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1601 if (ValidateWebGLFramebufferAttachmentClearType(
1602 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1603 {
1604 return false;
1605 }
1606 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001607 break;
1608
1609 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 return false;
1612 }
1613
1614 return ValidateClearBuffer(context);
1615}
1616
1617bool ValidateClearBufferfv(ValidationContext *context,
1618 GLenum buffer,
1619 GLint drawbuffer,
1620 const GLfloat *value)
1621{
1622 switch (buffer)
1623 {
1624 case GL_COLOR:
1625 if (drawbuffer < 0 ||
1626 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001628 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001629 return false;
1630 }
Geoff Lang76e65652017-03-27 14:58:02 -04001631 if (context->getExtensions().webglCompatibility)
1632 {
1633 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1634 GL_SIGNED_NORMALIZED};
1635 if (ValidateWebGLFramebufferAttachmentClearType(
1636 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1637 {
1638 return false;
1639 }
1640 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001641 break;
1642
1643 case GL_DEPTH:
1644 if (drawbuffer != 0)
1645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001647 return false;
1648 }
1649 break;
1650
1651 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001652 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001653 return false;
1654 }
1655
1656 return ValidateClearBuffer(context);
1657}
1658
1659bool ValidateClearBufferfi(ValidationContext *context,
1660 GLenum buffer,
1661 GLint drawbuffer,
1662 GLfloat depth,
1663 GLint stencil)
1664{
1665 switch (buffer)
1666 {
1667 case GL_DEPTH_STENCIL:
1668 if (drawbuffer != 0)
1669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001671 return false;
1672 }
1673 break;
1674
1675 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001677 return false;
1678 }
1679
1680 return ValidateClearBuffer(context);
1681}
1682
1683bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1684{
Martin Radev1be913c2016-07-11 17:59:16 +03001685 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001687 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Jamie Madillc29968b2016-01-20 11:17:23 -05001688 return false;
1689 }
1690
1691 return ValidateDrawBuffersBase(context, n, bufs);
1692}
1693
1694bool ValidateCopyTexSubImage3D(Context *context,
1695 GLenum target,
1696 GLint level,
1697 GLint xoffset,
1698 GLint yoffset,
1699 GLint zoffset,
1700 GLint x,
1701 GLint y,
1702 GLsizei width,
1703 GLsizei height)
1704{
Martin Radev1be913c2016-07-11 17:59:16 +03001705 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001707 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001708 return false;
1709 }
1710
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001711 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1712 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001713}
1714
Jamie Madill73a84962016-02-12 09:27:23 -05001715bool ValidateTexImage3D(Context *context,
1716 GLenum target,
1717 GLint level,
1718 GLint internalformat,
1719 GLsizei width,
1720 GLsizei height,
1721 GLsizei depth,
1722 GLint border,
1723 GLenum format,
1724 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001725 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001726{
Martin Radev1be913c2016-07-11 17:59:16 +03001727 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001730 return false;
1731 }
1732
1733 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001734 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001735 pixels);
1736}
1737
Geoff Langc52f6f12016-10-14 10:18:00 -04001738bool ValidateTexImage3DRobustANGLE(Context *context,
1739 GLenum target,
1740 GLint level,
1741 GLint internalformat,
1742 GLsizei width,
1743 GLsizei height,
1744 GLsizei depth,
1745 GLint border,
1746 GLenum format,
1747 GLenum type,
1748 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001749 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001750{
1751 if (context->getClientMajorVersion() < 3)
1752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001753 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001754 return false;
1755 }
1756
1757 if (!ValidateRobustEntryPoint(context, bufSize))
1758 {
1759 return false;
1760 }
1761
1762 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1763 0, 0, width, height, depth, border, format, type,
1764 bufSize, pixels);
1765}
1766
Jamie Madill73a84962016-02-12 09:27:23 -05001767bool ValidateTexSubImage3D(Context *context,
1768 GLenum target,
1769 GLint level,
1770 GLint xoffset,
1771 GLint yoffset,
1772 GLint zoffset,
1773 GLsizei width,
1774 GLsizei height,
1775 GLsizei depth,
1776 GLenum format,
1777 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001778 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001779{
Martin Radev1be913c2016-07-11 17:59:16 +03001780 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001782 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001783 return false;
1784 }
1785
1786 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1787 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001788 -1, pixels);
1789}
1790
1791bool ValidateTexSubImage3DRobustANGLE(Context *context,
1792 GLenum target,
1793 GLint level,
1794 GLint xoffset,
1795 GLint yoffset,
1796 GLint zoffset,
1797 GLsizei width,
1798 GLsizei height,
1799 GLsizei depth,
1800 GLenum format,
1801 GLenum type,
1802 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001803 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001804{
1805 if (context->getClientMajorVersion() < 3)
1806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001807 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001808 return false;
1809 }
1810
1811 if (!ValidateRobustEntryPoint(context, bufSize))
1812 {
1813 return false;
1814 }
1815
1816 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1817 yoffset, zoffset, width, height, depth, 0, format, type,
1818 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001819}
1820
1821bool ValidateCompressedTexSubImage3D(Context *context,
1822 GLenum target,
1823 GLint level,
1824 GLint xoffset,
1825 GLint yoffset,
1826 GLint zoffset,
1827 GLsizei width,
1828 GLsizei height,
1829 GLsizei depth,
1830 GLenum format,
1831 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001832 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001833{
Martin Radev1be913c2016-07-11 17:59:16 +03001834 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001836 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001837 return false;
1838 }
1839
Geoff Langca271392017-04-05 12:30:00 -04001840 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001841 if (!formatInfo.compressed)
1842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001843 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001844 return false;
1845 }
1846
Jamie Madill513558d2016-06-02 13:04:11 -04001847 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001848 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001849 if (blockSizeOrErr.isError())
1850 {
1851 context->handleError(blockSizeOrErr.getError());
1852 return false;
1853 }
1854 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001856 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001857 return false;
1858 }
1859
1860 if (!data)
1861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001862 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001863 return false;
1864 }
1865
1866 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001867 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001868}
Corentin Wallezb2931602017-04-11 15:58:57 -04001869bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1870 GLenum target,
1871 GLint level,
1872 GLint xoffset,
1873 GLint yoffset,
1874 GLint zoffset,
1875 GLsizei width,
1876 GLsizei height,
1877 GLsizei depth,
1878 GLenum format,
1879 GLsizei imageSize,
1880 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001881 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001882{
1883 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1884 {
1885 return false;
1886 }
1887
1888 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1889 height, depth, format, imageSize, data);
1890}
Jamie Madill73a84962016-02-12 09:27:23 -05001891
Olli Etuaho41997e72016-03-10 13:38:39 +02001892bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1893{
1894 return ValidateGenOrDeleteES3(context, n);
1895}
1896
1897bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1898{
1899 return ValidateGenOrDeleteES3(context, n);
1900}
1901
1902bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1903{
1904 return ValidateGenOrDeleteCountES3(context, count);
1905}
1906
1907bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1908{
1909 return ValidateGenOrDeleteCountES3(context, count);
1910}
1911
1912bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1913{
1914 return ValidateGenOrDeleteES3(context, n);
1915}
1916
1917bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1918{
1919 if (!ValidateGenOrDeleteES3(context, n))
1920 {
1921 return false;
1922 }
1923 for (GLint i = 0; i < n; ++i)
1924 {
1925 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1926 if (transformFeedback != nullptr && transformFeedback->isActive())
1927 {
1928 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001929 context->handleError(InvalidOperation()
1930 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001931 return false;
1932 }
1933 }
1934 return true;
1935}
1936
1937bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1938{
1939 return ValidateGenOrDeleteES3(context, n);
1940}
1941
1942bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1943{
1944 return ValidateGenOrDeleteES3(context, n);
1945}
1946
1947bool ValidateGenOrDeleteES3(Context *context, GLint n)
1948{
Martin Radev1be913c2016-07-11 17:59:16 +03001949 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001951 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001952 return false;
1953 }
1954 return ValidateGenOrDelete(context, n);
1955}
1956
1957bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1958{
Martin Radev1be913c2016-07-11 17:59:16 +03001959 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001961 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02001962 return false;
1963 }
1964 if (count < 0)
1965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001966 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02001967 return false;
1968 }
1969 return true;
1970}
1971
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001972bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1973{
Martin Radev1be913c2016-07-11 17:59:16 +03001974 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001976 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001977 return false;
1978 }
1979 switch (primitiveMode)
1980 {
1981 case GL_TRIANGLES:
1982 case GL_LINES:
1983 case GL_POINTS:
1984 break;
1985
1986 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001987 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001988 return false;
1989 }
1990
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001991 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001992 ASSERT(transformFeedback != nullptr);
1993
1994 if (transformFeedback->isActive())
1995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001996 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001997 return false;
1998 }
1999 return true;
2000}
2001
Jamie Madill876429b2017-04-20 15:46:24 -04002002bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002003{
Geoff Lang496c02d2016-10-20 11:38:11 -07002004 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2005}
2006
2007bool ValidateGetBufferPointervRobustANGLE(Context *context,
2008 GLenum target,
2009 GLenum pname,
2010 GLsizei bufSize,
2011 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002012 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002013{
2014 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002015 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002016 return false;
2017 }
2018
Geoff Lang496c02d2016-10-20 11:38:11 -07002019 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2020 {
2021 return false;
2022 }
2023
2024 if (!ValidateRobustBufferSize(context, bufSize, *length))
2025 {
2026 return false;
2027 }
2028
2029 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002030}
2031
2032bool ValidateUnmapBuffer(Context *context, GLenum target)
2033{
Martin Radev1be913c2016-07-11 17:59:16 +03002034 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002036 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002037 return false;
2038 }
2039
2040 return ValidateUnmapBufferBase(context, target);
2041}
2042
2043bool ValidateMapBufferRange(Context *context,
2044 GLenum target,
2045 GLintptr offset,
2046 GLsizeiptr length,
2047 GLbitfield access)
2048{
Martin Radev1be913c2016-07-11 17:59:16 +03002049 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002051 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002052 return false;
2053 }
2054
2055 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2056}
2057
2058bool ValidateFlushMappedBufferRange(Context *context,
2059 GLenum target,
2060 GLintptr offset,
2061 GLsizeiptr length)
2062{
Martin Radev1be913c2016-07-11 17:59:16 +03002063 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002065 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002066 return false;
2067 }
2068
2069 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2070}
2071
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002072bool ValidateIndexedStateQuery(ValidationContext *context,
2073 GLenum pname,
2074 GLuint index,
2075 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002076{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002077 if (length)
2078 {
2079 *length = 0;
2080 }
2081
Martin Radev66fb8202016-07-28 11:45:20 +03002082 GLenum nativeType;
2083 unsigned int numParams;
2084 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002086 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002087 return false;
2088 }
2089
2090 const Caps &caps = context->getCaps();
2091 switch (pname)
2092 {
2093 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2094 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2095 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2096 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002098 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002099 return false;
2100 }
2101 break;
2102
2103 case GL_UNIFORM_BUFFER_START:
2104 case GL_UNIFORM_BUFFER_SIZE:
2105 case GL_UNIFORM_BUFFER_BINDING:
2106 if (index >= caps.maxUniformBufferBindings)
2107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002108 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002109 return false;
2110 }
2111 break;
Shao80957d92017-02-20 21:25:59 +08002112
Martin Radev66fb8202016-07-28 11:45:20 +03002113 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2114 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2115 if (index >= 3u)
2116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002117 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002118 return false;
2119 }
2120 break;
Shao80957d92017-02-20 21:25:59 +08002121
Jiajia Qin6eafb042016-12-27 17:04:07 +08002122 case GL_ATOMIC_COUNTER_BUFFER_START:
2123 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2124 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2125 if (context->getClientVersion() < ES_3_1)
2126 {
2127 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002128 InvalidEnum()
2129 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002130 return false;
2131 }
2132 if (index >= caps.maxAtomicCounterBufferBindings)
2133 {
2134 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002135 InvalidValue()
2136 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002137 return false;
2138 }
2139 break;
Shao80957d92017-02-20 21:25:59 +08002140
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002141 case GL_SHADER_STORAGE_BUFFER_START:
2142 case GL_SHADER_STORAGE_BUFFER_SIZE:
2143 case GL_SHADER_STORAGE_BUFFER_BINDING:
2144 if (context->getClientVersion() < ES_3_1)
2145 {
2146 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002147 InvalidEnum()
2148 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002149 return false;
2150 }
2151 if (index >= caps.maxShaderStorageBufferBindings)
2152 {
2153 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002154 InvalidValue()
2155 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002156 return false;
2157 }
2158 break;
2159
Shao80957d92017-02-20 21:25:59 +08002160 case GL_VERTEX_BINDING_BUFFER:
2161 case GL_VERTEX_BINDING_DIVISOR:
2162 case GL_VERTEX_BINDING_OFFSET:
2163 case GL_VERTEX_BINDING_STRIDE:
2164 if (context->getClientVersion() < ES_3_1)
2165 {
2166 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002167 InvalidEnum()
2168 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002169 return false;
2170 }
2171 if (index >= caps.maxVertexAttribBindings)
2172 {
2173 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 InvalidValue()
2175 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002176 return false;
2177 }
2178 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002179 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002180 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002181 return false;
2182 }
2183
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002184 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002185 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002186 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002187 }
2188
2189 return true;
2190}
2191
2192bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2193{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002194 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002197 return false;
2198 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002199 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002200}
2201
Geoff Langcf255ea2016-10-20 11:39:09 -07002202bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2203 GLenum target,
2204 GLuint index,
2205 GLsizei bufSize,
2206 GLsizei *length,
2207 GLint *data)
2208{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002209 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002211 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Langcf255ea2016-10-20 11:39:09 -07002212 return false;
2213 }
2214
2215 if (!ValidateRobustEntryPoint(context, bufSize))
2216 {
2217 return false;
2218 }
2219
2220 if (!ValidateIndexedStateQuery(context, target, index, length))
2221 {
2222 return false;
2223 }
2224
2225 if (!ValidateRobustBufferSize(context, bufSize, *length))
2226 {
2227 return false;
2228 }
2229
2230 return true;
2231}
2232
Martin Radev66fb8202016-07-28 11:45:20 +03002233bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2234{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002235 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002237 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002238 return false;
2239 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002240 return ValidateIndexedStateQuery(context, target, index, nullptr);
2241}
2242
2243bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2244 GLenum target,
2245 GLuint index,
2246 GLsizei bufSize,
2247 GLsizei *length,
2248 GLint64 *data)
2249{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002250 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002252 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002253 return false;
2254 }
2255
2256 if (!ValidateRobustEntryPoint(context, bufSize))
2257 {
2258 return false;
2259 }
2260
2261 if (!ValidateIndexedStateQuery(context, target, index, length))
2262 {
2263 return false;
2264 }
2265
2266 if (!ValidateRobustBufferSize(context, bufSize, *length))
2267 {
2268 return false;
2269 }
2270
2271 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002272}
2273
Jamie Madillb0817d12016-11-01 15:48:31 -04002274bool ValidateCopyBufferSubData(ValidationContext *context,
2275 GLenum readTarget,
2276 GLenum writeTarget,
2277 GLintptr readOffset,
2278 GLintptr writeOffset,
2279 GLsizeiptr size)
2280{
2281 if (context->getClientMajorVersion() < 3)
2282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002283 context->handleError(InvalidOperation() << "CopyBufferSubData requires ES 3 or greater");
Jamie Madillb0817d12016-11-01 15:48:31 -04002284 return false;
2285 }
2286
2287 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002289 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002290 return false;
2291 }
2292
2293 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2294 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2295
2296 if (!readBuffer || !writeBuffer)
2297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002298 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002299 return false;
2300 }
2301
2302 // Verify that readBuffer and writeBuffer are not currently mapped
2303 if (readBuffer->isMapped() || writeBuffer->isMapped())
2304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002305 context->handleError(InvalidOperation()
2306 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002307 return false;
2308 }
2309
Jamie Madilld2f0c742016-11-02 10:34:41 -04002310 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2311 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2312 CheckedNumeric<GLintptr> checkedSize(size);
2313
2314 auto checkedReadSum = checkedReadOffset + checkedSize;
2315 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2316
2317 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2318 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2319 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002321 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002322 return false;
2323 }
2324
Jamie Madilld2f0c742016-11-02 10:34:41 -04002325 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002327 context->handleError(InvalidValue()
2328 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002329 return false;
2330 }
2331
Jamie Madilld2f0c742016-11-02 10:34:41 -04002332 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2333 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002335 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002336 return false;
2337 }
2338
2339 if (readBuffer == writeBuffer)
2340 {
2341 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2342 if (!checkedOffsetDiff.IsValid())
2343 {
2344 // This shold not be possible.
2345 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002346 context->handleError(InvalidValue()
2347 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002348 return false;
2349 }
2350
2351 if (checkedOffsetDiff.ValueOrDie() < size)
2352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002353 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002354 return false;
2355 }
2356 }
2357
Jamie Madillb0817d12016-11-01 15:48:31 -04002358 return true;
2359}
2360
Geoff Langc339c4e2016-11-29 10:37:36 -05002361bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2362{
2363 if (context->getClientMajorVersion() < 3)
2364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 context->handleError(InvalidOperation()
2366 << "glGetStringi requires OpenGL ES 3.0 or higher.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002367 return false;
2368 }
2369
2370 switch (name)
2371 {
2372 case GL_EXTENSIONS:
2373 if (index >= context->getExtensionStringCount())
2374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002375 context->handleError(InvalidValue()
2376 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002377 return false;
2378 }
2379 break;
2380
2381 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2382 if (!context->getExtensions().requestExtension)
2383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002384 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002385 return false;
2386 }
2387 if (index >= context->getRequestableExtensionStringCount())
2388 {
2389 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002390 InvalidValue()
2391 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002392 return false;
2393 }
2394 break;
2395
2396 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002397 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002398 return false;
2399 }
2400
2401 return true;
2402}
2403
Jamie Madille8fb6402017-02-14 17:56:40 -05002404bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2405 GLenum target,
2406 GLsizei samples,
2407 GLenum internalformat,
2408 GLsizei width,
2409 GLsizei height)
2410{
2411 if (context->getClientMajorVersion() < 3)
2412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002413 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002414 return false;
2415 }
2416
2417 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2418 height))
2419 {
2420 return false;
2421 }
2422
2423 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2424 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002425 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002426 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2427 samples > 0)
2428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002429 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002430 return false;
2431 }
2432
2433 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2434 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2435 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2436 {
2437 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002438 InvalidOperation()
2439 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002440 return false;
2441 }
2442
2443 return true;
2444}
2445
Geoff Langaa086d62017-03-23 16:47:21 -04002446bool ValidateVertexAttribIPointer(ValidationContext *context,
2447 GLuint index,
2448 GLint size,
2449 GLenum type,
2450 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002451 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002452{
2453 if (context->getClientMajorVersion() < 3)
2454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002455 context->handleError(InvalidOperation()
2456 << "VertexAttribIPointer requires OpenGL ES 3.0 or higher.");
Geoff Langaa086d62017-03-23 16:47:21 -04002457 return false;
2458 }
2459
Shao80957d92017-02-20 21:25:59 +08002460 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002461 {
Geoff Langaa086d62017-03-23 16:47:21 -04002462 return false;
2463 }
2464
Geoff Langaa086d62017-03-23 16:47:21 -04002465 if (stride < 0)
2466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002467 context->handleError(InvalidValue() << "stride cannot be negative.");
Geoff Langaa086d62017-03-23 16:47:21 -04002468 return false;
2469 }
2470
Shao80957d92017-02-20 21:25:59 +08002471 const Caps &caps = context->getCaps();
2472 if (context->getClientVersion() >= ES_3_1)
2473 {
2474 if (stride > caps.maxVertexAttribStride)
2475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002476 context->handleError(InvalidValue()
2477 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002478 return false;
2479 }
2480
2481 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2482 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2483 // validation should be inherited.
2484 if (index >= caps.maxVertexAttribBindings)
2485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002486 context->handleError(InvalidValue()
2487 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002488 return false;
2489 }
2490 }
2491
Geoff Langaa086d62017-03-23 16:47:21 -04002492 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2493 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2494 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2495 // and the pointer argument is not NULL.
2496 if (context->getGLState().getVertexArrayId() != 0 &&
2497 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002499 context
2500 ->handleError(InvalidOperation()
2501 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002502 return false;
2503 }
2504
Geoff Lang2d62ab72017-03-23 16:54:40 -04002505 if (context->getExtensions().webglCompatibility)
2506 {
2507 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2508 {
2509 return false;
2510 }
2511 }
2512
Geoff Langaa086d62017-03-23 16:47:21 -04002513 return true;
2514}
2515
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002516bool ValidateGetSynciv(Context *context,
2517 GLsync sync,
2518 GLenum pname,
2519 GLsizei bufSize,
2520 GLsizei *length,
2521 GLint *values)
2522{
2523 if (context->getClientMajorVersion() < 3)
2524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002525 context->handleError(InvalidOperation() << "GetSynciv requires OpenGL ES 3.0 or higher.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002526 return false;
2527 }
2528
2529 if (bufSize < 0)
2530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002531 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002532 return false;
2533 }
2534
2535 FenceSync *fenceSync = context->getFenceSync(sync);
2536 if (!fenceSync)
2537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002538 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002539 return false;
2540 }
2541
2542 switch (pname)
2543 {
2544 case GL_OBJECT_TYPE:
2545 case GL_SYNC_CONDITION:
2546 case GL_SYNC_FLAGS:
2547 case GL_SYNC_STATUS:
2548 break;
2549
2550 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002551 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002552 return false;
2553 }
2554
2555 return true;
2556}
2557
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002558bool ValidateDrawElementsInstanced(ValidationContext *context,
2559 GLenum mode,
2560 GLsizei count,
2561 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002562 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002563 GLsizei instanceCount)
2564{
2565 if (context->getClientMajorVersion() < 3)
2566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002567 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002568 return false;
2569 }
2570
2571 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2572}
2573
Jamie Madillc29968b2016-01-20 11:17:23 -05002574} // namespace gl