blob: e7c95ff05355ece3c737686691b559e4f4d7fe94 [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"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
21#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025namespace gl
26{
27
Martin Radev137032d2017-07-13 10:11:12 +030028namespace
29{
30bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36{
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
48 if (numViews < 1)
49 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63}
64
65bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68{
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83}
84
85} // namespace
86
He Yunchaoced53ae2016-11-29 15:00:51 +080087static bool ValidateTexImageFormatCombination(gl::Context *context,
Geoff Langca271392017-04-05 12:30:00 -040088 GLenum target,
He Yunchaoced53ae2016-11-29 15:00:51 +080089 GLenum internalFormat,
90 GLenum format,
91 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040092{
Geoff Lang5d601382014-07-22 15:14:06 -040093
94 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -040095 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -040096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050097 context->handleError(InvalidEnum() << "Invalid format.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -040098 return false;
99 }
100
101 if (!ValidES3Type(type))
102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500103 context->handleError(InvalidEnum() << "Invalid type.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400104 return false;
105 }
106
107 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
108 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
109 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
110 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
111 if (!ValidES3InternalFormat(internalFormat))
112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500113 context->handleError(InvalidValue() << "Invalid internalFormat.");
Geoff Langb1196682014-07-23 13:47:29 -0400114 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400115 }
116
Geoff Langca271392017-04-05 12:30:00 -0400117 // From the ES 3.0 spec section 3.8.3:
118 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
119 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
120 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
121 // INVALID_OPERATION error.
122 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500124 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
125 "GL_DEPTH_STENCIL if target is "
126 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400127 return false;
128 }
129
Geoff Lang5d601382014-07-22 15:14:06 -0400130 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400131 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500133 context->handleError(InvalidOperation()
134 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400135 return false;
136 }
137
138 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
139 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500141 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400142 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400143 }
144
145 return true;
146}
147
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500148bool ValidateES3TexImageParametersBase(Context *context,
149 GLenum target,
150 GLint level,
151 GLenum internalformat,
152 bool isCompressed,
153 bool isSubImage,
154 GLint xoffset,
155 GLint yoffset,
156 GLint zoffset,
157 GLsizei width,
158 GLsizei height,
159 GLsizei depth,
160 GLint border,
161 GLenum format,
162 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400163 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400164 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400165{
166 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -0700167 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500169 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400171 }
172
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400173 // Verify zero border
174 if (border != 0)
175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500176 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400177 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400178 }
179
Jamie Madill6f38f822014-06-06 17:12:20 -0400180 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
181 std::numeric_limits<GLsizei>::max() - xoffset < width ||
182 std::numeric_limits<GLsizei>::max() - yoffset < height ||
183 std::numeric_limits<GLsizei>::max() - zoffset < depth)
184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500185 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400186 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400187 }
188
Geoff Langaae65a42014-05-26 12:43:44 -0400189 const gl::Caps &caps = context->getCaps();
190
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400191 switch (target)
192 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800193 case GL_TEXTURE_2D:
194 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
195 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500197 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800198 return false;
199 }
200 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400201
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400202 case GL_TEXTURE_RECTANGLE_ANGLE:
203 ASSERT(level == 0);
204 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
205 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
206 {
207 context->handleError(InvalidValue());
208 return false;
209 }
210 if (isCompressed)
211 {
212 context->handleError(InvalidEnum()
213 << "Rectangle texture cannot have a compressed format.");
214 return false;
215 }
216 break;
217
He Yunchaoced53ae2016-11-29 15:00:51 +0800218 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
219 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
220 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
221 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
222 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
223 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
224 if (!isSubImage && width != height)
225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500226 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800227 return false;
228 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400229
He Yunchaoced53ae2016-11-29 15:00:51 +0800230 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500232 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800233 return false;
234 }
235 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400236
He Yunchaoced53ae2016-11-29 15:00:51 +0800237 case GL_TEXTURE_3D:
238 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
239 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
240 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500242 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800243 return false;
244 }
245 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246
He Yunchaoced53ae2016-11-29 15:00:51 +0800247 case GL_TEXTURE_2D_ARRAY:
248 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
249 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
250 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500252 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800253 return false;
254 }
255 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400256
He Yunchaoced53ae2016-11-29 15:00:51 +0800257 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500258 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400260 }
261
He Yunchaoced53ae2016-11-29 15:00:51 +0800262 gl::Texture *texture =
263 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400264 if (!texture)
265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500266 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400268 }
269
Geoff Lang69cce582015-09-17 13:20:36 -0400270 if (texture->getImmutableFormat() && !isSubImage)
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
276 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400277 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400278 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500279 if (isSubImage && actualInternalFormat == GL_NONE)
280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500281 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500282 return false;
283 }
284
Geoff Langc4e93662017-05-01 10:45:59 -0400285 const gl::InternalFormat &actualFormatInfo = isSubImage
286 ? *texture->getFormat(target, level).info
287 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400288 if (isCompressed)
289 {
tmartino7c102692015-10-02 16:43:40 -0400290 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500292 context->handleError(
293 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400294 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400295 }
296
Geoff Lang966c9402017-04-18 12:38:27 -0400297 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400298 {
Geoff Lang966c9402017-04-18 12:38:27 -0400299 if (!ValidCompressedSubImageSize(
300 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
301 texture->getWidth(target, level), texture->getHeight(target, level)))
302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500303 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400304 return false;
305 }
306
307 if (format != actualInternalFormat)
308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500309 context->handleError(InvalidOperation()
310 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400311 return false;
312 }
313 }
314 else
315 {
316 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500318 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400319 return false;
320 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321 }
322
Geoff Langeb66a6e2016-10-31 13:06:12 -0400323 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500325 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400326 return false;
327 }
328
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400329 if (target == GL_TEXTURE_3D)
330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500331 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400332 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 }
334 }
335 else
336 {
Geoff Langca271392017-04-05 12:30:00 -0400337 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400338 {
Geoff Lang5d601382014-07-22 15:14:06 -0400339 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400341 }
342
343 // Validate sub image parameters
344 if (isSubImage)
345 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500346 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500348 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400349 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400350 }
351
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400352 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500354 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400355 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 }
357
358 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
359 std::numeric_limits<GLsizei>::max() - yoffset < height ||
360 std::numeric_limits<GLsizei>::max() - zoffset < depth)
361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500362 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 }
365
Geoff Langa9be0dc2014-12-17 12:34:40 -0500366 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
367 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
368 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500370 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400372 }
373 }
374
Geoff Langdbcced82017-06-06 15:55:54 -0400375 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
376 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
377 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400378 {
379 return false;
380 }
381
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400382 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700383 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400384 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400385 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800386 // ...data is not evenly divisible into the number of bytes needed to store in memory a
387 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400388 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400389 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400390 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400391 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400392 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
393
Geoff Langff5b2d52016-09-07 11:32:23 -0400394 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500396 context->handleError(InvalidOperation()
397 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400398 return false;
399 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400400 }
401
Jamie Madill7a5f7382014-03-05 15:01:24 -0500402 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700403 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500405 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400406 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500407 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 return true;
411}
412
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500413bool ValidateES3TexImage2DParameters(Context *context,
414 GLenum target,
415 GLint level,
416 GLenum internalformat,
417 bool isCompressed,
418 bool isSubImage,
419 GLint xoffset,
420 GLint yoffset,
421 GLint zoffset,
422 GLsizei width,
423 GLsizei height,
424 GLsizei depth,
425 GLint border,
426 GLenum format,
427 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400428 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400429 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500430{
431 if (!ValidTexture2DDestinationTarget(context, target))
432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500433 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500434 return false;
435 }
436
437 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
438 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400439 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500440}
441
442bool ValidateES3TexImage3DParameters(Context *context,
443 GLenum target,
444 GLint level,
445 GLenum internalformat,
446 bool isCompressed,
447 bool isSubImage,
448 GLint xoffset,
449 GLint yoffset,
450 GLint zoffset,
451 GLsizei width,
452 GLsizei height,
453 GLsizei depth,
454 GLint border,
455 GLenum format,
456 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400457 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400458 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500459{
460 if (!ValidTexture3DDestinationTarget(context, target))
461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500462 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500463 return false;
464 }
465
466 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
467 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400468 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500469}
470
Geoff Lang5d601382014-07-22 15:14:06 -0400471struct EffectiveInternalFormatInfo
472{
Jamie Madill76648fe2016-10-05 17:01:41 -0400473 GLenum effectiveFormat;
474 GLenum destFormat;
475 GLuint minRedBits;
476 GLuint maxRedBits;
477 GLuint minGreenBits;
478 GLuint maxGreenBits;
479 GLuint minBlueBits;
480 GLuint maxBlueBits;
481 GLuint minAlphaBits;
482 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400483};
484
Jamie Madill76648fe2016-10-05 17:01:41 -0400485static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
486 GLenum targetFormat,
487 const EffectiveInternalFormatInfo *list,
488 size_t size,
489 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400490{
Jamie Madill76648fe2016-10-05 17:01:41 -0400491 for (size_t curFormat = 0; curFormat < size; ++curFormat)
492 {
493 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
494 if ((formatInfo.destFormat == targetFormat) &&
495 (formatInfo.minRedBits <= srcFormat.redBits &&
496 formatInfo.maxRedBits >= srcFormat.redBits) &&
497 (formatInfo.minGreenBits <= srcFormat.greenBits &&
498 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
499 (formatInfo.minBlueBits <= srcFormat.blueBits &&
500 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
501 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
502 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
503 {
504 *outEffectiveFormat = formatInfo.effectiveFormat;
505 return true;
506 }
507 }
Geoff Lang5d601382014-07-22 15:14:06 -0400508
Jamie Madill76648fe2016-10-05 17:01:41 -0400509 *outEffectiveFormat = GL_NONE;
510 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400511}
512
Jamie Madill76648fe2016-10-05 17:01:41 -0400513bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
514 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400515{
Jamie Madill76648fe2016-10-05 17:01:41 -0400516 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
517 // Effective internal format coresponding to destination internal format and linear source
518 // buffer component sizes.
519 // | Source channel min/max sizes |
520 // Effective Internal Format | N/A | R | G | B | A |
521 // clang-format off
522 constexpr EffectiveInternalFormatInfo list[] = {
523 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
524 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
525 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
526 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
527 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
528 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
529 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
530 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
531 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
532 };
533 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400534
Jamie Madill76648fe2016-10-05 17:01:41 -0400535 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
536}
Geoff Lang5d601382014-07-22 15:14:06 -0400537
Jamie Madill76648fe2016-10-05 17:01:41 -0400538bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
539 const InternalFormat &destFormat,
540 GLenum *outEffectiveFormat)
541{
542 constexpr GLuint umax = UINT_MAX;
543
544 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
545 // Effective internal format coresponding to destination internal format andlinear source buffer
546 // component sizes.
547 // | Source channel min/max sizes |
548 // Effective Internal Format | Dest Format | R | G | B | A |
549 // clang-format off
550 constexpr EffectiveInternalFormatInfo list[] = {
551 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
552 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
553 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
554 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
555 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
556 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
557 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
558 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
559 };
560 // clang-format on
561
562 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
563 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400564}
565
He Yunchaoced53ae2016-11-29 15:00:51 +0800566static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
567 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400568 GLenum *outEffectiveFormat)
569{
Geoff Langca271392017-04-05 12:30:00 -0400570 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400571 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400572 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400573 }
574 else
575 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400576 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400577 }
Geoff Lang5d601382014-07-22 15:14:06 -0400578}
579
Corentin Wallez76287682016-04-25 09:23:38 -0400580static bool EqualOrFirstZero(GLuint first, GLuint second)
581{
582 return first == 0 || first == second;
583}
584
Geoff Langca271392017-04-05 12:30:00 -0400585static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
586 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400587 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400588{
Jamie Madill21b786b2016-11-01 17:41:31 -0400589 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400590 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400591 return false;
592 }
Geoff Lang5d601382014-07-22 15:14:06 -0400593
Jamie Madill21b786b2016-11-01 17:41:31 -0400594 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
595 // must both be signed, unsigned, or fixed point and both source and destinations
596 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
597 // conversion between fixed and floating point.
598
599 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
600 (framebufferFormatInfo.colorEncoding == GL_SRGB))
601 {
602 return false;
603 }
604
605 if (((textureFormatInfo.componentType == GL_INT) !=
606 (framebufferFormatInfo.componentType == GL_INT)) ||
607 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
608 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
609 {
610 return false;
611 }
612
613 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
614 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
615 textureFormatInfo.componentType == GL_FLOAT) &&
616 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
617 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
618 framebufferFormatInfo.componentType == GL_FLOAT))
619 {
620 return false;
621 }
622
623 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
624 // The effective internal format of the source buffer is determined with the following rules
625 // applied in order:
626 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
627 // format then the effective internal format is the source buffer's sized internal format.
628 // * If the source buffer is a texture that was created with an unsized base internal format,
629 // then the effective internal format is the source image array's effective internal
630 // format, as specified by table 3.12, which is determined from the <format> and <type>
631 // that were used when the source image array was specified by TexImage*.
632 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
633 // where Destination Internal Format matches internalformat and where the [source channel
634 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
635 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
636 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800637 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400638 if (readBufferHandle != 0)
639 {
640 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
641 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400642 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400643 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400644 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400645 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400646 else
Geoff Lang5d601382014-07-22 15:14:06 -0400647 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400648 // Renderbuffers cannot be created with an unsized internal format, so this must be an
649 // unsized-format texture. We can use the same table we use when creating textures to
650 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400651 sourceEffectiveFormat =
652 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400653 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400654 }
655 else
656 {
657 // The effective internal format must be derived from the source framebuffer's channel
658 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
659 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400660 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400661 GLenum effectiveFormat;
662 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
663 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400664 {
Geoff Langca271392017-04-05 12:30:00 -0400665 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400666 }
667 else
668 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400669 return false;
670 }
671 }
672 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
673 {
674 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400675 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400676 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
677 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
678 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
679 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
680 {
Geoff Langca271392017-04-05 12:30:00 -0400681 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400682 }
683 else
684 {
685 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400686 }
687 }
688 else
689 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400690 UNREACHABLE();
691 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400692 }
Geoff Lang5d601382014-07-22 15:14:06 -0400693 }
694
Geoff Langca271392017-04-05 12:30:00 -0400695 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400696 {
697 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
698 // sized, component sizes of the source and destination formats must exactly match if the
699 // destination format exists.
700 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
701 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
702 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
703 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
704 {
705 return false;
706 }
707 }
708
709 return true; // A conversion function exists, and no rule in the specification has precluded
710 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400711}
712
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500713bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
714 GLenum target,
715 GLint level,
716 GLenum internalformat,
717 bool isSubImage,
718 GLint xoffset,
719 GLint yoffset,
720 GLint zoffset,
721 GLint x,
722 GLint y,
723 GLsizei width,
724 GLsizei height,
725 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400726{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400727 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400728 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400729 xoffset, yoffset, zoffset, x, y, width, height, border,
730 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400731 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400732 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400734 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400735
Jamie Madill51f40ec2016-06-15 14:06:00 -0400736 const auto &state = context->getGLState();
737 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
738 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400739
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400740 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500742 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400743 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400744 }
745
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400746 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500748 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400749 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400750 }
751
Jamie Madill0c8abca2016-07-22 20:21:26 -0400752 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753
754 if (isSubImage)
755 {
Geoff Langca271392017-04-05 12:30:00 -0400756 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500757 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500759 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400760 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761 }
762 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400763 else
764 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400765 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400766 const InternalFormat &framebufferFormat = *source->getFormat().info;
767 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400768 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500770 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400771 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400772 }
773 }
774
Geoff Lang784a8fd2013-09-24 12:33:16 -0400775 // If width or height is zero, it is a no-op. Return false without setting an error.
776 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777}
778
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500779bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
780 GLenum target,
781 GLint level,
782 GLenum internalformat,
783 bool isSubImage,
784 GLint xoffset,
785 GLint yoffset,
786 GLint zoffset,
787 GLint x,
788 GLint y,
789 GLsizei width,
790 GLsizei height,
791 GLint border)
792{
793 if (!ValidTexture2DDestinationTarget(context, target))
794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500795 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500796 return false;
797 }
798
799 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
800 xoffset, yoffset, zoffset, x, y, width, height,
801 border);
802}
803
804bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
805 GLenum target,
806 GLint level,
807 GLenum internalformat,
808 bool isSubImage,
809 GLint xoffset,
810 GLint yoffset,
811 GLint zoffset,
812 GLint x,
813 GLint y,
814 GLsizei width,
815 GLsizei height,
816 GLint border)
817{
818 if (!ValidTexture3DDestinationTarget(context, target))
819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500820 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500821 return false;
822 }
823
824 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
825 xoffset, yoffset, zoffset, x, y, width, height,
826 border);
827}
828
829bool ValidateES3TexStorageParametersBase(Context *context,
830 GLenum target,
831 GLsizei levels,
832 GLenum internalformat,
833 GLsizei width,
834 GLsizei height,
835 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836{
837 if (width < 1 || height < 1 || depth < 1 || levels < 1)
838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500839 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 }
842
Geoff Langb92c1332015-09-04 12:54:55 -0400843 GLsizei maxDim = std::max(width, height);
844 if (target != GL_TEXTURE_2D_ARRAY)
845 {
846 maxDim = std::max(maxDim, depth);
847 }
848
849 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500851 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400852 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 }
854
Geoff Langaae65a42014-05-26 12:43:44 -0400855 const gl::Caps &caps = context->getCaps();
856
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 switch (target)
858 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800859 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Geoff Langaae65a42014-05-26 12:43:44 -0400861 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
862 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500864 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400865 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 }
867 }
868 break;
869
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400870 case GL_TEXTURE_RECTANGLE_ANGLE:
871 {
872 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
873 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
874 {
875 context->handleError(InvalidValue());
876 return false;
877 }
878 }
879 break;
880
He Yunchaoced53ae2016-11-29 15:00:51 +0800881 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400882 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400883 if (width != height)
884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500885 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400886 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400887 }
888
Geoff Langaae65a42014-05-26 12:43:44 -0400889 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400892 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400893 }
894 }
895 break;
896
He Yunchaoced53ae2016-11-29 15:00:51 +0800897 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400898 {
Geoff Langaae65a42014-05-26 12:43:44 -0400899 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
900 static_cast<GLuint>(height) > caps.max3DTextureSize ||
901 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500903 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400904 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905 }
906 }
907 break;
908
He Yunchaoced53ae2016-11-29 15:00:51 +0800909 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 {
Geoff Langaae65a42014-05-26 12:43:44 -0400911 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
912 static_cast<GLuint>(height) > caps.max2DTextureSize ||
913 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500915 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400916 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917 }
918 }
919 break;
920
He Yunchaoced53ae2016-11-29 15:00:51 +0800921 default:
922 UNREACHABLE();
923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925
Geoff Lang691e58c2014-12-19 17:03:25 -0500926 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 if (!texture || texture->id() == 0)
928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500929 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400930 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931 }
932
Geoff Lang69cce582015-09-17 13:20:36 -0400933 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500935 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 }
938
Geoff Langca271392017-04-05 12:30:00 -0400939 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400940 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500942 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945
Geoff Langca271392017-04-05 12:30:00 -0400946 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500948 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 }
951
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400952 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
953 {
954 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
955 return false;
956 }
957
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 return true;
959}
960
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500961bool ValidateES3TexStorage2DParameters(Context *context,
962 GLenum target,
963 GLsizei levels,
964 GLenum internalformat,
965 GLsizei width,
966 GLsizei height,
967 GLsizei depth)
968{
969 if (!ValidTexture2DTarget(context, target))
970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500972 return false;
973 }
974
975 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
976 height, depth);
977}
978
979bool ValidateES3TexStorage3DParameters(Context *context,
980 GLenum target,
981 GLsizei levels,
982 GLenum internalformat,
983 GLsizei width,
984 GLsizei height,
985 GLsizei depth)
986{
987 if (!ValidTexture3DTarget(context, target))
988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500989 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500990 return false;
991 }
992
993 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
994 height, depth);
995}
996
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500997bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
998{
Martin Radev1be913c2016-07-11 17:59:16 +0300999 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001001 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001002 return false;
1003 }
1004
1005 return ValidateBeginQueryBase(context, target, id);
1006}
1007
1008bool ValidateEndQuery(gl::Context *context, GLenum target)
1009{
Martin Radev1be913c2016-07-11 17:59:16 +03001010 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001013 return false;
1014 }
1015
1016 return ValidateEndQueryBase(context, target);
1017}
1018
1019bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1020{
Martin Radev1be913c2016-07-11 17:59:16 +03001021 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001024 return false;
1025 }
1026
Geoff Lang2186c382016-10-14 10:54:54 -04001027 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001028}
1029
1030bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1031{
Martin Radev1be913c2016-07-11 17:59:16 +03001032 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001034 context->handleError(InvalidOperation() << "GLES version < 3.0");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001035 return false;
1036 }
1037
Geoff Lang2186c382016-10-14 10:54:54 -04001038 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001039}
1040
He Yunchaoced53ae2016-11-29 15:00:51 +08001041bool ValidateFramebufferTextureLayer(Context *context,
1042 GLenum target,
1043 GLenum attachment,
1044 GLuint texture,
1045 GLint level,
1046 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001047{
Martin Radev1be913c2016-07-11 17:59:16 +03001048 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001050 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001052 }
1053
Jamie Madill55ec3b12014-07-03 10:38:57 -04001054 if (layer < 0)
1055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001056 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001057 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001058 }
1059
1060 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1061 {
1062 return false;
1063 }
1064
1065 const gl::Caps &caps = context->getCaps();
1066 if (texture != 0)
1067 {
1068 gl::Texture *tex = context->getTexture(texture);
1069 ASSERT(tex);
1070
1071 switch (tex->getTarget())
1072 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001073 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001074 {
1075 if (level > gl::log2(caps.max2DTextureSize))
1076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001077 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001079 }
1080
1081 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001083 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001085 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001086 }
1087 break;
1088
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001090 {
1091 if (level > gl::log2(caps.max3DTextureSize))
1092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001093 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001094 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001095 }
1096
1097 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001099 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001100 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001101 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001102 }
1103 break;
1104
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001106 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001108 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001109
Jamie Madilla3944d42016-07-22 22:13:26 -04001110 const auto &format = tex->getFormat(tex->getTarget(), level);
1111 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001113 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001114 return false;
1115 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001116 }
1117
1118 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001119}
1120
He Yunchaoced53ae2016-11-29 15:00:51 +08001121bool ValidateInvalidateFramebuffer(Context *context,
1122 GLenum target,
1123 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001124 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125{
Martin Radev1be913c2016-07-11 17:59:16 +03001126 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001128 context->handleError(InvalidOperation() << "Operation only supported on ES 3.0 and above");
Austin Kinross08332632015-05-05 13:35:47 -07001129 return false;
1130 }
1131
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 bool defaultFramebuffer = false;
1133
1134 switch (target)
1135 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 case GL_DRAW_FRAMEBUFFER:
1137 case GL_FRAMEBUFFER:
1138 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1139 break;
1140 case GL_READ_FRAMEBUFFER:
1141 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1142 break;
1143 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001144 context->handleError(InvalidEnum() << "Invalid framebuffer target");
He Yunchaoced53ae2016-11-29 15:00:51 +08001145 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 }
1147
He Yunchaoced53ae2016-11-29 15:00:51 +08001148 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1149 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150}
1151
Jamie Madillc29968b2016-01-20 11:17:23 -05001152bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001153{
Martin Radev1be913c2016-07-11 17:59:16 +03001154 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001158 }
1159
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001160 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001162 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001163 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001164 }
1165
1166 return true;
1167}
1168
Olli Etuaho71dfb362016-03-10 14:04:27 +02001169bool ValidateDrawRangeElements(Context *context,
1170 GLenum mode,
1171 GLuint start,
1172 GLuint end,
1173 GLsizei count,
1174 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001175 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001176{
Martin Radev1be913c2016-07-11 17:59:16 +03001177 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001179 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001180 return false;
1181 }
1182
1183 if (end < start)
1184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001185 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001186 return false;
1187 }
1188
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001189 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001190 {
1191 return false;
1192 }
1193
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001194 // Use the parameter buffer to retrieve and cache the index range.
1195 const auto &params = context->getParams<HasIndexRange>();
1196 const auto &indexRangeOpt = params.getIndexRange();
1197 if (!indexRangeOpt.valid())
1198 {
1199 // Unexpected error.
1200 return false;
1201 }
1202
1203 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001204 {
1205 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001206 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001207 return false;
1208 }
1209 return true;
1210}
1211
He Yunchaoced53ae2016-11-29 15:00:51 +08001212bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001213{
Martin Radev1be913c2016-07-11 17:59:16 +03001214 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001216 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001217 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001218 }
1219
Jamie Madill78f41802014-08-25 15:47:55 -04001220 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001221}
1222
Jamie Madillb885e572015-02-03 16:16:04 -05001223bool ValidateReadBuffer(Context *context, GLenum src)
1224{
Martin Radev1be913c2016-07-11 17:59:16 +03001225 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001227 context->handleError(InvalidOperation());
Jamie Madillb885e572015-02-03 16:16:04 -05001228 return false;
1229 }
1230
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001231 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001232
1233 if (readFBO == nullptr)
1234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001235 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001236 return false;
1237 }
1238
1239 if (src == GL_NONE)
1240 {
1241 return true;
1242 }
1243
Olli Etuaho84c9f592016-03-09 14:37:25 +02001244 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001247 return false;
1248 }
1249
1250 if (readFBO->id() == 0)
1251 {
1252 if (src != GL_BACK)
1253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(
1255 InvalidOperation()
1256 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001257 return false;
1258 }
1259 }
1260 else
1261 {
1262 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1263
1264 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001266 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001267 return false;
1268 }
1269 }
1270
1271 return true;
1272}
1273
Jamie Madill86af3d22015-07-21 15:14:07 -04001274bool ValidateCompressedTexImage3D(Context *context,
1275 GLenum target,
1276 GLint level,
1277 GLenum internalformat,
1278 GLsizei width,
1279 GLsizei height,
1280 GLsizei depth,
1281 GLint border,
1282 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001283 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001284{
Martin Radev1be913c2016-07-11 17:59:16 +03001285 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001287 context->handleError(InvalidOperation());
Jamie Madill86af3d22015-07-21 15:14:07 -04001288 return false;
1289 }
1290
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001291 if (!ValidTextureTarget(context, target))
1292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001293 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001294 return false;
1295 }
1296
Jamie Madille2e406c2016-06-02 13:04:10 -04001297 // Validate image size
1298 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001300 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001301 return false;
1302 }
1303
Geoff Langca271392017-04-05 12:30:00 -04001304 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001305 if (!formatInfo.compressed)
1306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001307 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001308 return false;
1309 }
1310
Jamie Madill513558d2016-06-02 13:04:11 -04001311 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001312 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001313 if (blockSizeOrErr.isError())
1314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001315 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001316 return false;
1317 }
1318 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001321 return false;
1322 }
1323
1324 // 3D texture target validation
1325 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001328 return false;
1329 }
1330
1331 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001332 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001333 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1334 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001335 {
1336 return false;
1337 }
1338
1339 return true;
1340}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001341
Corentin Wallezb2931602017-04-11 15:58:57 -04001342bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1343 GLenum target,
1344 GLint level,
1345 GLenum internalformat,
1346 GLsizei width,
1347 GLsizei height,
1348 GLsizei depth,
1349 GLint border,
1350 GLsizei imageSize,
1351 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001352 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001353{
1354 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1355 {
1356 return false;
1357 }
1358
1359 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1360 depth, border, imageSize, data);
1361}
1362
Austin Kinrossbc781f32015-10-26 09:27:38 -07001363bool ValidateBindVertexArray(Context *context, GLuint array)
1364{
Martin Radev1be913c2016-07-11 17:59:16 +03001365 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001368 return false;
1369 }
1370
1371 return ValidateBindVertexArrayBase(context, array);
1372}
1373
Austin Kinrossbc781f32015-10-26 09:27:38 -07001374bool ValidateIsVertexArray(Context *context)
1375{
Martin Radev1be913c2016-07-11 17:59:16 +03001376 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07001379 return false;
1380 }
1381
1382 return true;
1383}
Geoff Langc5629752015-12-07 16:29:04 -05001384
Jiajia Qin6eafb042016-12-27 17:04:07 +08001385static bool ValidateBindBufferCommon(Context *context,
1386 GLenum target,
1387 GLuint index,
1388 GLuint buffer,
1389 GLintptr offset,
1390 GLsizeiptr size)
1391{
1392 if (context->getClientMajorVersion() < 3)
1393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(InvalidOperation());
Jiajia Qin6eafb042016-12-27 17:04:07 +08001395 return false;
1396 }
1397
1398 if (buffer != 0 && offset < 0)
1399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001400 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001401 return false;
1402 }
1403
1404 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1405 !context->isBufferGenerated(buffer))
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001408 return false;
1409 }
1410
1411 const Caps &caps = context->getCaps();
1412 switch (target)
1413 {
1414 case GL_TRANSFORM_FEEDBACK_BUFFER:
1415 {
1416 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001418 context->handleError(InvalidValue() << "index is greater than or equal to the "
1419 "number of TRANSFORM_FEEDBACK_BUFFER "
1420 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001421 return false;
1422 }
1423 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001425 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001426 return false;
1427 }
1428
1429 TransformFeedback *curTransformFeedback =
1430 context->getGLState().getCurrentTransformFeedback();
1431 if (curTransformFeedback && curTransformFeedback->isActive())
1432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidOperation()
1434 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1435 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001436 return false;
1437 }
1438 break;
1439 }
1440 case GL_UNIFORM_BUFFER:
1441 {
1442 if (index >= caps.maxUniformBufferBindings)
1443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidValue() << "index is greater than or equal to the "
1445 "number of UNIFORM_BUFFER indexed "
1446 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001447 return false;
1448 }
1449
1450 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1451 {
1452 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001453 InvalidValue()
1454 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001455 return false;
1456 }
1457 break;
1458 }
1459 case GL_ATOMIC_COUNTER_BUFFER:
1460 {
1461 if (context->getClientVersion() < ES_3_1)
1462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidEnum()
1464 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001465 return false;
1466 }
1467 if (index >= caps.maxAtomicCounterBufferBindings)
1468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001469 context->handleError(InvalidValue() << "index is greater than or equal to the "
1470 "number of ATOMIC_COUNTER_BUFFER "
1471 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001472 return false;
1473 }
1474 if (buffer != 0 && (offset % 4) != 0)
1475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001476 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001477 return false;
1478 }
1479 break;
1480 }
1481 case GL_SHADER_STORAGE_BUFFER:
1482 {
1483 if (context->getClientVersion() < ES_3_1)
1484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidEnum()
1486 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001487 return false;
1488 }
1489 if (index >= caps.maxShaderStorageBufferBindings)
1490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 context->handleError(InvalidValue() << "index is greater than or equal to the "
1492 "number of SHADER_STORAGE_BUFFER "
1493 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001494 return false;
1495 }
1496 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001498 context->handleError(InvalidValue() << "offset must be multiple of value of "
1499 "SHADER_STORAGE_BUFFER_OFFSET_"
1500 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001501 return false;
1502 }
1503 break;
1504 }
1505 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001507 return false;
1508 }
1509
1510 return true;
1511}
1512
1513bool ValidateBindBufferBase(Context *context, GLenum target, GLuint index, GLuint buffer)
1514{
1515 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1516}
1517
1518bool ValidateBindBufferRange(Context *context,
1519 GLenum target,
1520 GLuint index,
1521 GLuint buffer,
1522 GLintptr offset,
1523 GLsizeiptr size)
1524{
1525 if (buffer != 0 && size <= 0)
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidValue()
1528 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001529 return false;
1530 }
1531 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1532}
1533
Geoff Langc5629752015-12-07 16:29:04 -05001534bool ValidateProgramBinary(Context *context,
1535 GLuint program,
1536 GLenum binaryFormat,
1537 const void *binary,
1538 GLint length)
1539{
Martin Radev1be913c2016-07-11 17:59:16 +03001540 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001542 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001543 return false;
1544 }
1545
1546 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1547}
1548
1549bool ValidateGetProgramBinary(Context *context,
1550 GLuint program,
1551 GLsizei bufSize,
1552 GLsizei *length,
1553 GLenum *binaryFormat,
1554 void *binary)
1555{
Martin Radev1be913c2016-07-11 17:59:16 +03001556 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001558 context->handleError(InvalidOperation());
Geoff Langc5629752015-12-07 16:29:04 -05001559 return false;
1560 }
1561
1562 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1563}
1564
Olli Etuahof0fee072016-03-30 15:11:58 +03001565bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001566{
Martin Radev1be913c2016-07-11 17:59:16 +03001567 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001569 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Geoff Langc5629752015-12-07 16:29:04 -05001570 return false;
1571 }
1572
1573 if (GetValidProgram(context, program) == nullptr)
1574 {
1575 return false;
1576 }
1577
1578 switch (pname)
1579 {
1580 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001581 if (value != GL_FALSE && value != GL_TRUE)
1582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001583 context->handleError(InvalidValue()
1584 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001585 return false;
1586 }
Geoff Langc5629752015-12-07 16:29:04 -05001587 break;
1588
Yunchao He61afff12017-03-14 15:34:03 +08001589 case GL_PROGRAM_SEPARABLE:
1590 if (context->getClientVersion() < ES_3_1)
1591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001592 context->handleError(InvalidEnum()
1593 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001594 return false;
1595 }
1596
1597 if (value != GL_FALSE && value != GL_TRUE)
1598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001599 context->handleError(InvalidValue()
1600 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001601 return false;
1602 }
1603 break;
1604
Geoff Langc5629752015-12-07 16:29:04 -05001605 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001606 context->handleError(InvalidEnum()
1607 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001608 return false;
1609 }
1610
1611 return true;
1612}
Jamie Madillc29968b2016-01-20 11:17:23 -05001613
1614bool ValidateBlitFramebuffer(Context *context,
1615 GLint srcX0,
1616 GLint srcY0,
1617 GLint srcX1,
1618 GLint srcY1,
1619 GLint dstX0,
1620 GLint dstY0,
1621 GLint dstX1,
1622 GLint dstY1,
1623 GLbitfield mask,
1624 GLenum filter)
1625{
Martin Radev1be913c2016-07-11 17:59:16 +03001626 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001628 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001629 return false;
1630 }
1631
1632 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1633 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634}
Jamie Madillc29968b2016-01-20 11:17:23 -05001635
1636bool ValidateClearBufferiv(ValidationContext *context,
1637 GLenum buffer,
1638 GLint drawbuffer,
1639 const GLint *value)
1640{
1641 switch (buffer)
1642 {
1643 case GL_COLOR:
1644 if (drawbuffer < 0 ||
1645 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001648 return false;
1649 }
Geoff Lang76e65652017-03-27 14:58:02 -04001650 if (context->getExtensions().webglCompatibility)
1651 {
1652 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001653 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001654 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1655 {
1656 return false;
1657 }
1658 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001659 break;
1660
1661 case GL_STENCIL:
1662 if (drawbuffer != 0)
1663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001664 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001665 return false;
1666 }
1667 break;
1668
1669 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001671 return false;
1672 }
1673
1674 return ValidateClearBuffer(context);
1675}
1676
1677bool ValidateClearBufferuiv(ValidationContext *context,
1678 GLenum buffer,
1679 GLint drawbuffer,
1680 const GLuint *value)
1681{
1682 switch (buffer)
1683 {
1684 case GL_COLOR:
1685 if (drawbuffer < 0 ||
1686 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001689 return false;
1690 }
Geoff Lang76e65652017-03-27 14:58:02 -04001691 if (context->getExtensions().webglCompatibility)
1692 {
1693 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001694 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001695 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1696 {
1697 return false;
1698 }
1699 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001700 break;
1701
1702 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001703 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001704 return false;
1705 }
1706
1707 return ValidateClearBuffer(context);
1708}
1709
1710bool ValidateClearBufferfv(ValidationContext *context,
1711 GLenum buffer,
1712 GLint drawbuffer,
1713 const GLfloat *value)
1714{
1715 switch (buffer)
1716 {
1717 case GL_COLOR:
1718 if (drawbuffer < 0 ||
1719 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001721 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001722 return false;
1723 }
Geoff Lang76e65652017-03-27 14:58:02 -04001724 if (context->getExtensions().webglCompatibility)
1725 {
1726 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1727 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001728 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001729 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1730 {
1731 return false;
1732 }
1733 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001734 break;
1735
1736 case GL_DEPTH:
1737 if (drawbuffer != 0)
1738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001739 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001740 return false;
1741 }
1742 break;
1743
1744 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001745 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001746 return false;
1747 }
1748
1749 return ValidateClearBuffer(context);
1750}
1751
1752bool ValidateClearBufferfi(ValidationContext *context,
1753 GLenum buffer,
1754 GLint drawbuffer,
1755 GLfloat depth,
1756 GLint stencil)
1757{
1758 switch (buffer)
1759 {
1760 case GL_DEPTH_STENCIL:
1761 if (drawbuffer != 0)
1762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001763 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001764 return false;
1765 }
1766 break;
1767
1768 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001769 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001770 return false;
1771 }
1772
1773 return ValidateClearBuffer(context);
1774}
1775
1776bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1777{
Martin Radev1be913c2016-07-11 17:59:16 +03001778 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 return ValidateDrawBuffersBase(context, n, bufs);
1785}
1786
1787bool ValidateCopyTexSubImage3D(Context *context,
1788 GLenum target,
1789 GLint level,
1790 GLint xoffset,
1791 GLint yoffset,
1792 GLint zoffset,
1793 GLint x,
1794 GLint y,
1795 GLsizei width,
1796 GLsizei height)
1797{
Martin Radev1be913c2016-07-11 17:59:16 +03001798 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001800 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05001801 return false;
1802 }
1803
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001804 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1805 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001806}
1807
Jamie Madill73a84962016-02-12 09:27:23 -05001808bool ValidateTexImage3D(Context *context,
1809 GLenum target,
1810 GLint level,
1811 GLint internalformat,
1812 GLsizei width,
1813 GLsizei height,
1814 GLsizei depth,
1815 GLint border,
1816 GLenum format,
1817 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001818 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001819{
Martin Radev1be913c2016-07-11 17:59:16 +03001820 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001822 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001823 return false;
1824 }
1825
1826 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001827 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001828 pixels);
1829}
1830
Geoff Langc52f6f12016-10-14 10:18:00 -04001831bool ValidateTexImage3DRobustANGLE(Context *context,
1832 GLenum target,
1833 GLint level,
1834 GLint internalformat,
1835 GLsizei width,
1836 GLsizei height,
1837 GLsizei depth,
1838 GLint border,
1839 GLenum format,
1840 GLenum type,
1841 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001842 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001843{
1844 if (context->getClientMajorVersion() < 3)
1845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001846 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001847 return false;
1848 }
1849
1850 if (!ValidateRobustEntryPoint(context, bufSize))
1851 {
1852 return false;
1853 }
1854
1855 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1856 0, 0, width, height, depth, border, format, type,
1857 bufSize, pixels);
1858}
1859
Jamie Madill73a84962016-02-12 09:27:23 -05001860bool ValidateTexSubImage3D(Context *context,
1861 GLenum target,
1862 GLint level,
1863 GLint xoffset,
1864 GLint yoffset,
1865 GLint zoffset,
1866 GLsizei width,
1867 GLsizei height,
1868 GLsizei depth,
1869 GLenum format,
1870 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001871 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05001872{
Martin Radev1be913c2016-07-11 17:59:16 +03001873 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001875 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001876 return false;
1877 }
1878
1879 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1880 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001881 -1, pixels);
1882}
1883
1884bool ValidateTexSubImage3DRobustANGLE(Context *context,
1885 GLenum target,
1886 GLint level,
1887 GLint xoffset,
1888 GLint yoffset,
1889 GLint zoffset,
1890 GLsizei width,
1891 GLsizei height,
1892 GLsizei depth,
1893 GLenum format,
1894 GLenum type,
1895 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001896 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04001897{
1898 if (context->getClientMajorVersion() < 3)
1899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001900 context->handleError(InvalidOperation());
Geoff Langc52f6f12016-10-14 10:18:00 -04001901 return false;
1902 }
1903
1904 if (!ValidateRobustEntryPoint(context, bufSize))
1905 {
1906 return false;
1907 }
1908
1909 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1910 yoffset, zoffset, width, height, depth, 0, format, type,
1911 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001912}
1913
1914bool ValidateCompressedTexSubImage3D(Context *context,
1915 GLenum target,
1916 GLint level,
1917 GLint xoffset,
1918 GLint yoffset,
1919 GLint zoffset,
1920 GLsizei width,
1921 GLsizei height,
1922 GLsizei depth,
1923 GLenum format,
1924 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001925 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05001926{
Martin Radev1be913c2016-07-11 17:59:16 +03001927 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001929 context->handleError(InvalidOperation());
Jamie Madill73a84962016-02-12 09:27:23 -05001930 return false;
1931 }
1932
Geoff Langca271392017-04-05 12:30:00 -04001933 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05001934 if (!formatInfo.compressed)
1935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001936 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05001937 return false;
1938 }
1939
Jamie Madill513558d2016-06-02 13:04:11 -04001940 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001941 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001942 if (blockSizeOrErr.isError())
1943 {
1944 context->handleError(blockSizeOrErr.getError());
1945 return false;
1946 }
1947 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001949 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001950 return false;
1951 }
1952
1953 if (!data)
1954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001955 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05001956 return false;
1957 }
1958
1959 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Lang966c9402017-04-18 12:38:27 -04001960 width, height, depth, 0, format, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001961}
Corentin Wallezb2931602017-04-11 15:58:57 -04001962bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
1963 GLenum target,
1964 GLint level,
1965 GLint xoffset,
1966 GLint yoffset,
1967 GLint zoffset,
1968 GLsizei width,
1969 GLsizei height,
1970 GLsizei depth,
1971 GLenum format,
1972 GLsizei imageSize,
1973 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001974 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001975{
1976 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1977 {
1978 return false;
1979 }
1980
1981 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
1982 height, depth, format, imageSize, data);
1983}
Jamie Madill73a84962016-02-12 09:27:23 -05001984
Olli Etuaho41997e72016-03-10 13:38:39 +02001985bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1986{
1987 return ValidateGenOrDeleteES3(context, n);
1988}
1989
1990bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1991{
1992 return ValidateGenOrDeleteES3(context, n);
1993}
1994
1995bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1996{
1997 return ValidateGenOrDeleteCountES3(context, count);
1998}
1999
2000bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2001{
2002 return ValidateGenOrDeleteCountES3(context, count);
2003}
2004
2005bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2006{
2007 return ValidateGenOrDeleteES3(context, n);
2008}
2009
2010bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2011{
2012 if (!ValidateGenOrDeleteES3(context, n))
2013 {
2014 return false;
2015 }
2016 for (GLint i = 0; i < n; ++i)
2017 {
2018 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2019 if (transformFeedback != nullptr && transformFeedback->isActive())
2020 {
2021 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002022 context->handleError(InvalidOperation()
2023 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002024 return false;
2025 }
2026 }
2027 return true;
2028}
2029
2030bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2031{
2032 return ValidateGenOrDeleteES3(context, n);
2033}
2034
2035bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2036{
2037 return ValidateGenOrDeleteES3(context, n);
2038}
2039
2040bool ValidateGenOrDeleteES3(Context *context, GLint n)
2041{
Martin Radev1be913c2016-07-11 17:59:16 +03002042 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002044 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002045 return false;
2046 }
2047 return ValidateGenOrDelete(context, n);
2048}
2049
2050bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
2051{
Martin Radev1be913c2016-07-11 17:59:16 +03002052 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02002053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002054 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002055 return false;
2056 }
2057 if (count < 0)
2058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002059 context->handleError(InvalidValue() << "count < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02002060 return false;
2061 }
2062 return true;
2063}
2064
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002065bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2066{
Martin Radev1be913c2016-07-11 17:59:16 +03002067 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002069 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002070 return false;
2071 }
2072 switch (primitiveMode)
2073 {
2074 case GL_TRIANGLES:
2075 case GL_LINES:
2076 case GL_POINTS:
2077 break;
2078
2079 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002080 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002081 return false;
2082 }
2083
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002084 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002085 ASSERT(transformFeedback != nullptr);
2086
2087 if (transformFeedback->isActive())
2088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002089 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002090 return false;
2091 }
Geoff Lang79f71042017-08-14 16:43:43 -04002092
2093 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2094 {
2095 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2096 if (buffer.get() && buffer->isMapped())
2097 {
2098 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2099 return false;
2100 }
2101 }
2102
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002103 return true;
2104}
2105
Jamie Madill876429b2017-04-20 15:46:24 -04002106bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002107{
Geoff Lang496c02d2016-10-20 11:38:11 -07002108 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2109}
2110
2111bool ValidateGetBufferPointervRobustANGLE(Context *context,
2112 GLenum target,
2113 GLenum pname,
2114 GLsizei bufSize,
2115 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002116 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002117{
2118 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002119 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002120 return false;
2121 }
2122
Geoff Lang496c02d2016-10-20 11:38:11 -07002123 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2124 {
2125 return false;
2126 }
2127
2128 if (!ValidateRobustBufferSize(context, bufSize, *length))
2129 {
2130 return false;
2131 }
2132
2133 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002134}
2135
2136bool ValidateUnmapBuffer(Context *context, GLenum target)
2137{
Martin Radev1be913c2016-07-11 17:59:16 +03002138 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002140 context->handleError(InvalidOperation());
Olli Etuaho4f667482016-03-30 15:56:35 +03002141 return false;
2142 }
2143
2144 return ValidateUnmapBufferBase(context, target);
2145}
2146
2147bool ValidateMapBufferRange(Context *context,
2148 GLenum target,
2149 GLintptr offset,
2150 GLsizeiptr length,
2151 GLbitfield access)
2152{
Martin Radev1be913c2016-07-11 17:59:16 +03002153 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002156 return false;
2157 }
2158
2159 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2160}
2161
2162bool ValidateFlushMappedBufferRange(Context *context,
2163 GLenum target,
2164 GLintptr offset,
2165 GLsizeiptr length)
2166{
Martin Radev1be913c2016-07-11 17:59:16 +03002167 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002169 context->handleError(InvalidOperation() << "Context does not support GLES3.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002170 return false;
2171 }
2172
2173 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2174}
2175
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002176bool ValidateIndexedStateQuery(ValidationContext *context,
2177 GLenum pname,
2178 GLuint index,
2179 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002180{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002181 if (length)
2182 {
2183 *length = 0;
2184 }
2185
Martin Radev66fb8202016-07-28 11:45:20 +03002186 GLenum nativeType;
2187 unsigned int numParams;
2188 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002190 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002191 return false;
2192 }
2193
2194 const Caps &caps = context->getCaps();
2195 switch (pname)
2196 {
2197 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2198 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2199 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2200 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002202 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002203 return false;
2204 }
2205 break;
2206
2207 case GL_UNIFORM_BUFFER_START:
2208 case GL_UNIFORM_BUFFER_SIZE:
2209 case GL_UNIFORM_BUFFER_BINDING:
2210 if (index >= caps.maxUniformBufferBindings)
2211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002212 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002213 return false;
2214 }
2215 break;
Shao80957d92017-02-20 21:25:59 +08002216
Martin Radev66fb8202016-07-28 11:45:20 +03002217 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2218 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2219 if (index >= 3u)
2220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002221 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002222 return false;
2223 }
2224 break;
Shao80957d92017-02-20 21:25:59 +08002225
Jiajia Qin6eafb042016-12-27 17:04:07 +08002226 case GL_ATOMIC_COUNTER_BUFFER_START:
2227 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2228 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2229 if (context->getClientVersion() < ES_3_1)
2230 {
2231 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002232 InvalidEnum()
2233 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002234 return false;
2235 }
2236 if (index >= caps.maxAtomicCounterBufferBindings)
2237 {
2238 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002239 InvalidValue()
2240 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002241 return false;
2242 }
2243 break;
Shao80957d92017-02-20 21:25:59 +08002244
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002245 case GL_SHADER_STORAGE_BUFFER_START:
2246 case GL_SHADER_STORAGE_BUFFER_SIZE:
2247 case GL_SHADER_STORAGE_BUFFER_BINDING:
2248 if (context->getClientVersion() < ES_3_1)
2249 {
2250 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002251 InvalidEnum()
2252 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002253 return false;
2254 }
2255 if (index >= caps.maxShaderStorageBufferBindings)
2256 {
2257 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002258 InvalidValue()
2259 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002260 return false;
2261 }
2262 break;
2263
Shao80957d92017-02-20 21:25:59 +08002264 case GL_VERTEX_BINDING_BUFFER:
2265 case GL_VERTEX_BINDING_DIVISOR:
2266 case GL_VERTEX_BINDING_OFFSET:
2267 case GL_VERTEX_BINDING_STRIDE:
2268 if (context->getClientVersion() < ES_3_1)
2269 {
2270 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 InvalidEnum()
2272 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002273 return false;
2274 }
2275 if (index >= caps.maxVertexAttribBindings)
2276 {
2277 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002278 InvalidValue()
2279 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002280 return false;
2281 }
2282 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002283 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002284 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002285 return false;
2286 }
2287
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002288 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002289 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002290 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002291 }
2292
2293 return true;
2294}
2295
2296bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2297{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002298 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002300 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002301 return false;
2302 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002303 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002304}
2305
Geoff Langcf255ea2016-10-20 11:39:09 -07002306bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2307 GLenum target,
2308 GLuint index,
2309 GLsizei bufSize,
2310 GLsizei *length,
2311 GLint *data)
2312{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002313 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002315 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Langcf255ea2016-10-20 11:39:09 -07002316 return false;
2317 }
2318
2319 if (!ValidateRobustEntryPoint(context, bufSize))
2320 {
2321 return false;
2322 }
2323
2324 if (!ValidateIndexedStateQuery(context, target, index, length))
2325 {
2326 return false;
2327 }
2328
2329 if (!ValidateRobustBufferSize(context, bufSize, *length))
2330 {
2331 return false;
2332 }
2333
2334 return true;
2335}
2336
Martin Radev66fb8202016-07-28 11:45:20 +03002337bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2338{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002339 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002341 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Martin Radev66fb8202016-07-28 11:45:20 +03002342 return false;
2343 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002344 return ValidateIndexedStateQuery(context, target, index, nullptr);
2345}
2346
2347bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2348 GLenum target,
2349 GLuint index,
2350 GLsizei bufSize,
2351 GLsizei *length,
2352 GLint64 *data)
2353{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002354 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002356 context->handleError(InvalidOperation() << "Context does not support GLES3.0");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002357 return false;
2358 }
2359
2360 if (!ValidateRobustEntryPoint(context, bufSize))
2361 {
2362 return false;
2363 }
2364
2365 if (!ValidateIndexedStateQuery(context, target, index, length))
2366 {
2367 return false;
2368 }
2369
2370 if (!ValidateRobustBufferSize(context, bufSize, *length))
2371 {
2372 return false;
2373 }
2374
2375 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002376}
2377
Jamie Madillb0817d12016-11-01 15:48:31 -04002378bool ValidateCopyBufferSubData(ValidationContext *context,
2379 GLenum readTarget,
2380 GLenum writeTarget,
2381 GLintptr readOffset,
2382 GLintptr writeOffset,
2383 GLsizeiptr size)
2384{
2385 if (context->getClientMajorVersion() < 3)
2386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002387 context->handleError(InvalidOperation() << "CopyBufferSubData requires ES 3 or greater");
Jamie Madillb0817d12016-11-01 15:48:31 -04002388 return false;
2389 }
2390
2391 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
2392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002393 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002394 return false;
2395 }
2396
2397 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2398 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2399
2400 if (!readBuffer || !writeBuffer)
2401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002402 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002403 return false;
2404 }
2405
2406 // Verify that readBuffer and writeBuffer are not currently mapped
2407 if (readBuffer->isMapped() || writeBuffer->isMapped())
2408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002409 context->handleError(InvalidOperation()
2410 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002411 return false;
2412 }
2413
Jamie Madilld2f0c742016-11-02 10:34:41 -04002414 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2415 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2416 CheckedNumeric<GLintptr> checkedSize(size);
2417
2418 auto checkedReadSum = checkedReadOffset + checkedSize;
2419 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2420
2421 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2422 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2423 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002425 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002426 return false;
2427 }
2428
Jamie Madilld2f0c742016-11-02 10:34:41 -04002429 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002431 context->handleError(InvalidValue()
2432 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002433 return false;
2434 }
2435
Jamie Madilld2f0c742016-11-02 10:34:41 -04002436 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2437 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002439 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002440 return false;
2441 }
2442
2443 if (readBuffer == writeBuffer)
2444 {
2445 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2446 if (!checkedOffsetDiff.IsValid())
2447 {
2448 // This shold not be possible.
2449 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002450 context->handleError(InvalidValue()
2451 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002452 return false;
2453 }
2454
2455 if (checkedOffsetDiff.ValueOrDie() < size)
2456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002457 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002458 return false;
2459 }
2460 }
2461
Jamie Madillb0817d12016-11-01 15:48:31 -04002462 return true;
2463}
2464
Geoff Langc339c4e2016-11-29 10:37:36 -05002465bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2466{
2467 if (context->getClientMajorVersion() < 3)
2468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002469 context->handleError(InvalidOperation()
2470 << "glGetStringi requires OpenGL ES 3.0 or higher.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002471 return false;
2472 }
2473
2474 switch (name)
2475 {
2476 case GL_EXTENSIONS:
2477 if (index >= context->getExtensionStringCount())
2478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002479 context->handleError(InvalidValue()
2480 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002481 return false;
2482 }
2483 break;
2484
2485 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2486 if (!context->getExtensions().requestExtension)
2487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002489 return false;
2490 }
2491 if (index >= context->getRequestableExtensionStringCount())
2492 {
2493 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002494 InvalidValue()
2495 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002496 return false;
2497 }
2498 break;
2499
2500 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002501 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002502 return false;
2503 }
2504
2505 return true;
2506}
2507
Jamie Madille8fb6402017-02-14 17:56:40 -05002508bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2509 GLenum target,
2510 GLsizei samples,
2511 GLenum internalformat,
2512 GLsizei width,
2513 GLsizei height)
2514{
2515 if (context->getClientMajorVersion() < 3)
2516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002517 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002518 return false;
2519 }
2520
2521 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2522 height))
2523 {
2524 return false;
2525 }
2526
2527 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2528 // format if samples is greater than zero.
Geoff Langca271392017-04-05 12:30:00 -04002529 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Jamie Madille8fb6402017-02-14 17:56:40 -05002530 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2531 samples > 0)
2532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002533 context->handleError(InvalidOperation());
Jamie Madille8fb6402017-02-14 17:56:40 -05002534 return false;
2535 }
2536
2537 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2538 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2539 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2540 {
2541 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 InvalidOperation()
2543 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002544 return false;
2545 }
2546
2547 return true;
2548}
2549
Geoff Langaa086d62017-03-23 16:47:21 -04002550bool ValidateVertexAttribIPointer(ValidationContext *context,
2551 GLuint index,
2552 GLint size,
2553 GLenum type,
2554 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002555 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002556{
2557 if (context->getClientMajorVersion() < 3)
2558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidOperation()
2560 << "VertexAttribIPointer requires OpenGL ES 3.0 or higher.");
Geoff Langaa086d62017-03-23 16:47:21 -04002561 return false;
2562 }
2563
Shao80957d92017-02-20 21:25:59 +08002564 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002565 {
Geoff Langaa086d62017-03-23 16:47:21 -04002566 return false;
2567 }
2568
Geoff Langaa086d62017-03-23 16:47:21 -04002569 if (stride < 0)
2570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002571 context->handleError(InvalidValue() << "stride cannot be negative.");
Geoff Langaa086d62017-03-23 16:47:21 -04002572 return false;
2573 }
2574
Shao80957d92017-02-20 21:25:59 +08002575 const Caps &caps = context->getCaps();
2576 if (context->getClientVersion() >= ES_3_1)
2577 {
2578 if (stride > caps.maxVertexAttribStride)
2579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002580 context->handleError(InvalidValue()
2581 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08002582 return false;
2583 }
2584
2585 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2586 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2587 // validation should be inherited.
2588 if (index >= caps.maxVertexAttribBindings)
2589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002590 context->handleError(InvalidValue()
2591 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002592 return false;
2593 }
2594 }
2595
Geoff Langaa086d62017-03-23 16:47:21 -04002596 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2597 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2598 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2599 // and the pointer argument is not NULL.
2600 if (context->getGLState().getVertexArrayId() != 0 &&
2601 context->getGLState().getArrayBufferId() == 0 && pointer != nullptr)
2602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002603 context
2604 ->handleError(InvalidOperation()
2605 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04002606 return false;
2607 }
2608
Geoff Lang2d62ab72017-03-23 16:54:40 -04002609 if (context->getExtensions().webglCompatibility)
2610 {
2611 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2612 {
2613 return false;
2614 }
2615 }
2616
Geoff Langaa086d62017-03-23 16:47:21 -04002617 return true;
2618}
2619
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002620bool ValidateGetSynciv(Context *context,
2621 GLsync sync,
2622 GLenum pname,
2623 GLsizei bufSize,
2624 GLsizei *length,
2625 GLint *values)
2626{
2627 if (context->getClientMajorVersion() < 3)
2628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002629 context->handleError(InvalidOperation() << "GetSynciv requires OpenGL ES 3.0 or higher.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002630 return false;
2631 }
2632
2633 if (bufSize < 0)
2634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002635 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002636 return false;
2637 }
2638
2639 FenceSync *fenceSync = context->getFenceSync(sync);
2640 if (!fenceSync)
2641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002642 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002643 return false;
2644 }
2645
2646 switch (pname)
2647 {
2648 case GL_OBJECT_TYPE:
2649 case GL_SYNC_CONDITION:
2650 case GL_SYNC_FLAGS:
2651 case GL_SYNC_STATUS:
2652 break;
2653
2654 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002655 context->handleError(InvalidEnum() << "Invalid pname.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04002656 return false;
2657 }
2658
2659 return true;
2660}
2661
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002662bool ValidateDrawElementsInstanced(ValidationContext *context,
2663 GLenum mode,
2664 GLsizei count,
2665 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002666 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002667 GLsizei instanceCount)
2668{
2669 if (context->getClientMajorVersion() < 3)
2670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002671 context->handleError(InvalidOperation() << "Requires a GLES 3.0 or higher context.");
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002672 return false;
2673 }
2674
2675 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2676}
2677
Martin Radev137032d2017-07-13 10:11:12 +03002678bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2679 GLenum target,
2680 GLenum attachment,
2681 GLuint texture,
2682 GLint level,
2683 GLint baseViewIndex,
2684 GLsizei numViews)
2685{
2686
2687 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2688 numViews))
2689 {
2690 return false;
2691 }
2692
2693 if (baseViewIndex < 0)
2694 {
2695 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2696 return false;
2697 }
2698
2699 if (texture != 0)
2700 {
2701 Texture *tex = context->getTexture(texture);
2702 ASSERT(tex);
2703
2704 switch (tex->getTarget())
2705 {
2706 case GL_TEXTURE_2D_ARRAY:
2707 {
2708 const Caps &caps = context->getCaps();
2709 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2710 {
2711 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2712 "greater than "
2713 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2714 return false;
2715 }
2716 }
2717 break;
2718 default:
2719 context->handleError(InvalidOperation()
2720 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2721 return false;
2722 }
2723
2724 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2725 {
2726 return false;
2727 }
2728 }
2729
2730 return true;
2731}
2732
2733bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2734 GLenum target,
2735 GLenum attachment,
2736 GLuint texture,
2737 GLint level,
2738 GLsizei numViews,
2739 const GLint *viewportOffsets)
2740{
2741 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2742 numViews))
2743 {
2744 return false;
2745 }
2746
2747 const GLsizei numViewportOffsetValues = numViews * 2;
2748 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2749 {
2750 if (viewportOffsets[i] < 0)
2751 {
2752 context->handleError(InvalidValue()
2753 << "viewportOffsets cannot contain negative values.");
2754 return false;
2755 }
2756 }
2757
2758 if (texture != 0)
2759 {
2760 Texture *tex = context->getTexture(texture);
2761 ASSERT(tex);
2762
2763 switch (tex->getTarget())
2764 {
2765 case GL_TEXTURE_2D:
2766 break;
2767 default:
2768 context->handleError(InvalidOperation()
2769 << "Texture's target must be GL_TEXTURE_2D.");
2770 return false;
2771 }
2772
2773 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2774 {
2775 return false;
2776 }
2777 }
2778
2779 return true;
2780}
2781
Jamie Madillc29968b2016-01-20 11:17:23 -05002782} // namespace gl