blob: 9754d5eeedd9f1736ff41dd8abd3ccdfbc640b13 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madilld2f0c742016-11-02 10:34:41 -040011#include "base/numerics/safe_conversions.h"
12#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/validationES.h"
15#include "libANGLE/Context.h"
16#include "libANGLE/Texture.h"
17#include "libANGLE/Framebuffer.h"
18#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040021
Jamie Madille2e406c2016-06-02 13:04:10 -040022using namespace angle;
23
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024namespace gl
25{
26
He Yunchaoced53ae2016-11-29 15:00:51 +080027static bool ValidateTexImageFormatCombination(gl::Context *context,
28 GLenum internalFormat,
29 GLenum format,
30 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -040031{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050032 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
33 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
34 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
35 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
Geoff Langbaadf232014-08-04 13:58:02 -040036 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
Geoff Langeb66a6e2016-10-31 13:06:12 -040037 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang5d601382014-07-22 15:14:06 -040038 {
Jamie Madill437fa652016-05-03 15:13:24 -040039 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040040 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040041 }
42
43 // The type and format are valid if any supported internal format has that type and format
Jamie Madill55e98212016-10-05 16:39:13 -040044 if (!ValidES3Format(format) || !ValidES3Type(type))
Geoff Lang5d601382014-07-22 15:14:06 -040045 {
Jamie Madill437fa652016-05-03 15:13:24 -040046 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -040047 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040048 }
49
50 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -040051 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -040052 {
Jamie Madill437fa652016-05-03 15:13:24 -040053 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -040054 return false;
Geoff Lang5d601382014-07-22 15:14:06 -040055 }
56
57 return true;
58}
59
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050060bool ValidateES3TexImageParametersBase(Context *context,
61 GLenum target,
62 GLint level,
63 GLenum internalformat,
64 bool isCompressed,
65 bool isSubImage,
66 GLint xoffset,
67 GLint yoffset,
68 GLint zoffset,
69 GLsizei width,
70 GLsizei height,
71 GLsizei depth,
72 GLint border,
73 GLenum format,
74 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -040075 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -050076 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040077{
78 // Validate image size
Austin Kinross08528e12015-10-07 16:24:40 -070079 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040083 }
84
Geoff Lange8ebe7f2013-08-05 15:03:13 -040085 // Verify zero border
86 if (border != 0)
87 {
Jamie Madill437fa652016-05-03 15:13:24 -040088 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040090 }
91
Jamie Madill6f38f822014-06-06 17:12:20 -040092 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
93 std::numeric_limits<GLsizei>::max() - xoffset < width ||
94 std::numeric_limits<GLsizei>::max() - yoffset < height ||
95 std::numeric_limits<GLsizei>::max() - zoffset < depth)
96 {
Jamie Madill437fa652016-05-03 15:13:24 -040097 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -040098 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040099 }
100
Geoff Langaae65a42014-05-26 12:43:44 -0400101 const gl::Caps &caps = context->getCaps();
102
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400103 switch (target)
104 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800105 case GL_TEXTURE_2D:
106 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
107 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
108 {
109 context->handleError(Error(GL_INVALID_VALUE));
110 return false;
111 }
112 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400113
He Yunchaoced53ae2016-11-29 15:00:51 +0800114 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
115 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
116 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
117 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
118 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
119 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
120 if (!isSubImage && width != height)
121 {
122 context->handleError(Error(GL_INVALID_VALUE));
123 return false;
124 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400125
He Yunchaoced53ae2016-11-29 15:00:51 +0800126 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
127 {
128 context->handleError(Error(GL_INVALID_VALUE));
129 return false;
130 }
131 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400132
He Yunchaoced53ae2016-11-29 15:00:51 +0800133 case GL_TEXTURE_3D:
134 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
135 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
136 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
137 {
138 context->handleError(Error(GL_INVALID_VALUE));
139 return false;
140 }
141 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400142
He Yunchaoced53ae2016-11-29 15:00:51 +0800143 case GL_TEXTURE_2D_ARRAY:
144 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
145 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
146 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
147 {
148 context->handleError(Error(GL_INVALID_VALUE));
149 return false;
150 }
151 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400152
He Yunchaoced53ae2016-11-29 15:00:51 +0800153 default:
154 context->handleError(Error(GL_INVALID_ENUM));
155 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400156 }
157
He Yunchaoced53ae2016-11-29 15:00:51 +0800158 gl::Texture *texture =
159 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400160 if (!texture)
161 {
Jamie Madill437fa652016-05-03 15:13:24 -0400162 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400163 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400164 }
165
Geoff Lang69cce582015-09-17 13:20:36 -0400166 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400167 {
Jamie Madill437fa652016-05-03 15:13:24 -0400168 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400169 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400170 }
171
172 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400173 GLenum actualInternalFormat =
174 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500175 if (isSubImage && actualInternalFormat == GL_NONE)
176 {
177 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
178 return false;
179 }
180
Geoff Lang5d601382014-07-22 15:14:06 -0400181 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400182 if (isCompressed)
183 {
tmartino7c102692015-10-02 16:43:40 -0400184 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400185 {
Jamie Madill437fa652016-05-03 15:13:24 -0400186 context->handleError(Error(
tmartino7c102692015-10-02 16:43:40 -0400187 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
Geoff Langb1196682014-07-23 13:47:29 -0400188 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400189 }
190
tmartino7c102692015-10-02 16:43:40 -0400191 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400192 {
Jamie Madill437fa652016-05-03 15:13:24 -0400193 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400194 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400195 }
196
Geoff Langeb66a6e2016-10-31 13:06:12 -0400197 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400198 {
Jamie Madill437fa652016-05-03 15:13:24 -0400199 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang839ce0b2015-10-23 13:13:12 -0400200 return false;
201 }
202
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400203 if (target == GL_TEXTURE_3D)
204 {
Jamie Madill437fa652016-05-03 15:13:24 -0400205 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400206 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400207 }
208 }
209 else
210 {
Geoff Langbaadf232014-08-04 13:58:02 -0400211 if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400212 {
Geoff Lang5d601382014-07-22 15:14:06 -0400213 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400214 }
215
216 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
217 {
Jamie Madill437fa652016-05-03 15:13:24 -0400218 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400219 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400220 }
221 }
222
223 // Validate sub image parameters
224 if (isSubImage)
225 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500226 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400227 {
Jamie Madill437fa652016-05-03 15:13:24 -0400228 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 }
231
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 if (width == 0 || height == 0 || depth == 0)
233 {
234 return false;
235 }
236
237 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
238 {
Jamie Madill437fa652016-05-03 15:13:24 -0400239 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400241 }
242
243 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
244 std::numeric_limits<GLsizei>::max() - yoffset < height ||
245 std::numeric_limits<GLsizei>::max() - zoffset < depth)
246 {
Jamie Madill437fa652016-05-03 15:13:24 -0400247 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400249 }
250
Geoff Langa9be0dc2014-12-17 12:34:40 -0500251 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
252 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
253 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400254 {
Jamie Madill437fa652016-05-03 15:13:24 -0400255 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400257 }
258 }
259
Geoff Langff5b2d52016-09-07 11:32:23 -0400260 if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
261 imageSize))
262 {
263 return false;
264 }
265
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400266 // Check for pixel unpack buffer related API errors
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700267 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400268 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400269 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800270 // ...data is not evenly divisible into the number of bytes needed to store in memory a
271 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400272 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400273 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400274 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400275 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400276 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
277
Geoff Langff5b2d52016-09-07 11:32:23 -0400278 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400279 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400280 context->handleError(
281 Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
Jamie Madillc751d1e2014-10-21 17:46:29 -0400282 return false;
283 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400284 }
285
Jamie Madill7a5f7382014-03-05 15:01:24 -0500286 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700287 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500288 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400289 context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -0400290 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500291 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400292 }
293
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400294 return true;
295}
296
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500297bool ValidateES3TexImage2DParameters(Context *context,
298 GLenum target,
299 GLint level,
300 GLenum internalformat,
301 bool isCompressed,
302 bool isSubImage,
303 GLint xoffset,
304 GLint yoffset,
305 GLint zoffset,
306 GLsizei width,
307 GLsizei height,
308 GLsizei depth,
309 GLint border,
310 GLenum format,
311 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400312 GLsizei imageSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500313 const GLvoid *pixels)
314{
315 if (!ValidTexture2DDestinationTarget(context, target))
316 {
Jamie Madill437fa652016-05-03 15:13:24 -0400317 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500318 return false;
319 }
320
321 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
322 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400323 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500324}
325
326bool ValidateES3TexImage3DParameters(Context *context,
327 GLenum target,
328 GLint level,
329 GLenum internalformat,
330 bool isCompressed,
331 bool isSubImage,
332 GLint xoffset,
333 GLint yoffset,
334 GLint zoffset,
335 GLsizei width,
336 GLsizei height,
337 GLsizei depth,
338 GLint border,
339 GLenum format,
340 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400341 GLsizei bufSize,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500342 const GLvoid *pixels)
343{
344 if (!ValidTexture3DDestinationTarget(context, target))
345 {
Jamie Madill437fa652016-05-03 15:13:24 -0400346 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500347 return false;
348 }
349
350 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
351 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langc52f6f12016-10-14 10:18:00 -0400352 depth, border, format, type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500353}
354
Geoff Lang5d601382014-07-22 15:14:06 -0400355struct EffectiveInternalFormatInfo
356{
Jamie Madill76648fe2016-10-05 17:01:41 -0400357 GLenum effectiveFormat;
358 GLenum destFormat;
359 GLuint minRedBits;
360 GLuint maxRedBits;
361 GLuint minGreenBits;
362 GLuint maxGreenBits;
363 GLuint minBlueBits;
364 GLuint maxBlueBits;
365 GLuint minAlphaBits;
366 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400367};
368
Jamie Madill76648fe2016-10-05 17:01:41 -0400369static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
370 GLenum targetFormat,
371 const EffectiveInternalFormatInfo *list,
372 size_t size,
373 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400374{
Jamie Madill76648fe2016-10-05 17:01:41 -0400375 for (size_t curFormat = 0; curFormat < size; ++curFormat)
376 {
377 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
378 if ((formatInfo.destFormat == targetFormat) &&
379 (formatInfo.minRedBits <= srcFormat.redBits &&
380 formatInfo.maxRedBits >= srcFormat.redBits) &&
381 (formatInfo.minGreenBits <= srcFormat.greenBits &&
382 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
383 (formatInfo.minBlueBits <= srcFormat.blueBits &&
384 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
385 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
386 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
387 {
388 *outEffectiveFormat = formatInfo.effectiveFormat;
389 return true;
390 }
391 }
Geoff Lang5d601382014-07-22 15:14:06 -0400392
Jamie Madill76648fe2016-10-05 17:01:41 -0400393 *outEffectiveFormat = GL_NONE;
394 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400395}
396
Jamie Madill76648fe2016-10-05 17:01:41 -0400397bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
398 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400399{
Jamie Madill76648fe2016-10-05 17:01:41 -0400400 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
401 // Effective internal format coresponding to destination internal format and linear source
402 // buffer component sizes.
403 // | Source channel min/max sizes |
404 // Effective Internal Format | N/A | R | G | B | A |
405 // clang-format off
406 constexpr EffectiveInternalFormatInfo list[] = {
407 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
408 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
409 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
410 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
411 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
412 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
413 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
414 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
415 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
416 };
417 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400418
Jamie Madill76648fe2016-10-05 17:01:41 -0400419 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
420}
Geoff Lang5d601382014-07-22 15:14:06 -0400421
Jamie Madill76648fe2016-10-05 17:01:41 -0400422bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
423 const InternalFormat &destFormat,
424 GLenum *outEffectiveFormat)
425{
426 constexpr GLuint umax = UINT_MAX;
427
428 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
429 // Effective internal format coresponding to destination internal format andlinear source buffer
430 // component sizes.
431 // | Source channel min/max sizes |
432 // Effective Internal Format | Dest Format | R | G | B | A |
433 // clang-format off
434 constexpr EffectiveInternalFormatInfo list[] = {
435 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
436 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
437 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
438 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
439 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
440 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
441 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
442 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
443 };
444 // clang-format on
445
446 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
447 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400448}
449
He Yunchaoced53ae2016-11-29 15:00:51 +0800450static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
451 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400452 GLenum *outEffectiveFormat)
453{
Geoff Lang5d601382014-07-22 15:14:06 -0400454 if (destFormat.pixelBytes > 0)
455 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400456 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400457 }
458 else
459 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400460 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400461 }
Geoff Lang5d601382014-07-22 15:14:06 -0400462}
463
Corentin Wallez76287682016-04-25 09:23:38 -0400464static bool EqualOrFirstZero(GLuint first, GLuint second)
465{
466 return first == 0 || first == second;
467}
468
Jamie Madill0c8abca2016-07-22 20:21:26 -0400469static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
470 const Format &framebufferFormat,
471 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400472{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400473 const auto &textureFormatInfo = *textureFormat.info;
474 const auto &framebufferFormatInfo = *framebufferFormat.info;
Geoff Lang5d601382014-07-22 15:14:06 -0400475
Jamie Madill21b786b2016-11-01 17:41:31 -0400476 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400477 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400478 return false;
479 }
Geoff Lang5d601382014-07-22 15:14:06 -0400480
Jamie Madill21b786b2016-11-01 17:41:31 -0400481 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
482 // must both be signed, unsigned, or fixed point and both source and destinations
483 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
484 // conversion between fixed and floating point.
485
486 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
487 (framebufferFormatInfo.colorEncoding == GL_SRGB))
488 {
489 return false;
490 }
491
492 if (((textureFormatInfo.componentType == GL_INT) !=
493 (framebufferFormatInfo.componentType == GL_INT)) ||
494 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
495 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
496 {
497 return false;
498 }
499
500 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
501 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
502 textureFormatInfo.componentType == GL_FLOAT) &&
503 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
504 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
505 framebufferFormatInfo.componentType == GL_FLOAT))
506 {
507 return false;
508 }
509
510 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
511 // The effective internal format of the source buffer is determined with the following rules
512 // applied in order:
513 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
514 // format then the effective internal format is the source buffer's sized internal format.
515 // * If the source buffer is a texture that was created with an unsized base internal format,
516 // then the effective internal format is the source image array's effective internal
517 // format, as specified by table 3.12, which is determined from the <format> and <type>
518 // that were used when the source image array was specified by TexImage*.
519 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
520 // where Destination Internal Format matches internalformat and where the [source channel
521 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
522 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
523 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
524 const InternalFormat *sourceEffectiveFormat = NULL;
525 if (readBufferHandle != 0)
526 {
527 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
528 // renderbuffer
529 if (framebufferFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400530 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400531 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400532 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400533 else
Geoff Lang5d601382014-07-22 15:14:06 -0400534 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400535 // Renderbuffers cannot be created with an unsized internal format, so this must be an
536 // unsized-format texture. We can use the same table we use when creating textures to
537 // get its effective sized format.
538 GLenum sizedInternalFormat =
539 GetSizedInternalFormat(framebufferFormatInfo.format, framebufferFormatInfo.type);
540 sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400541 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400542 }
543 else
544 {
545 // The effective internal format must be derived from the source framebuffer's channel
546 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
547 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400548 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400549 GLenum effectiveFormat;
550 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
551 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400552 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400553 sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400554 }
555 else
556 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400557 return false;
558 }
559 }
560 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
561 {
562 // SRGB buffers can only be copied to sized format destinations according to table 3.18
563 if (textureFormat.sized &&
564 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
565 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
566 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
567 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
568 {
569 sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
570 }
571 else
572 {
573 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400574 }
575 }
576 else
577 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400578 UNREACHABLE();
579 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400580 }
Geoff Lang5d601382014-07-22 15:14:06 -0400581 }
582
Jamie Madill21b786b2016-11-01 17:41:31 -0400583 if (textureFormat.sized)
584 {
585 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
586 // sized, component sizes of the source and destination formats must exactly match if the
587 // destination format exists.
588 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
589 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
590 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
591 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
592 {
593 return false;
594 }
595 }
596
597 return true; // A conversion function exists, and no rule in the specification has precluded
598 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400599}
600
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500601bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
602 GLenum target,
603 GLint level,
604 GLenum internalformat,
605 bool isSubImage,
606 GLint xoffset,
607 GLint yoffset,
608 GLint zoffset,
609 GLint x,
610 GLint y,
611 GLsizei width,
612 GLsizei height,
613 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400614{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400615 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400616 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400617 xoffset, yoffset, zoffset, x, y, width, height, border,
618 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400619 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400620 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400621 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400622 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400623
Jamie Madill51f40ec2016-06-15 14:06:00 -0400624 const auto &state = context->getGLState();
625 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
626 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400627
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700628 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400629 {
Jamie Madill437fa652016-05-03 15:13:24 -0400630 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400631 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400632 }
633
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700634 if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill3c7fa222014-06-05 13:08:51 -0400635 {
Jamie Madill437fa652016-05-03 15:13:24 -0400636 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400637 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400638 }
639
Jamie Madill0c8abca2016-07-22 20:21:26 -0400640 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400641
642 if (isSubImage)
643 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400644 if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
Jamie Madillc29968b2016-01-20 11:17:23 -0500645 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400646 {
Jamie Madill437fa652016-05-03 15:13:24 -0400647 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400648 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400649 }
650 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400651 else
652 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400653 // Use format/type from the source FBO. (Might not be perfect for all cases?)
654 const auto framebufferFormat = source->getFormat();
655 Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
656 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400657 {
Jamie Madill437fa652016-05-03 15:13:24 -0400658 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400659 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400660 }
661 }
662
Geoff Lang784a8fd2013-09-24 12:33:16 -0400663 // If width or height is zero, it is a no-op. Return false without setting an error.
664 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665}
666
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500667bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
668 GLenum target,
669 GLint level,
670 GLenum internalformat,
671 bool isSubImage,
672 GLint xoffset,
673 GLint yoffset,
674 GLint zoffset,
675 GLint x,
676 GLint y,
677 GLsizei width,
678 GLsizei height,
679 GLint border)
680{
681 if (!ValidTexture2DDestinationTarget(context, target))
682 {
Jamie Madill437fa652016-05-03 15:13:24 -0400683 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500684 return false;
685 }
686
687 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
688 xoffset, yoffset, zoffset, x, y, width, height,
689 border);
690}
691
692bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
693 GLenum target,
694 GLint level,
695 GLenum internalformat,
696 bool isSubImage,
697 GLint xoffset,
698 GLint yoffset,
699 GLint zoffset,
700 GLint x,
701 GLint y,
702 GLsizei width,
703 GLsizei height,
704 GLint border)
705{
706 if (!ValidTexture3DDestinationTarget(context, target))
707 {
Jamie Madill437fa652016-05-03 15:13:24 -0400708 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500709 return false;
710 }
711
712 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
713 xoffset, yoffset, zoffset, x, y, width, height,
714 border);
715}
716
717bool ValidateES3TexStorageParametersBase(Context *context,
718 GLenum target,
719 GLsizei levels,
720 GLenum internalformat,
721 GLsizei width,
722 GLsizei height,
723 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400724{
725 if (width < 1 || height < 1 || depth < 1 || levels < 1)
726 {
Jamie Madill437fa652016-05-03 15:13:24 -0400727 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400728 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400729 }
730
Geoff Langb92c1332015-09-04 12:54:55 -0400731 GLsizei maxDim = std::max(width, height);
732 if (target != GL_TEXTURE_2D_ARRAY)
733 {
734 maxDim = std::max(maxDim, depth);
735 }
736
737 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400738 {
Jamie Madill437fa652016-05-03 15:13:24 -0400739 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400740 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400741 }
742
Geoff Langaae65a42014-05-26 12:43:44 -0400743 const gl::Caps &caps = context->getCaps();
744
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 switch (target)
746 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800747 case GL_TEXTURE_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400748 {
Geoff Langaae65a42014-05-26 12:43:44 -0400749 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
750 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400751 {
Jamie Madill437fa652016-05-03 15:13:24 -0400752 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400753 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754 }
755 }
756 break;
757
He Yunchaoced53ae2016-11-29 15:00:51 +0800758 case GL_TEXTURE_CUBE_MAP:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 if (width != height)
761 {
Jamie Madill437fa652016-05-03 15:13:24 -0400762 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400763 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 }
765
Geoff Langaae65a42014-05-26 12:43:44 -0400766 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 {
Jamie Madill437fa652016-05-03 15:13:24 -0400768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400769 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770 }
771 }
772 break;
773
He Yunchaoced53ae2016-11-29 15:00:51 +0800774 case GL_TEXTURE_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 {
Geoff Langaae65a42014-05-26 12:43:44 -0400776 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
777 static_cast<GLuint>(height) > caps.max3DTextureSize ||
778 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 {
Jamie Madill437fa652016-05-03 15:13:24 -0400780 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400781 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 }
783 }
784 break;
785
He Yunchaoced53ae2016-11-29 15:00:51 +0800786 case GL_TEXTURE_2D_ARRAY:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 {
Geoff Langaae65a42014-05-26 12:43:44 -0400788 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
789 static_cast<GLuint>(height) > caps.max2DTextureSize ||
790 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 {
Jamie Madill437fa652016-05-03 15:13:24 -0400792 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400793 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 }
795 }
796 break;
797
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 default:
799 UNREACHABLE();
800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400801 }
802
Geoff Lang691e58c2014-12-19 17:03:25 -0500803 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 if (!texture || texture->id() == 0)
805 {
Jamie Madill437fa652016-05-03 15:13:24 -0400806 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400807 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808 }
809
Geoff Lang69cce582015-09-17 13:20:36 -0400810 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 {
Jamie Madill437fa652016-05-03 15:13:24 -0400812 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 }
815
Geoff Lang5d601382014-07-22 15:14:06 -0400816 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -0400817 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 {
Jamie Madill437fa652016-05-03 15:13:24 -0400819 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 }
822
Geoff Lang5d601382014-07-22 15:14:06 -0400823 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 {
Jamie Madill437fa652016-05-03 15:13:24 -0400825 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400826 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 }
828
829 return true;
830}
831
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500832bool ValidateES3TexStorage2DParameters(Context *context,
833 GLenum target,
834 GLsizei levels,
835 GLenum internalformat,
836 GLsizei width,
837 GLsizei height,
838 GLsizei depth)
839{
840 if (!ValidTexture2DTarget(context, target))
841 {
Jamie Madill437fa652016-05-03 15:13:24 -0400842 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500843 return false;
844 }
845
846 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
847 height, depth);
848}
849
850bool ValidateES3TexStorage3DParameters(Context *context,
851 GLenum target,
852 GLsizei levels,
853 GLenum internalformat,
854 GLsizei width,
855 GLsizei height,
856 GLsizei depth)
857{
858 if (!ValidTexture3DTarget(context, target))
859 {
Jamie Madill437fa652016-05-03 15:13:24 -0400860 context->handleError(Error(GL_INVALID_ENUM));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500861 return false;
862 }
863
864 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
865 height, depth);
866}
867
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500868bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
869{
Martin Radev1be913c2016-07-11 17:59:16 +0300870 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500871 {
Jamie Madill437fa652016-05-03 15:13:24 -0400872 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500873 return false;
874 }
875
876 return ValidateBeginQueryBase(context, target, id);
877}
878
879bool ValidateEndQuery(gl::Context *context, GLenum target)
880{
Martin Radev1be913c2016-07-11 17:59:16 +0300881 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500882 {
Jamie Madill437fa652016-05-03 15:13:24 -0400883 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500884 return false;
885 }
886
887 return ValidateEndQueryBase(context, target);
888}
889
890bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
891{
Martin Radev1be913c2016-07-11 17:59:16 +0300892 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500893 {
Jamie Madill437fa652016-05-03 15:13:24 -0400894 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500895 return false;
896 }
897
Geoff Lang2186c382016-10-14 10:54:54 -0400898 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500899}
900
901bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
902{
Martin Radev1be913c2016-07-11 17:59:16 +0300903 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500904 {
Jamie Madill437fa652016-05-03 15:13:24 -0400905 context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500906 return false;
907 }
908
Geoff Lang2186c382016-10-14 10:54:54 -0400909 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500910}
911
He Yunchaoced53ae2016-11-29 15:00:51 +0800912bool ValidateFramebufferTextureLayer(Context *context,
913 GLenum target,
914 GLenum attachment,
915 GLuint texture,
916 GLint level,
917 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -0400918{
Martin Radev1be913c2016-07-11 17:59:16 +0300919 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -0400920 {
Jamie Madill437fa652016-05-03 15:13:24 -0400921 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400922 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -0400923 }
924
Jamie Madill55ec3b12014-07-03 10:38:57 -0400925 if (layer < 0)
926 {
Jamie Madill437fa652016-05-03 15:13:24 -0400927 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400928 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400929 }
930
931 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
932 {
933 return false;
934 }
935
936 const gl::Caps &caps = context->getCaps();
937 if (texture != 0)
938 {
939 gl::Texture *tex = context->getTexture(texture);
940 ASSERT(tex);
941
942 switch (tex->getTarget())
943 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800944 case GL_TEXTURE_2D_ARRAY:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400945 {
946 if (level > gl::log2(caps.max2DTextureSize))
947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400950 }
951
952 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400956 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400957 }
958 break;
959
He Yunchaoced53ae2016-11-29 15:00:51 +0800960 case GL_TEXTURE_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -0400961 {
962 if (level > gl::log2(caps.max3DTextureSize))
963 {
Jamie Madill437fa652016-05-03 15:13:24 -0400964 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400965 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400966 }
967
968 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
969 {
Jamie Madill437fa652016-05-03 15:13:24 -0400970 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400971 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400972 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400973 }
974 break;
975
He Yunchaoced53ae2016-11-29 15:00:51 +0800976 default:
977 context->handleError(Error(GL_INVALID_OPERATION));
978 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -0400979 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500980
Jamie Madilla3944d42016-07-22 22:13:26 -0400981 const auto &format = tex->getFormat(tex->getTarget(), level);
982 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500983 {
Jamie Madill437fa652016-05-03 15:13:24 -0400984 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500985 return false;
986 }
Jamie Madill55ec3b12014-07-03 10:38:57 -0400987 }
988
989 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -0400990}
991
He Yunchaoced53ae2016-11-29 15:00:51 +0800992bool ValidateES3RenderbufferStorageParameters(gl::Context *context,
993 GLenum target,
994 GLsizei samples,
995 GLenum internalformat,
996 GLsizei width,
997 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -0800998{
He Yunchaoced53ae2016-11-29 15:00:51 +0800999 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
1000 height))
Corentin Walleze0902642014-11-04 12:32:15 -08001001 {
1002 return false;
1003 }
1004
He Yunchaoced53ae2016-11-29 15:00:51 +08001005 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
1006 // format if samples is greater than zero.
Corentin Walleze0902642014-11-04 12:32:15 -08001007 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001008 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
1009 samples > 0)
Corentin Walleze0902642014-11-04 12:32:15 -08001010 {
Jamie Madill437fa652016-05-03 15:13:24 -04001011 context->handleError(Error(GL_INVALID_OPERATION));
Corentin Walleze0902642014-11-04 12:32:15 -08001012 return false;
1013 }
1014
1015 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
1016 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1017 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1018 {
Jamie Madill437fa652016-05-03 15:13:24 -04001019 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02001020 Error(GL_INVALID_OPERATION,
1021 "Samples must not be greater than maximum supported value for the format."));
Corentin Walleze0902642014-11-04 12:32:15 -08001022 return false;
1023 }
1024
1025 return true;
1026}
1027
He Yunchaoced53ae2016-11-29 15:00:51 +08001028bool ValidateInvalidateFramebuffer(Context *context,
1029 GLenum target,
1030 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001031 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032{
Martin Radev1be913c2016-07-11 17:59:16 +03001033 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001034 {
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(
1036 Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
Austin Kinross08332632015-05-05 13:35:47 -07001037 return false;
1038 }
1039
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 bool defaultFramebuffer = false;
1041
1042 switch (target)
1043 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001044 case GL_DRAW_FRAMEBUFFER:
1045 case GL_FRAMEBUFFER:
1046 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1047 break;
1048 case GL_READ_FRAMEBUFFER:
1049 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1050 break;
1051 default:
1052 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 }
1055
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1057 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058}
1059
Jamie Madillc29968b2016-01-20 11:17:23 -05001060bool ValidateClearBuffer(ValidationContext *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001061{
Martin Radev1be913c2016-07-11 17:59:16 +03001062 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001063 {
Jamie Madill437fa652016-05-03 15:13:24 -04001064 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001065 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001066 }
1067
Jamie Madill51f40ec2016-06-15 14:06:00 -04001068 if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
1069 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001070 {
Jamie Madill437fa652016-05-03 15:13:24 -04001071 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001072 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001073 }
1074
1075 return true;
1076}
1077
Olli Etuaho71dfb362016-03-10 14:04:27 +02001078bool ValidateDrawRangeElements(Context *context,
1079 GLenum mode,
1080 GLuint start,
1081 GLuint end,
1082 GLsizei count,
1083 GLenum type,
1084 const GLvoid *indices,
1085 IndexRange *indexRange)
1086{
Martin Radev1be913c2016-07-11 17:59:16 +03001087 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001088 {
Jamie Madill437fa652016-05-03 15:13:24 -04001089 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001090 return false;
1091 }
1092
1093 if (end < start)
1094 {
Jamie Madill437fa652016-05-03 15:13:24 -04001095 context->handleError(Error(GL_INVALID_VALUE, "end < start"));
Olli Etuaho71dfb362016-03-10 14:04:27 +02001096 return false;
1097 }
1098
1099 if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
1100 {
1101 return false;
1102 }
1103
1104 if (indexRange->end > end || indexRange->start < start)
1105 {
1106 // GL spec says that behavior in this case is undefined - generating an error is fine.
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(
Olli Etuaho71dfb362016-03-10 14:04:27 +02001108 Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
1109 return false;
1110 }
1111 return true;
1112}
1113
He Yunchaoced53ae2016-11-29 15:00:51 +08001114bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001115{
Martin Radev1be913c2016-07-11 17:59:16 +03001116 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001117 {
Jamie Madill437fa652016-05-03 15:13:24 -04001118 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001120 }
1121
Jamie Madill78f41802014-08-25 15:47:55 -04001122 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001123}
1124
Jamie Madillb885e572015-02-03 16:16:04 -05001125bool ValidateReadBuffer(Context *context, GLenum src)
1126{
Martin Radev1be913c2016-07-11 17:59:16 +03001127 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001128 {
Jamie Madill437fa652016-05-03 15:13:24 -04001129 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillb885e572015-02-03 16:16:04 -05001130 return false;
1131 }
1132
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001133 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001134
1135 if (readFBO == nullptr)
1136 {
Jamie Madill437fa652016-05-03 15:13:24 -04001137 context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
Jamie Madillb885e572015-02-03 16:16:04 -05001138 return false;
1139 }
1140
1141 if (src == GL_NONE)
1142 {
1143 return true;
1144 }
1145
Olli Etuaho84c9f592016-03-09 14:37:25 +02001146 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001147 {
Jamie Madill437fa652016-05-03 15:13:24 -04001148 context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
Jamie Madillb885e572015-02-03 16:16:04 -05001149 return false;
1150 }
1151
1152 if (readFBO->id() == 0)
1153 {
1154 if (src != GL_BACK)
1155 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001156 const char *errorMsg =
1157 "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
Jamie Madill437fa652016-05-03 15:13:24 -04001158 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001159 return false;
1160 }
1161 }
1162 else
1163 {
1164 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1165
1166 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1167 {
1168 const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
Jamie Madillb885e572015-02-03 16:16:04 -05001170 return false;
1171 }
1172 }
1173
1174 return true;
1175}
1176
Jamie Madill86af3d22015-07-21 15:14:07 -04001177bool ValidateCompressedTexImage3D(Context *context,
1178 GLenum target,
1179 GLint level,
1180 GLenum internalformat,
1181 GLsizei width,
1182 GLsizei height,
1183 GLsizei depth,
1184 GLint border,
1185 GLsizei imageSize,
1186 const GLvoid *data)
1187{
Martin Radev1be913c2016-07-11 17:59:16 +03001188 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001189 {
Jamie Madill437fa652016-05-03 15:13:24 -04001190 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill86af3d22015-07-21 15:14:07 -04001191 return false;
1192 }
1193
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001194 if (!ValidTextureTarget(context, target))
1195 {
1196 context->handleError(Error(GL_INVALID_ENUM));
1197 return false;
1198 }
1199
Jamie Madille2e406c2016-06-02 13:04:10 -04001200 // Validate image size
1201 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1202 {
1203 context->handleError(Error(GL_INVALID_VALUE));
1204 return false;
1205 }
1206
Jamie Madill86af3d22015-07-21 15:14:07 -04001207 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001208 if (!formatInfo.compressed)
1209 {
1210 context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
1211 return false;
1212 }
1213
Jamie Madill513558d2016-06-02 13:04:11 -04001214 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001215 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001216 if (blockSizeOrErr.isError())
1217 {
Jamie Madill513558d2016-06-02 13:04:11 -04001218 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madille2e406c2016-06-02 13:04:10 -04001219 return false;
1220 }
1221 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill86af3d22015-07-21 15:14:07 -04001222 {
Jamie Madill437fa652016-05-03 15:13:24 -04001223 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill86af3d22015-07-21 15:14:07 -04001224 return false;
1225 }
1226
1227 // 3D texture target validation
1228 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(
Jamie Madill86af3d22015-07-21 15:14:07 -04001231 Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
1232 return false;
1233 }
1234
1235 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001236 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001237 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1238 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001239 {
1240 return false;
1241 }
1242
1243 return true;
1244}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001245
1246bool ValidateBindVertexArray(Context *context, GLuint array)
1247{
Martin Radev1be913c2016-07-11 17:59:16 +03001248 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001249 {
Jamie Madill437fa652016-05-03 15:13:24 -04001250 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001251 return false;
1252 }
1253
1254 return ValidateBindVertexArrayBase(context, array);
1255}
1256
Austin Kinrossbc781f32015-10-26 09:27:38 -07001257bool ValidateIsVertexArray(Context *context)
1258{
Martin Radev1be913c2016-07-11 17:59:16 +03001259 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001260 {
Jamie Madill437fa652016-05-03 15:13:24 -04001261 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001262 return false;
1263 }
1264
1265 return true;
1266}
Geoff Langc5629752015-12-07 16:29:04 -05001267
1268bool ValidateProgramBinary(Context *context,
1269 GLuint program,
1270 GLenum binaryFormat,
1271 const void *binary,
1272 GLint length)
1273{
Martin Radev1be913c2016-07-11 17:59:16 +03001274 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001275 {
Jamie Madill437fa652016-05-03 15:13:24 -04001276 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001277 return false;
1278 }
1279
1280 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1281}
1282
1283bool ValidateGetProgramBinary(Context *context,
1284 GLuint program,
1285 GLsizei bufSize,
1286 GLsizei *length,
1287 GLenum *binaryFormat,
1288 void *binary)
1289{
Martin Radev1be913c2016-07-11 17:59:16 +03001290 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001291 {
Jamie Madill437fa652016-05-03 15:13:24 -04001292 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langc5629752015-12-07 16:29:04 -05001293 return false;
1294 }
1295
1296 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1297}
1298
Olli Etuahof0fee072016-03-30 15:11:58 +03001299bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001300{
Martin Radev1be913c2016-07-11 17:59:16 +03001301 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001302 {
Jamie Madill437fa652016-05-03 15:13:24 -04001303 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Geoff Langc5629752015-12-07 16:29:04 -05001304 return false;
1305 }
1306
1307 if (GetValidProgram(context, program) == nullptr)
1308 {
1309 return false;
1310 }
1311
1312 switch (pname)
1313 {
1314 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001315 if (value != GL_FALSE && value != GL_TRUE)
1316 {
Jamie Madill437fa652016-05-03 15:13:24 -04001317 context->handleError(Error(
Olli Etuahof0fee072016-03-30 15:11:58 +03001318 GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
1319 return false;
1320 }
Geoff Langc5629752015-12-07 16:29:04 -05001321 break;
1322
1323 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001324 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
Geoff Langc5629752015-12-07 16:29:04 -05001325 return false;
1326 }
1327
1328 return true;
1329}
Jamie Madillc29968b2016-01-20 11:17:23 -05001330
1331bool ValidateBlitFramebuffer(Context *context,
1332 GLint srcX0,
1333 GLint srcY0,
1334 GLint srcX1,
1335 GLint srcY1,
1336 GLint dstX0,
1337 GLint dstY0,
1338 GLint dstX1,
1339 GLint dstY1,
1340 GLbitfield mask,
1341 GLenum filter)
1342{
Martin Radev1be913c2016-07-11 17:59:16 +03001343 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001344 {
Jamie Madill437fa652016-05-03 15:13:24 -04001345 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001346 return false;
1347 }
1348
1349 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1350 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351}
Jamie Madillc29968b2016-01-20 11:17:23 -05001352
1353bool ValidateClearBufferiv(ValidationContext *context,
1354 GLenum buffer,
1355 GLint drawbuffer,
1356 const GLint *value)
1357{
1358 switch (buffer)
1359 {
1360 case GL_COLOR:
1361 if (drawbuffer < 0 ||
1362 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1363 {
Jamie Madill437fa652016-05-03 15:13:24 -04001364 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001365 return false;
1366 }
1367 break;
1368
1369 case GL_STENCIL:
1370 if (drawbuffer != 0)
1371 {
Jamie Madill437fa652016-05-03 15:13:24 -04001372 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001373 return false;
1374 }
1375 break;
1376
1377 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001378 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001379 return false;
1380 }
1381
1382 return ValidateClearBuffer(context);
1383}
1384
1385bool ValidateClearBufferuiv(ValidationContext *context,
1386 GLenum buffer,
1387 GLint drawbuffer,
1388 const GLuint *value)
1389{
1390 switch (buffer)
1391 {
1392 case GL_COLOR:
1393 if (drawbuffer < 0 ||
1394 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1395 {
Jamie Madill437fa652016-05-03 15:13:24 -04001396 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001397 return false;
1398 }
1399 break;
1400
1401 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001402 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001403 return false;
1404 }
1405
1406 return ValidateClearBuffer(context);
1407}
1408
1409bool ValidateClearBufferfv(ValidationContext *context,
1410 GLenum buffer,
1411 GLint drawbuffer,
1412 const GLfloat *value)
1413{
1414 switch (buffer)
1415 {
1416 case GL_COLOR:
1417 if (drawbuffer < 0 ||
1418 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001421 return false;
1422 }
1423 break;
1424
1425 case GL_DEPTH:
1426 if (drawbuffer != 0)
1427 {
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001429 return false;
1430 }
1431 break;
1432
1433 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001434 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001435 return false;
1436 }
1437
1438 return ValidateClearBuffer(context);
1439}
1440
1441bool ValidateClearBufferfi(ValidationContext *context,
1442 GLenum buffer,
1443 GLint drawbuffer,
1444 GLfloat depth,
1445 GLint stencil)
1446{
1447 switch (buffer)
1448 {
1449 case GL_DEPTH_STENCIL:
1450 if (drawbuffer != 0)
1451 {
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001453 return false;
1454 }
1455 break;
1456
1457 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001458 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05001459 return false;
1460 }
1461
1462 return ValidateClearBuffer(context);
1463}
1464
1465bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1466{
Martin Radev1be913c2016-07-11 17:59:16 +03001467 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001468 {
Jamie Madill437fa652016-05-03 15:13:24 -04001469 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001470 return false;
1471 }
1472
1473 return ValidateDrawBuffersBase(context, n, bufs);
1474}
1475
1476bool ValidateCopyTexSubImage3D(Context *context,
1477 GLenum target,
1478 GLint level,
1479 GLint xoffset,
1480 GLint yoffset,
1481 GLint zoffset,
1482 GLint x,
1483 GLint y,
1484 GLsizei width,
1485 GLsizei height)
1486{
Martin Radev1be913c2016-07-11 17:59:16 +03001487 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 {
Jamie Madill437fa652016-05-03 15:13:24 -04001489 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 return false;
1491 }
1492
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001493 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1494 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05001495}
1496
Jamie Madill73a84962016-02-12 09:27:23 -05001497bool ValidateTexImage3D(Context *context,
1498 GLenum target,
1499 GLint level,
1500 GLint internalformat,
1501 GLsizei width,
1502 GLsizei height,
1503 GLsizei depth,
1504 GLint border,
1505 GLenum format,
1506 GLenum type,
1507 const GLvoid *pixels)
1508{
Martin Radev1be913c2016-07-11 17:59:16 +03001509 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001510 {
Jamie Madill437fa652016-05-03 15:13:24 -04001511 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001512 return false;
1513 }
1514
1515 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001516 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001517 pixels);
1518}
1519
Geoff Langc52f6f12016-10-14 10:18:00 -04001520bool ValidateTexImage3DRobustANGLE(Context *context,
1521 GLenum target,
1522 GLint level,
1523 GLint internalformat,
1524 GLsizei width,
1525 GLsizei height,
1526 GLsizei depth,
1527 GLint border,
1528 GLenum format,
1529 GLenum type,
1530 GLsizei bufSize,
1531 const GLvoid *pixels)
1532{
1533 if (context->getClientMajorVersion() < 3)
1534 {
1535 context->handleError(Error(GL_INVALID_OPERATION));
1536 return false;
1537 }
1538
1539 if (!ValidateRobustEntryPoint(context, bufSize))
1540 {
1541 return false;
1542 }
1543
1544 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1545 0, 0, width, height, depth, border, format, type,
1546 bufSize, pixels);
1547}
1548
Jamie Madill73a84962016-02-12 09:27:23 -05001549bool ValidateTexSubImage3D(Context *context,
1550 GLenum target,
1551 GLint level,
1552 GLint xoffset,
1553 GLint yoffset,
1554 GLint zoffset,
1555 GLsizei width,
1556 GLsizei height,
1557 GLsizei depth,
1558 GLenum format,
1559 GLenum type,
1560 const GLvoid *pixels)
1561{
Martin Radev1be913c2016-07-11 17:59:16 +03001562 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001563 {
Jamie Madill437fa652016-05-03 15:13:24 -04001564 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001565 return false;
1566 }
1567
1568 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1569 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04001570 -1, pixels);
1571}
1572
1573bool ValidateTexSubImage3DRobustANGLE(Context *context,
1574 GLenum target,
1575 GLint level,
1576 GLint xoffset,
1577 GLint yoffset,
1578 GLint zoffset,
1579 GLsizei width,
1580 GLsizei height,
1581 GLsizei depth,
1582 GLenum format,
1583 GLenum type,
1584 GLsizei bufSize,
1585 const GLvoid *pixels)
1586{
1587 if (context->getClientMajorVersion() < 3)
1588 {
1589 context->handleError(Error(GL_INVALID_OPERATION));
1590 return false;
1591 }
1592
1593 if (!ValidateRobustEntryPoint(context, bufSize))
1594 {
1595 return false;
1596 }
1597
1598 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1599 yoffset, zoffset, width, height, depth, 0, format, type,
1600 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001601}
1602
1603bool ValidateCompressedTexSubImage3D(Context *context,
1604 GLenum target,
1605 GLint level,
1606 GLint xoffset,
1607 GLint yoffset,
1608 GLint zoffset,
1609 GLsizei width,
1610 GLsizei height,
1611 GLsizei depth,
1612 GLenum format,
1613 GLsizei imageSize,
1614 const GLvoid *data)
1615{
Martin Radev1be913c2016-07-11 17:59:16 +03001616 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001617 {
Jamie Madill437fa652016-05-03 15:13:24 -04001618 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madill73a84962016-02-12 09:27:23 -05001619 return false;
1620 }
1621
1622 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001623 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001624 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
Jamie Madille2e406c2016-06-02 13:04:10 -04001625 if (blockSizeOrErr.isError())
1626 {
1627 context->handleError(blockSizeOrErr.getError());
1628 return false;
1629 }
1630 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001633 return false;
1634 }
1635
1636 if (!data)
1637 {
Jamie Madill437fa652016-05-03 15:13:24 -04001638 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001639 return false;
1640 }
1641
1642 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001643 width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
Jamie Madill73a84962016-02-12 09:27:23 -05001644}
1645
Olli Etuaho41997e72016-03-10 13:38:39 +02001646bool ValidateGenQueries(Context *context, GLint n, GLuint *)
1647{
1648 return ValidateGenOrDeleteES3(context, n);
1649}
1650
1651bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
1652{
1653 return ValidateGenOrDeleteES3(context, n);
1654}
1655
1656bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
1657{
1658 return ValidateGenOrDeleteCountES3(context, count);
1659}
1660
1661bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
1662{
1663 return ValidateGenOrDeleteCountES3(context, count);
1664}
1665
1666bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
1667{
1668 return ValidateGenOrDeleteES3(context, n);
1669}
1670
1671bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
1672{
1673 if (!ValidateGenOrDeleteES3(context, n))
1674 {
1675 return false;
1676 }
1677 for (GLint i = 0; i < n; ++i)
1678 {
1679 auto *transformFeedback = context->getTransformFeedback(ids[i]);
1680 if (transformFeedback != nullptr && transformFeedback->isActive())
1681 {
1682 // ES 3.0.4 section 2.15.1 page 86
Jamie Madill437fa652016-05-03 15:13:24 -04001683 context->handleError(
Olli Etuaho41997e72016-03-10 13:38:39 +02001684 Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
1685 return false;
1686 }
1687 }
1688 return true;
1689}
1690
1691bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
1692{
1693 return ValidateGenOrDeleteES3(context, n);
1694}
1695
1696bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
1697{
1698 return ValidateGenOrDeleteES3(context, n);
1699}
1700
1701bool ValidateGenOrDeleteES3(Context *context, GLint n)
1702{
Martin Radev1be913c2016-07-11 17:59:16 +03001703 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001704 {
Jamie Madill437fa652016-05-03 15:13:24 -04001705 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001706 return false;
1707 }
1708 return ValidateGenOrDelete(context, n);
1709}
1710
1711bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
1712{
Martin Radev1be913c2016-07-11 17:59:16 +03001713 if (context->getClientMajorVersion() < 3)
Olli Etuaho41997e72016-03-10 13:38:39 +02001714 {
Jamie Madill437fa652016-05-03 15:13:24 -04001715 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho41997e72016-03-10 13:38:39 +02001716 return false;
1717 }
1718 if (count < 0)
1719 {
Jamie Madill437fa652016-05-03 15:13:24 -04001720 context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02001721 return false;
1722 }
1723 return true;
1724}
1725
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001726bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
1727{
Martin Radev1be913c2016-07-11 17:59:16 +03001728 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001729 {
Jamie Madill437fa652016-05-03 15:13:24 -04001730 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001731 return false;
1732 }
1733 switch (primitiveMode)
1734 {
1735 case GL_TRIANGLES:
1736 case GL_LINES:
1737 case GL_POINTS:
1738 break;
1739
1740 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001742 return false;
1743 }
1744
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001745 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001746 ASSERT(transformFeedback != nullptr);
1747
1748 if (transformFeedback->isActive())
1749 {
Jamie Madill437fa652016-05-03 15:13:24 -04001750 context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02001751 return false;
1752 }
1753 return true;
1754}
1755
Olli Etuaho4f667482016-03-30 15:56:35 +03001756bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
1757{
Geoff Lang496c02d2016-10-20 11:38:11 -07001758 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
1759}
1760
1761bool ValidateGetBufferPointervRobustANGLE(Context *context,
1762 GLenum target,
1763 GLenum pname,
1764 GLsizei bufSize,
1765 GLsizei *length,
1766 GLvoid **params)
1767{
1768 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03001769 {
Olli Etuaho4f667482016-03-30 15:56:35 +03001770 return false;
1771 }
1772
Geoff Lang496c02d2016-10-20 11:38:11 -07001773 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
1774 {
1775 return false;
1776 }
1777
1778 if (!ValidateRobustBufferSize(context, bufSize, *length))
1779 {
1780 return false;
1781 }
1782
1783 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03001784}
1785
1786bool ValidateUnmapBuffer(Context *context, GLenum target)
1787{
Martin Radev1be913c2016-07-11 17:59:16 +03001788 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001789 {
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_OPERATION));
Olli Etuaho4f667482016-03-30 15:56:35 +03001791 return false;
1792 }
1793
1794 return ValidateUnmapBufferBase(context, target);
1795}
1796
1797bool ValidateMapBufferRange(Context *context,
1798 GLenum target,
1799 GLintptr offset,
1800 GLsizeiptr length,
1801 GLbitfield access)
1802{
Martin Radev1be913c2016-07-11 17:59:16 +03001803 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001806 return false;
1807 }
1808
1809 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1810}
1811
1812bool ValidateFlushMappedBufferRange(Context *context,
1813 GLenum target,
1814 GLintptr offset,
1815 GLsizeiptr length)
1816{
Martin Radev1be913c2016-07-11 17:59:16 +03001817 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03001818 {
Jamie Madill437fa652016-05-03 15:13:24 -04001819 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001820 return false;
1821 }
1822
1823 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1824}
1825
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001826bool ValidateIndexedStateQuery(ValidationContext *context,
1827 GLenum pname,
1828 GLuint index,
1829 GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03001830{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001831 if (length)
1832 {
1833 *length = 0;
1834 }
1835
Martin Radev66fb8202016-07-28 11:45:20 +03001836 GLenum nativeType;
1837 unsigned int numParams;
1838 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
1839 {
1840 context->handleError(Error(GL_INVALID_ENUM));
1841 return false;
1842 }
1843
1844 const Caps &caps = context->getCaps();
1845 switch (pname)
1846 {
1847 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1848 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1849 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
1850 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1851 {
1852 context->handleError(Error(GL_INVALID_VALUE));
1853 return false;
1854 }
1855 break;
1856
1857 case GL_UNIFORM_BUFFER_START:
1858 case GL_UNIFORM_BUFFER_SIZE:
1859 case GL_UNIFORM_BUFFER_BINDING:
1860 if (index >= caps.maxUniformBufferBindings)
1861 {
1862 context->handleError(Error(GL_INVALID_VALUE));
1863 return false;
1864 }
1865 break;
1866 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
1867 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
1868 if (index >= 3u)
1869 {
1870 context->handleError(Error(GL_INVALID_VALUE));
1871 return false;
1872 }
1873 break;
1874 default:
1875 context->handleError(Error(GL_INVALID_ENUM));
1876 return false;
1877 }
1878
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001879 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03001880 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001881 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03001882 }
1883
1884 return true;
1885}
1886
1887bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
1888{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001889 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001890 {
1891 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1892 return false;
1893 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001894 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03001895}
1896
Geoff Langcf255ea2016-10-20 11:39:09 -07001897bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
1898 GLenum target,
1899 GLuint index,
1900 GLsizei bufSize,
1901 GLsizei *length,
1902 GLint *data)
1903{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001904 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07001905 {
1906 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1907 return false;
1908 }
1909
1910 if (!ValidateRobustEntryPoint(context, bufSize))
1911 {
1912 return false;
1913 }
1914
1915 if (!ValidateIndexedStateQuery(context, target, index, length))
1916 {
1917 return false;
1918 }
1919
1920 if (!ValidateRobustBufferSize(context, bufSize, *length))
1921 {
1922 return false;
1923 }
1924
1925 return true;
1926}
1927
Martin Radev66fb8202016-07-28 11:45:20 +03001928bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
1929{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001930 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03001931 {
1932 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1933 return false;
1934 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001935 return ValidateIndexedStateQuery(context, target, index, nullptr);
1936}
1937
1938bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
1939 GLenum target,
1940 GLuint index,
1941 GLsizei bufSize,
1942 GLsizei *length,
1943 GLint64 *data)
1944{
Geoff Langeb66a6e2016-10-31 13:06:12 -04001945 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04001946 {
1947 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
1948 return false;
1949 }
1950
1951 if (!ValidateRobustEntryPoint(context, bufSize))
1952 {
1953 return false;
1954 }
1955
1956 if (!ValidateIndexedStateQuery(context, target, index, length))
1957 {
1958 return false;
1959 }
1960
1961 if (!ValidateRobustBufferSize(context, bufSize, *length))
1962 {
1963 return false;
1964 }
1965
1966 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03001967}
1968
Jamie Madillb0817d12016-11-01 15:48:31 -04001969bool ValidateCopyBufferSubData(ValidationContext *context,
1970 GLenum readTarget,
1971 GLenum writeTarget,
1972 GLintptr readOffset,
1973 GLintptr writeOffset,
1974 GLsizeiptr size)
1975{
1976 if (context->getClientMajorVersion() < 3)
1977 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001978 context->handleError(
1979 Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001980 return false;
1981 }
1982
1983 if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
1984 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001985 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001986 return false;
1987 }
1988
1989 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
1990 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
1991
1992 if (!readBuffer || !writeBuffer)
1993 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04001994 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
Jamie Madillb0817d12016-11-01 15:48:31 -04001995 return false;
1996 }
1997
1998 // Verify that readBuffer and writeBuffer are not currently mapped
1999 if (readBuffer->isMapped() || writeBuffer->isMapped())
2000 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002001 context->handleError(
2002 Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002003 return false;
2004 }
2005
Jamie Madilld2f0c742016-11-02 10:34:41 -04002006 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2007 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2008 CheckedNumeric<GLintptr> checkedSize(size);
2009
2010 auto checkedReadSum = checkedReadOffset + checkedSize;
2011 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2012
2013 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2014 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2015 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002016 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002017 context->handleError(
2018 Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
Jamie Madillb0817d12016-11-01 15:48:31 -04002019 return false;
2020 }
2021
Jamie Madilld2f0c742016-11-02 10:34:41 -04002022 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002023 {
Jamie Madilld2f0c742016-11-02 10:34:41 -04002024 context->handleError(
2025 Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
Jamie Madillb0817d12016-11-01 15:48:31 -04002026 return false;
2027 }
2028
Jamie Madilld2f0c742016-11-02 10:34:41 -04002029 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2030 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2031 {
2032 context->handleError(
2033 Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
2034 return false;
2035 }
2036
2037 if (readBuffer == writeBuffer)
2038 {
2039 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2040 if (!checkedOffsetDiff.IsValid())
2041 {
2042 // This shold not be possible.
2043 UNREACHABLE();
2044 context->handleError(
2045 Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
2046 return false;
2047 }
2048
2049 if (checkedOffsetDiff.ValueOrDie() < size)
2050 {
2051 context->handleError(Error(GL_INVALID_VALUE));
2052 return false;
2053 }
2054 }
2055
Jamie Madillb0817d12016-11-01 15:48:31 -04002056 return true;
2057}
2058
Geoff Langc339c4e2016-11-29 10:37:36 -05002059bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2060{
2061 if (context->getClientMajorVersion() < 3)
2062 {
2063 context->handleError(
2064 Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
2065 return false;
2066 }
2067
2068 switch (name)
2069 {
2070 case GL_EXTENSIONS:
2071 if (index >= context->getExtensionStringCount())
2072 {
2073 context->handleError(Error(
2074 GL_INVALID_VALUE, "index must be less than the number of extension strings."));
2075 return false;
2076 }
2077 break;
2078
2079 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2080 if (!context->getExtensions().requestExtension)
2081 {
2082 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2083 return false;
2084 }
2085 if (index >= context->getRequestableExtensionStringCount())
2086 {
2087 context->handleError(
2088 Error(GL_INVALID_VALUE,
2089 "index must be less than the number of requestable extension strings."));
2090 return false;
2091 }
2092 break;
2093
2094 default:
2095 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
2096 return false;
2097 }
2098
2099 return true;
2100}
2101
Jamie Madillc29968b2016-01-20 11:17:23 -05002102} // namespace gl