blob: 540ed1a504d38cef79b8fa54fed9fcb8129310bd [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// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/validationES.h"
Jamie Madill73a84962016-02-12 09:27:23 -050014#include "libANGLE/validationES3.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#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 Langd8605522016-04-13 10:19:12 -040021#include "libANGLE/Uniform.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
23#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030024#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025#include "common/utilities.h"
26
27namespace gl
28{
29
Jamie Madillc29968b2016-01-20 11:17:23 -050030namespace
31{
32
33bool IsPartialBlit(gl::Context *context,
34 const FramebufferAttachment *readBuffer,
35 const FramebufferAttachment *writeBuffer,
36 GLint srcX0,
37 GLint srcY0,
38 GLint srcX1,
39 GLint srcY1,
40 GLint dstX0,
41 GLint dstY0,
42 GLint dstX1,
43 GLint dstY1)
44{
45 const Extents &writeSize = writeBuffer->getSize();
46 const Extents &readSize = readBuffer->getSize();
47
48 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
49 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
50 {
51 return true;
52 }
53
Jamie Madilldfde6ab2016-06-09 07:07:18 -070054 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050055 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050057 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
58 scissor.height < writeSize.height;
59 }
60
61 return false;
62}
63
Sami Väisänend59ca052016-06-21 16:10:00 +030064template <typename T>
65bool ValidatePathInstances(gl::Context *context,
66 GLsizei numPaths,
67 const void *paths,
68 GLuint pathBase)
69{
70 const auto *array = static_cast<const T *>(paths);
71
72 for (GLsizei i = 0; i < numPaths; ++i)
73 {
74 const GLuint pathName = array[i] + pathBase;
75 if (context->hasPath(pathName) && !context->hasPathData(pathName))
76 {
77 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
78 return false;
79 }
80 }
81 return true;
82}
83
84bool ValidateInstancedPathParameters(gl::Context *context,
85 GLsizei numPaths,
86 GLenum pathNameType,
87 const void *paths,
88 GLuint pathBase,
89 GLenum transformType,
90 const GLfloat *transformValues)
91{
92 if (!context->getExtensions().pathRendering)
93 {
94 context->handleError(
95 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
96 return false;
97 }
98
99 if (paths == nullptr)
100 {
101 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
102 return false;
103 }
104
105 if (numPaths < 0)
106 {
107 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
108 return false;
109 }
110
111 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
112 {
113 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
114 return false;
115 }
116
117 std::uint32_t pathNameTypeSize = 0;
118 std::uint32_t componentCount = 0;
119
120 switch (pathNameType)
121 {
122 case GL_UNSIGNED_BYTE:
123 pathNameTypeSize = sizeof(GLubyte);
124 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
125 return false;
126 break;
127
128 case GL_BYTE:
129 pathNameTypeSize = sizeof(GLbyte);
130 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
131 return false;
132 break;
133
134 case GL_UNSIGNED_SHORT:
135 pathNameTypeSize = sizeof(GLushort);
136 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
137 return false;
138 break;
139
140 case GL_SHORT:
141 pathNameTypeSize = sizeof(GLshort);
142 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
143 return false;
144 break;
145
146 case GL_UNSIGNED_INT:
147 pathNameTypeSize = sizeof(GLuint);
148 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
149 return false;
150 break;
151
152 case GL_INT:
153 pathNameTypeSize = sizeof(GLint);
154 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
155 return false;
156 break;
157
158 default:
159 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
160 return false;
161 }
162
163 switch (transformType)
164 {
165 case GL_NONE:
166 componentCount = 0;
167 break;
168 case GL_TRANSLATE_X_CHROMIUM:
169 case GL_TRANSLATE_Y_CHROMIUM:
170 componentCount = 1;
171 break;
172 case GL_TRANSLATE_2D_CHROMIUM:
173 componentCount = 2;
174 break;
175 case GL_TRANSLATE_3D_CHROMIUM:
176 componentCount = 3;
177 break;
178 case GL_AFFINE_2D_CHROMIUM:
179 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
180 componentCount = 6;
181 break;
182 case GL_AFFINE_3D_CHROMIUM:
183 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
184 componentCount = 12;
185 break;
186 default:
187 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
188 return false;
189 }
190 if (componentCount != 0 && transformValues == nullptr)
191 {
192 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
193 return false;
194 }
195
196 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
197 checkedSize += (numPaths * pathNameTypeSize);
198 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
199 if (!checkedSize.IsValid())
200 {
201 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
202 return false;
203 }
204
205 return true;
206}
207
Jamie Madillc29968b2016-01-20 11:17:23 -0500208} // anonymous namespace
209
Geoff Langb1196682014-07-23 13:47:29 -0400210bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400211 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
212 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
213{
Jamie Madill6f38f822014-06-06 17:12:20 -0400214 if (!ValidTexture2DDestinationTarget(context, target))
215 {
Jamie Madill437fa652016-05-03 15:13:24 -0400216 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400217 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400218 }
219
Austin Kinross08528e12015-10-07 16:24:40 -0700220 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400221 {
Jamie Madill437fa652016-05-03 15:13:24 -0400222 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400223 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400224 }
225
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400226 if (level < 0 || xoffset < 0 ||
227 std::numeric_limits<GLsizei>::max() - xoffset < width ||
228 std::numeric_limits<GLsizei>::max() - yoffset < height)
229 {
Jamie Madill437fa652016-05-03 15:13:24 -0400230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
Geoff Lang005df412013-10-16 14:12:50 -0400234 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400235 {
Jamie Madill437fa652016-05-03 15:13:24 -0400236 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400237 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400238 }
239
Geoff Langaae65a42014-05-26 12:43:44 -0400240 const gl::Caps &caps = context->getCaps();
241
Geoff Langa9be0dc2014-12-17 12:34:40 -0500242 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500244 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
245 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 {
Jamie Madill437fa652016-05-03 15:13:24 -0400247 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400249 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500250 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500251 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500252 {
253 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400254 {
Jamie Madill437fa652016-05-03 15:13:24 -0400255 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400257 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258
Geoff Langa9be0dc2014-12-17 12:34:40 -0500259 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
260 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
261 {
Jamie Madill437fa652016-05-03 15:13:24 -0400262 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500263 return false;
264 }
265 }
266 else
267 {
Jamie Madill437fa652016-05-03 15:13:24 -0400268 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400270 }
271
Geoff Lang691e58c2014-12-19 17:03:25 -0500272 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400273 if (!texture)
274 {
Jamie Madill437fa652016-05-03 15:13:24 -0400275 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400276 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400277 }
278
Geoff Langa9be0dc2014-12-17 12:34:40 -0500279 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400280 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500281 if (format != GL_NONE)
282 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400283 if (gl::GetSizedInternalFormat(format, type) !=
284 texture->getFormat(target, level).asSized())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500285 {
Jamie Madill437fa652016-05-03 15:13:24 -0400286 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500287 return false;
288 }
289 }
290
291 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
292 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
293 {
Jamie Madill437fa652016-05-03 15:13:24 -0400294 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500295 return false;
296 }
297 }
298 else
299 {
Geoff Lang69cce582015-09-17 13:20:36 -0400300 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500301 {
Jamie Madill437fa652016-05-03 15:13:24 -0400302 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500303 return false;
304 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305 }
306
307 // Verify zero border
308 if (border != 0)
309 {
Jamie Madill437fa652016-05-03 15:13:24 -0400310 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400314 if (isCompressed)
315 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400316 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400317 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400318 switch (actualInternalFormat)
319 {
320 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
321 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400322 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400323 {
Jamie Madill437fa652016-05-03 15:13:24 -0400324 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400326 }
327 break;
328 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400329 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400330 {
Jamie Madill437fa652016-05-03 15:13:24 -0400331 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400332 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 }
334 break;
335 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400336 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400337 {
Jamie Madill437fa652016-05-03 15:13:24 -0400338 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400339 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340 }
341 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400342 case GL_ETC1_RGB8_OES:
343 if (!context->getExtensions().compressedETC1RGB8Texture)
344 {
Jamie Madill437fa652016-05-03 15:13:24 -0400345 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400346 return false;
347 }
348 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800349 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
350 if (!context->getExtensions().lossyETCDecode)
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800353 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
354 return false;
355 }
356 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400357 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(
tmartino0ccd5ae2015-10-01 14:33:14 -0400359 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
360 return false;
361 }
362 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
363 {
Jamie Madill437fa652016-05-03 15:13:24 -0400364 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400366 }
367 }
368 else
369 {
370 // validate <type> by itself (used as secondary key below)
371 switch (type)
372 {
373 case GL_UNSIGNED_BYTE:
374 case GL_UNSIGNED_SHORT_5_6_5:
375 case GL_UNSIGNED_SHORT_4_4_4_4:
376 case GL_UNSIGNED_SHORT_5_5_5_1:
377 case GL_UNSIGNED_SHORT:
378 case GL_UNSIGNED_INT:
379 case GL_UNSIGNED_INT_24_8_OES:
380 case GL_HALF_FLOAT_OES:
381 case GL_FLOAT:
382 break;
383 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400384 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400385 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400386 }
387
388 // validate <format> + <type> combinations
389 // - invalid <format> -> sets INVALID_ENUM
390 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
391 switch (format)
392 {
393 case GL_ALPHA:
394 case GL_LUMINANCE:
395 case GL_LUMINANCE_ALPHA:
396 switch (type)
397 {
398 case GL_UNSIGNED_BYTE:
399 case GL_FLOAT:
400 case GL_HALF_FLOAT_OES:
401 break;
Geoff Langb1196682014-07-23 13:47:29 -0400402 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400403 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400404 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400405 }
406 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400407 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400408 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400409 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400410 {
Jamie Madill437fa652016-05-03 15:13:24 -0400411 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400412 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400413 }
414 switch (type)
415 {
416 case GL_UNSIGNED_BYTE:
417 case GL_FLOAT:
418 case GL_HALF_FLOAT_OES:
419 break;
420 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400421 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400422 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400423 }
424 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400425 case GL_RGB:
426 switch (type)
427 {
428 case GL_UNSIGNED_BYTE:
429 case GL_UNSIGNED_SHORT_5_6_5:
430 case GL_FLOAT:
431 case GL_HALF_FLOAT_OES:
432 break;
433 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400434 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400436 }
437 break;
438 case GL_RGBA:
439 switch (type)
440 {
441 case GL_UNSIGNED_BYTE:
442 case GL_UNSIGNED_SHORT_4_4_4_4:
443 case GL_UNSIGNED_SHORT_5_5_5_1:
444 case GL_FLOAT:
445 case GL_HALF_FLOAT_OES:
446 break;
447 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400448 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400449 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 }
451 break;
452 case GL_BGRA_EXT:
453 switch (type)
454 {
455 case GL_UNSIGNED_BYTE:
456 break;
457 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400458 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400459 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400460 }
461 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400462 case GL_SRGB_EXT:
463 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400464 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400465 {
Jamie Madill437fa652016-05-03 15:13:24 -0400466 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400467 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400468 }
469 switch (type)
470 {
471 case GL_UNSIGNED_BYTE:
472 break;
473 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400474 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400475 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400476 }
477 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400478 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
479 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
480 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
481 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
482 break;
483 case GL_DEPTH_COMPONENT:
484 switch (type)
485 {
486 case GL_UNSIGNED_SHORT:
487 case GL_UNSIGNED_INT:
488 break;
489 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400490 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400491 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400492 }
493 break;
494 case GL_DEPTH_STENCIL_OES:
495 switch (type)
496 {
497 case GL_UNSIGNED_INT_24_8_OES:
498 break;
499 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400500 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400501 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400502 }
503 break;
504 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400505 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400506 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400507 }
508
509 switch (format)
510 {
511 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
512 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400513 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400514 {
Jamie Madill437fa652016-05-03 15:13:24 -0400515 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400516 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400517 }
518 else
519 {
Jamie Madill437fa652016-05-03 15:13:24 -0400520 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400521 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400522 }
523 break;
524 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400525 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400526 {
Jamie Madill437fa652016-05-03 15:13:24 -0400527 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400528 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400529 }
530 else
531 {
Jamie Madill437fa652016-05-03 15:13:24 -0400532 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400533 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400534 }
535 break;
536 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400537 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400538 {
Jamie Madill437fa652016-05-03 15:13:24 -0400539 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400540 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400541 }
542 else
543 {
Jamie Madill437fa652016-05-03 15:13:24 -0400544 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400545 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400546 }
547 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400548 case GL_ETC1_RGB8_OES:
549 if (context->getExtensions().compressedETC1RGB8Texture)
550 {
Jamie Madill437fa652016-05-03 15:13:24 -0400551 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400552 return false;
553 }
554 else
555 {
Jamie Madill437fa652016-05-03 15:13:24 -0400556 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400557 return false;
558 }
559 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800560 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
561 if (context->getExtensions().lossyETCDecode)
562 {
Jamie Madill437fa652016-05-03 15:13:24 -0400563 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800564 Error(GL_INVALID_OPERATION,
565 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
566 return false;
567 }
568 else
569 {
Jamie Madill437fa652016-05-03 15:13:24 -0400570 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800571 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
572 return false;
573 }
574 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400575 case GL_DEPTH_COMPONENT:
576 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400577 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400578 {
Jamie Madill437fa652016-05-03 15:13:24 -0400579 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400580 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400581 }
582 if (target != GL_TEXTURE_2D)
583 {
Jamie Madill437fa652016-05-03 15:13:24 -0400584 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400585 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400586 }
587 // OES_depth_texture supports loading depth data and multiple levels,
588 // but ANGLE_depth_texture does not
589 if (pixels != NULL || level != 0)
590 {
Jamie Madill437fa652016-05-03 15:13:24 -0400591 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400592 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400593 }
594 break;
595 default:
596 break;
597 }
598
599 if (type == GL_FLOAT)
600 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400601 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400602 {
Jamie Madill437fa652016-05-03 15:13:24 -0400603 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400604 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400605 }
606 }
607 else if (type == GL_HALF_FLOAT_OES)
608 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400609 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400610 {
Jamie Madill437fa652016-05-03 15:13:24 -0400611 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400612 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400613 }
614 }
615 }
616
617 return true;
618}
619
Jamie Madillc29968b2016-01-20 11:17:23 -0500620bool ValidateES2CopyTexImageParameters(ValidationContext *context,
621 GLenum target,
622 GLint level,
623 GLenum internalformat,
624 bool isSubImage,
625 GLint xoffset,
626 GLint yoffset,
627 GLint x,
628 GLint y,
629 GLsizei width,
630 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400631 GLint border)
632{
Jamie Madill560a8d82014-05-21 13:06:20 -0400633 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400634
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500635 if (!ValidTexture2DDestinationTarget(context, target))
636 {
Jamie Madill437fa652016-05-03 15:13:24 -0400637 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500638 return false;
639 }
640
Jamie Madill560a8d82014-05-21 13:06:20 -0400641 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
642 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400643 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400644 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400645 }
646
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700647 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400648 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madillbc393df2015-01-29 13:46:07 -0500649 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
650 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400651
652 // [OpenGL ES 2.0.24] table 3.9
653 if (isSubImage)
654 {
655 switch (textureFormat)
656 {
657 case GL_ALPHA:
658 if (colorbufferFormat != GL_ALPHA8_EXT &&
659 colorbufferFormat != GL_RGBA4 &&
660 colorbufferFormat != GL_RGB5_A1 &&
661 colorbufferFormat != GL_RGBA8_OES)
662 {
Jamie Madill437fa652016-05-03 15:13:24 -0400663 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400664 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665 }
666 break;
667 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400668 if (colorbufferFormat != GL_R8_EXT &&
669 colorbufferFormat != GL_RG8_EXT &&
670 colorbufferFormat != GL_RGB565 &&
671 colorbufferFormat != GL_RGB8_OES &&
672 colorbufferFormat != GL_RGBA4 &&
673 colorbufferFormat != GL_RGB5_A1 &&
674 colorbufferFormat != GL_RGBA8_OES)
675 {
Jamie Madill437fa652016-05-03 15:13:24 -0400676 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400677 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400678 }
679 break;
680 case GL_RED_EXT:
681 if (colorbufferFormat != GL_R8_EXT &&
682 colorbufferFormat != GL_RG8_EXT &&
683 colorbufferFormat != GL_RGB565 &&
684 colorbufferFormat != GL_RGB8_OES &&
685 colorbufferFormat != GL_RGBA4 &&
686 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500687 colorbufferFormat != GL_RGBA8_OES &&
688 colorbufferFormat != GL_R32F &&
689 colorbufferFormat != GL_RG32F &&
690 colorbufferFormat != GL_RGB32F &&
691 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400692 {
Jamie Madill437fa652016-05-03 15:13:24 -0400693 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400694 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400695 }
696 break;
697 case GL_RG_EXT:
698 if (colorbufferFormat != GL_RG8_EXT &&
699 colorbufferFormat != GL_RGB565 &&
700 colorbufferFormat != GL_RGB8_OES &&
701 colorbufferFormat != GL_RGBA4 &&
702 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500703 colorbufferFormat != GL_RGBA8_OES &&
704 colorbufferFormat != GL_RG32F &&
705 colorbufferFormat != GL_RGB32F &&
706 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400707 {
Jamie Madill437fa652016-05-03 15:13:24 -0400708 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400709 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400710 }
711 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712 case GL_RGB:
713 if (colorbufferFormat != GL_RGB565 &&
714 colorbufferFormat != GL_RGB8_OES &&
715 colorbufferFormat != GL_RGBA4 &&
716 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500717 colorbufferFormat != GL_RGBA8_OES &&
718 colorbufferFormat != GL_RGB32F &&
719 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400720 {
Jamie Madill437fa652016-05-03 15:13:24 -0400721 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400722 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 }
724 break;
725 case GL_LUMINANCE_ALPHA:
726 case GL_RGBA:
727 if (colorbufferFormat != GL_RGBA4 &&
728 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500729 colorbufferFormat != GL_RGBA8_OES &&
730 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731 {
Jamie Madill437fa652016-05-03 15:13:24 -0400732 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400733 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400734 }
735 break;
736 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
737 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
738 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
739 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400740 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800741 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400742 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400743 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400744 case GL_DEPTH_COMPONENT:
745 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400746 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400747 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400748 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400749 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400750 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400751 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500752
753 if (internalFormatInfo.type == GL_FLOAT &&
754 !context->getExtensions().textureFloat)
755 {
Jamie Madill437fa652016-05-03 15:13:24 -0400756 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500757 return false;
758 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759 }
760 else
761 {
762 switch (internalformat)
763 {
764 case GL_ALPHA:
765 if (colorbufferFormat != GL_ALPHA8_EXT &&
766 colorbufferFormat != GL_RGBA4 &&
767 colorbufferFormat != GL_RGB5_A1 &&
768 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500769 colorbufferFormat != GL_RGBA8_OES &&
770 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 {
Jamie Madill437fa652016-05-03 15:13:24 -0400772 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400773 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400774 }
775 break;
776 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400777 if (colorbufferFormat != GL_R8_EXT &&
778 colorbufferFormat != GL_RG8_EXT &&
779 colorbufferFormat != GL_RGB565 &&
780 colorbufferFormat != GL_RGB8_OES &&
781 colorbufferFormat != GL_RGBA4 &&
782 colorbufferFormat != GL_RGB5_A1 &&
783 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500784 colorbufferFormat != GL_RGBA8_OES &&
785 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400786 {
Jamie Madill437fa652016-05-03 15:13:24 -0400787 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400788 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400789 }
790 break;
791 case GL_RED_EXT:
792 if (colorbufferFormat != GL_R8_EXT &&
793 colorbufferFormat != GL_RG8_EXT &&
794 colorbufferFormat != GL_RGB565 &&
795 colorbufferFormat != GL_RGB8_OES &&
796 colorbufferFormat != GL_RGBA4 &&
797 colorbufferFormat != GL_RGB5_A1 &&
798 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500799 colorbufferFormat != GL_RGBA8_OES &&
800 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400801 {
Jamie Madill437fa652016-05-03 15:13:24 -0400802 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400803 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400804 }
805 break;
806 case GL_RG_EXT:
807 if (colorbufferFormat != GL_RG8_EXT &&
808 colorbufferFormat != GL_RGB565 &&
809 colorbufferFormat != GL_RGB8_OES &&
810 colorbufferFormat != GL_RGBA4 &&
811 colorbufferFormat != GL_RGB5_A1 &&
812 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500813 colorbufferFormat != GL_RGBA8_OES &&
814 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400815 {
Jamie Madill437fa652016-05-03 15:13:24 -0400816 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400817 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400818 }
819 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820 case GL_RGB:
821 if (colorbufferFormat != GL_RGB565 &&
822 colorbufferFormat != GL_RGB8_OES &&
823 colorbufferFormat != GL_RGBA4 &&
824 colorbufferFormat != GL_RGB5_A1 &&
825 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500826 colorbufferFormat != GL_RGBA8_OES &&
827 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 {
Jamie Madill437fa652016-05-03 15:13:24 -0400829 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400830 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 }
832 break;
833 case GL_LUMINANCE_ALPHA:
834 case GL_RGBA:
835 if (colorbufferFormat != GL_RGBA4 &&
836 colorbufferFormat != GL_RGB5_A1 &&
837 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500838 colorbufferFormat != GL_RGBA8_OES &&
839 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 {
Jamie Madill437fa652016-05-03 15:13:24 -0400841 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 }
844 break;
845 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
846 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400847 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848 {
Jamie Madill437fa652016-05-03 15:13:24 -0400849 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400850 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400851 }
852 else
853 {
Jamie Madill437fa652016-05-03 15:13:24 -0400854 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400855 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400856 }
857 break;
858 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400859 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Jamie Madill437fa652016-05-03 15:13:24 -0400861 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 }
864 else
865 {
Jamie Madill437fa652016-05-03 15:13:24 -0400866 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400867 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868 }
869 break;
870 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400871 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400872 {
Jamie Madill437fa652016-05-03 15:13:24 -0400873 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400874 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400875 }
876 else
877 {
Jamie Madill437fa652016-05-03 15:13:24 -0400878 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400879 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400880 }
881 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400882 case GL_ETC1_RGB8_OES:
883 if (context->getExtensions().compressedETC1RGB8Texture)
884 {
Jamie Madill437fa652016-05-03 15:13:24 -0400885 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400886 return false;
887 }
888 else
889 {
Jamie Madill437fa652016-05-03 15:13:24 -0400890 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400891 return false;
892 }
893 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800894 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
895 if (context->getExtensions().lossyETCDecode)
896 {
Jamie Madill437fa652016-05-03 15:13:24 -0400897 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800898 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
899 return false;
900 }
901 else
902 {
Jamie Madill437fa652016-05-03 15:13:24 -0400903 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800904 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
905 return false;
906 }
907 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 case GL_DEPTH_COMPONENT:
909 case GL_DEPTH_COMPONENT16:
910 case GL_DEPTH_COMPONENT32_OES:
911 case GL_DEPTH_STENCIL_OES:
912 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400913 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 {
Jamie Madill437fa652016-05-03 15:13:24 -0400915 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400916 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917 }
918 else
919 {
Jamie Madill437fa652016-05-03 15:13:24 -0400920 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400921 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 }
923 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400924 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400925 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 }
927 }
928
Geoff Lang784a8fd2013-09-24 12:33:16 -0400929 // If width or height is zero, it is a no-op. Return false without setting an error.
930 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931}
932
Geoff Langb1196682014-07-23 13:47:29 -0400933bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 GLsizei width, GLsizei height)
935{
936 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
937 {
Jamie Madill437fa652016-05-03 15:13:24 -0400938 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400939 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 }
941
942 if (width < 1 || height < 1 || levels < 1)
943 {
Jamie Madill437fa652016-05-03 15:13:24 -0400944 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400945 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400946 }
947
948 if (target == GL_TEXTURE_CUBE_MAP && width != height)
949 {
Jamie Madill437fa652016-05-03 15:13:24 -0400950 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400951 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 }
953
954 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
955 {
Jamie Madill437fa652016-05-03 15:13:24 -0400956 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959
Geoff Lang5d601382014-07-22 15:14:06 -0400960 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
961 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962 {
Jamie Madill437fa652016-05-03 15:13:24 -0400963 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400964 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400965 }
966
Geoff Langaae65a42014-05-26 12:43:44 -0400967 const gl::Caps &caps = context->getCaps();
968
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 switch (target)
970 {
971 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400972 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
973 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 {
Jamie Madill437fa652016-05-03 15:13:24 -0400975 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400976 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400977 }
978 break;
979 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400980 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
981 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 {
Jamie Madill437fa652016-05-03 15:13:24 -0400983 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400984 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400985 }
986 break;
987 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400988 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 }
991
Geoff Langc0b9ef42014-07-02 10:02:37 -0400992 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 {
994 if (!gl::isPow2(width) || !gl::isPow2(height))
995 {
Jamie Madill437fa652016-05-03 15:13:24 -0400996 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 }
999 }
1000
1001 switch (internalformat)
1002 {
1003 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1004 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001005 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 {
Jamie Madill437fa652016-05-03 15:13:24 -04001007 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001008 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001009 }
1010 break;
1011 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001012 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 {
Jamie Madill437fa652016-05-03 15:13:24 -04001014 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001015 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 }
1017 break;
1018 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001019 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Jamie Madill437fa652016-05-03 15:13:24 -04001021 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001025 case GL_ETC1_RGB8_OES:
1026 if (!context->getExtensions().compressedETC1RGB8Texture)
1027 {
Jamie Madill437fa652016-05-03 15:13:24 -04001028 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001029 return false;
1030 }
1031 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001032 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1033 if (!context->getExtensions().lossyETCDecode)
1034 {
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001036 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1037 return false;
1038 }
1039 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 case GL_RGBA32F_EXT:
1041 case GL_RGB32F_EXT:
1042 case GL_ALPHA32F_EXT:
1043 case GL_LUMINANCE32F_EXT:
1044 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001045 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 {
Jamie Madill437fa652016-05-03 15:13:24 -04001047 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001048 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 }
1050 break;
1051 case GL_RGBA16F_EXT:
1052 case GL_RGB16F_EXT:
1053 case GL_ALPHA16F_EXT:
1054 case GL_LUMINANCE16F_EXT:
1055 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001056 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057 {
Jamie Madill437fa652016-05-03 15:13:24 -04001058 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001059 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 }
1061 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001062 case GL_R8_EXT:
1063 case GL_RG8_EXT:
1064 case GL_R16F_EXT:
1065 case GL_RG16F_EXT:
1066 case GL_R32F_EXT:
1067 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001068 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001069 {
Jamie Madill437fa652016-05-03 15:13:24 -04001070 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001071 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001072 }
1073 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 case GL_DEPTH_COMPONENT16:
1075 case GL_DEPTH_COMPONENT32_OES:
1076 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001077 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 {
Jamie Madill437fa652016-05-03 15:13:24 -04001079 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 }
1082 if (target != GL_TEXTURE_2D)
1083 {
Jamie Madill437fa652016-05-03 15:13:24 -04001084 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001085 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 }
1087 // ANGLE_depth_texture only supports 1-level textures
1088 if (levels != 1)
1089 {
Jamie Madill437fa652016-05-03 15:13:24 -04001090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093 break;
1094 default:
1095 break;
1096 }
1097
Geoff Lang691e58c2014-12-19 17:03:25 -05001098 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 if (!texture || texture->id() == 0)
1100 {
Jamie Madill437fa652016-05-03 15:13:24 -04001101 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 }
1104
Geoff Lang69cce582015-09-17 13:20:36 -04001105 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 {
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001108 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001109 }
1110
1111 return true;
1112}
1113
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001114// check for combinations of format and type that are valid for ReadPixels
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001115bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116{
1117 switch (format)
1118 {
1119 case GL_RGBA:
1120 switch (type)
1121 {
1122 case GL_UNSIGNED_BYTE:
1123 break;
1124 default:
1125 return false;
1126 }
1127 break;
1128 case GL_BGRA_EXT:
1129 switch (type)
1130 {
1131 case GL_UNSIGNED_BYTE:
1132 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1133 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1134 break;
1135 default:
1136 return false;
1137 }
1138 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001139 case GL_RG_EXT:
1140 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001141 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001142 {
1143 return false;
1144 }
1145 switch (type)
1146 {
1147 case GL_UNSIGNED_BYTE:
1148 break;
1149 default:
1150 return false;
1151 }
1152 break;
1153
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 default:
1155 return false;
1156 }
1157 return true;
1158}
1159
Austin Kinross08332632015-05-05 13:35:47 -07001160bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1161 const GLenum *attachments)
1162{
Jamie Madillc29968b2016-01-20 11:17:23 -05001163 if (!context->getExtensions().discardFramebuffer)
1164 {
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001166 return false;
1167 }
1168
Austin Kinross08332632015-05-05 13:35:47 -07001169 bool defaultFramebuffer = false;
1170
1171 switch (target)
1172 {
1173 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001174 defaultFramebuffer =
1175 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1176 break;
Austin Kinross08332632015-05-05 13:35:47 -07001177 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001178 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001179 return false;
1180 }
1181
1182 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1183}
1184
Austin Kinrossbc781f32015-10-26 09:27:38 -07001185bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1186{
1187 if (!context->getExtensions().vertexArrayObject)
1188 {
Jamie Madill437fa652016-05-03 15:13:24 -04001189 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001190 return false;
1191 }
1192
1193 return ValidateBindVertexArrayBase(context, array);
1194}
1195
1196bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1197{
1198 if (!context->getExtensions().vertexArrayObject)
1199 {
Jamie Madill437fa652016-05-03 15:13:24 -04001200 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001201 return false;
1202 }
1203
Olli Etuaho41997e72016-03-10 13:38:39 +02001204 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001205}
1206
1207bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1208{
1209 if (!context->getExtensions().vertexArrayObject)
1210 {
Jamie Madill437fa652016-05-03 15:13:24 -04001211 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001212 return false;
1213 }
1214
Olli Etuaho41997e72016-03-10 13:38:39 +02001215 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001216}
1217
1218bool ValidateIsVertexArrayOES(Context *context)
1219{
1220 if (!context->getExtensions().vertexArrayObject)
1221 {
Jamie Madill437fa652016-05-03 15:13:24 -04001222 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001223 return false;
1224 }
1225
1226 return true;
1227}
Geoff Langc5629752015-12-07 16:29:04 -05001228
1229bool ValidateProgramBinaryOES(Context *context,
1230 GLuint program,
1231 GLenum binaryFormat,
1232 const void *binary,
1233 GLint length)
1234{
1235 if (!context->getExtensions().getProgramBinary)
1236 {
Jamie Madill437fa652016-05-03 15:13:24 -04001237 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001238 return false;
1239 }
1240
1241 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1242}
1243
1244bool ValidateGetProgramBinaryOES(Context *context,
1245 GLuint program,
1246 GLsizei bufSize,
1247 GLsizei *length,
1248 GLenum *binaryFormat,
1249 void *binary)
1250{
1251 if (!context->getExtensions().getProgramBinary)
1252 {
Jamie Madill437fa652016-05-03 15:13:24 -04001253 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001254 return false;
1255 }
1256
1257 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1258}
Geoff Lange102fee2015-12-10 11:23:30 -05001259
Geoff Lang70d0f492015-12-10 17:45:46 -05001260static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1261{
1262 switch (source)
1263 {
1264 case GL_DEBUG_SOURCE_API:
1265 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1266 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1267 case GL_DEBUG_SOURCE_OTHER:
1268 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1269 return !mustBeThirdPartyOrApplication;
1270
1271 case GL_DEBUG_SOURCE_THIRD_PARTY:
1272 case GL_DEBUG_SOURCE_APPLICATION:
1273 return true;
1274
1275 default:
1276 return false;
1277 }
1278}
1279
1280static bool ValidDebugType(GLenum type)
1281{
1282 switch (type)
1283 {
1284 case GL_DEBUG_TYPE_ERROR:
1285 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1286 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1287 case GL_DEBUG_TYPE_PERFORMANCE:
1288 case GL_DEBUG_TYPE_PORTABILITY:
1289 case GL_DEBUG_TYPE_OTHER:
1290 case GL_DEBUG_TYPE_MARKER:
1291 case GL_DEBUG_TYPE_PUSH_GROUP:
1292 case GL_DEBUG_TYPE_POP_GROUP:
1293 return true;
1294
1295 default:
1296 return false;
1297 }
1298}
1299
1300static bool ValidDebugSeverity(GLenum severity)
1301{
1302 switch (severity)
1303 {
1304 case GL_DEBUG_SEVERITY_HIGH:
1305 case GL_DEBUG_SEVERITY_MEDIUM:
1306 case GL_DEBUG_SEVERITY_LOW:
1307 case GL_DEBUG_SEVERITY_NOTIFICATION:
1308 return true;
1309
1310 default:
1311 return false;
1312 }
1313}
1314
Geoff Lange102fee2015-12-10 11:23:30 -05001315bool ValidateDebugMessageControlKHR(Context *context,
1316 GLenum source,
1317 GLenum type,
1318 GLenum severity,
1319 GLsizei count,
1320 const GLuint *ids,
1321 GLboolean enabled)
1322{
1323 if (!context->getExtensions().debug)
1324 {
Jamie Madill437fa652016-05-03 15:13:24 -04001325 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001326 return false;
1327 }
1328
Geoff Lang70d0f492015-12-10 17:45:46 -05001329 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1330 {
Jamie Madill437fa652016-05-03 15:13:24 -04001331 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001332 return false;
1333 }
1334
1335 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001338 return false;
1339 }
1340
1341 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1342 {
Jamie Madill437fa652016-05-03 15:13:24 -04001343 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001344 return false;
1345 }
1346
1347 if (count > 0)
1348 {
1349 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1350 {
Jamie Madill437fa652016-05-03 15:13:24 -04001351 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001352 GL_INVALID_OPERATION,
1353 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1354 return false;
1355 }
1356
1357 if (severity != GL_DONT_CARE)
1358 {
Jamie Madill437fa652016-05-03 15:13:24 -04001359 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001360 Error(GL_INVALID_OPERATION,
1361 "If count is greater than zero, severity must be GL_DONT_CARE."));
1362 return false;
1363 }
1364 }
1365
Geoff Lange102fee2015-12-10 11:23:30 -05001366 return true;
1367}
1368
1369bool ValidateDebugMessageInsertKHR(Context *context,
1370 GLenum source,
1371 GLenum type,
1372 GLuint id,
1373 GLenum severity,
1374 GLsizei length,
1375 const GLchar *buf)
1376{
1377 if (!context->getExtensions().debug)
1378 {
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001380 return false;
1381 }
1382
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001383 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001384 {
1385 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1386 // not generate an error.
1387 return false;
1388 }
1389
1390 if (!ValidDebugSeverity(severity))
1391 {
Jamie Madill437fa652016-05-03 15:13:24 -04001392 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001393 return false;
1394 }
1395
1396 if (!ValidDebugType(type))
1397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001399 return false;
1400 }
1401
1402 if (!ValidDebugSource(source, true))
1403 {
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001405 return false;
1406 }
1407
1408 size_t messageLength = (length < 0) ? strlen(buf) : length;
1409 if (messageLength > context->getExtensions().maxDebugMessageLength)
1410 {
Jamie Madill437fa652016-05-03 15:13:24 -04001411 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001412 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1413 return false;
1414 }
1415
Geoff Lange102fee2015-12-10 11:23:30 -05001416 return true;
1417}
1418
1419bool ValidateDebugMessageCallbackKHR(Context *context,
1420 GLDEBUGPROCKHR callback,
1421 const void *userParam)
1422{
1423 if (!context->getExtensions().debug)
1424 {
Jamie Madill437fa652016-05-03 15:13:24 -04001425 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001426 return false;
1427 }
1428
Geoff Lange102fee2015-12-10 11:23:30 -05001429 return true;
1430}
1431
1432bool ValidateGetDebugMessageLogKHR(Context *context,
1433 GLuint count,
1434 GLsizei bufSize,
1435 GLenum *sources,
1436 GLenum *types,
1437 GLuint *ids,
1438 GLenum *severities,
1439 GLsizei *lengths,
1440 GLchar *messageLog)
1441{
1442 if (!context->getExtensions().debug)
1443 {
Jamie Madill437fa652016-05-03 15:13:24 -04001444 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001445 return false;
1446 }
1447
Geoff Lang70d0f492015-12-10 17:45:46 -05001448 if (bufSize < 0 && messageLog != nullptr)
1449 {
Jamie Madill437fa652016-05-03 15:13:24 -04001450 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001451 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1452 return false;
1453 }
1454
Geoff Lange102fee2015-12-10 11:23:30 -05001455 return true;
1456}
1457
1458bool ValidatePushDebugGroupKHR(Context *context,
1459 GLenum source,
1460 GLuint id,
1461 GLsizei length,
1462 const GLchar *message)
1463{
1464 if (!context->getExtensions().debug)
1465 {
Jamie Madill437fa652016-05-03 15:13:24 -04001466 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001467 return false;
1468 }
1469
Geoff Lang70d0f492015-12-10 17:45:46 -05001470 if (!ValidDebugSource(source, true))
1471 {
Jamie Madill437fa652016-05-03 15:13:24 -04001472 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001473 return false;
1474 }
1475
1476 size_t messageLength = (length < 0) ? strlen(message) : length;
1477 if (messageLength > context->getExtensions().maxDebugMessageLength)
1478 {
Jamie Madill437fa652016-05-03 15:13:24 -04001479 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001480 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1481 return false;
1482 }
1483
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001484 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001485 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1486 {
Jamie Madill437fa652016-05-03 15:13:24 -04001487 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001488 Error(GL_STACK_OVERFLOW,
1489 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1490 return false;
1491 }
1492
Geoff Lange102fee2015-12-10 11:23:30 -05001493 return true;
1494}
1495
1496bool ValidatePopDebugGroupKHR(Context *context)
1497{
1498 if (!context->getExtensions().debug)
1499 {
Jamie Madill437fa652016-05-03 15:13:24 -04001500 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001501 return false;
1502 }
1503
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001504 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001505 if (currentStackSize <= 1)
1506 {
Jamie Madill437fa652016-05-03 15:13:24 -04001507 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001508 return false;
1509 }
1510
1511 return true;
1512}
1513
1514static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1515{
1516 switch (identifier)
1517 {
1518 case GL_BUFFER:
1519 if (context->getBuffer(name) == nullptr)
1520 {
Jamie Madill437fa652016-05-03 15:13:24 -04001521 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001522 return false;
1523 }
1524 return true;
1525
1526 case GL_SHADER:
1527 if (context->getShader(name) == nullptr)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001530 return false;
1531 }
1532 return true;
1533
1534 case GL_PROGRAM:
1535 if (context->getProgram(name) == nullptr)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001538 return false;
1539 }
1540 return true;
1541
1542 case GL_VERTEX_ARRAY:
1543 if (context->getVertexArray(name) == nullptr)
1544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001546 return false;
1547 }
1548 return true;
1549
1550 case GL_QUERY:
1551 if (context->getQuery(name) == nullptr)
1552 {
Jamie Madill437fa652016-05-03 15:13:24 -04001553 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001554 return false;
1555 }
1556 return true;
1557
1558 case GL_TRANSFORM_FEEDBACK:
1559 if (context->getTransformFeedback(name) == nullptr)
1560 {
Jamie Madill437fa652016-05-03 15:13:24 -04001561 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001562 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1563 return false;
1564 }
1565 return true;
1566
1567 case GL_SAMPLER:
1568 if (context->getSampler(name) == nullptr)
1569 {
Jamie Madill437fa652016-05-03 15:13:24 -04001570 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001571 return false;
1572 }
1573 return true;
1574
1575 case GL_TEXTURE:
1576 if (context->getTexture(name) == nullptr)
1577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001579 return false;
1580 }
1581 return true;
1582
1583 case GL_RENDERBUFFER:
1584 if (context->getRenderbuffer(name) == nullptr)
1585 {
Jamie Madill437fa652016-05-03 15:13:24 -04001586 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001587 return false;
1588 }
1589 return true;
1590
1591 case GL_FRAMEBUFFER:
1592 if (context->getFramebuffer(name) == nullptr)
1593 {
Jamie Madill437fa652016-05-03 15:13:24 -04001594 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001595 return false;
1596 }
1597 return true;
1598
1599 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001600 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001601 return false;
1602 }
Geoff Lange102fee2015-12-10 11:23:30 -05001603}
1604
Martin Radev9d901792016-07-15 15:58:58 +03001605static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1606{
1607 size_t labelLength = 0;
1608
1609 if (length < 0)
1610 {
1611 if (label != nullptr)
1612 {
1613 labelLength = strlen(label);
1614 }
1615 }
1616 else
1617 {
1618 labelLength = static_cast<size_t>(length);
1619 }
1620
1621 if (labelLength > context->getExtensions().maxLabelLength)
1622 {
1623 context->handleError(
1624 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1625 return false;
1626 }
1627
1628 return true;
1629}
1630
Geoff Lange102fee2015-12-10 11:23:30 -05001631bool ValidateObjectLabelKHR(Context *context,
1632 GLenum identifier,
1633 GLuint name,
1634 GLsizei length,
1635 const GLchar *label)
1636{
1637 if (!context->getExtensions().debug)
1638 {
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001640 return false;
1641 }
1642
Geoff Lang70d0f492015-12-10 17:45:46 -05001643 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1644 {
1645 return false;
1646 }
1647
Martin Radev9d901792016-07-15 15:58:58 +03001648 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001650 return false;
1651 }
1652
Geoff Lange102fee2015-12-10 11:23:30 -05001653 return true;
1654}
1655
1656bool ValidateGetObjectLabelKHR(Context *context,
1657 GLenum identifier,
1658 GLuint name,
1659 GLsizei bufSize,
1660 GLsizei *length,
1661 GLchar *label)
1662{
1663 if (!context->getExtensions().debug)
1664 {
Jamie Madill437fa652016-05-03 15:13:24 -04001665 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001666 return false;
1667 }
1668
Geoff Lang70d0f492015-12-10 17:45:46 -05001669 if (bufSize < 0)
1670 {
Jamie Madill437fa652016-05-03 15:13:24 -04001671 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001672 return false;
1673 }
1674
1675 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1676 {
1677 return false;
1678 }
1679
Martin Radev9d901792016-07-15 15:58:58 +03001680 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001681}
1682
1683static bool ValidateObjectPtrName(Context *context, const void *ptr)
1684{
1685 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1686 {
Jamie Madill437fa652016-05-03 15:13:24 -04001687 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001688 return false;
1689 }
1690
Geoff Lange102fee2015-12-10 11:23:30 -05001691 return true;
1692}
1693
1694bool ValidateObjectPtrLabelKHR(Context *context,
1695 const void *ptr,
1696 GLsizei length,
1697 const GLchar *label)
1698{
1699 if (!context->getExtensions().debug)
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001702 return false;
1703 }
1704
Geoff Lang70d0f492015-12-10 17:45:46 -05001705 if (!ValidateObjectPtrName(context, ptr))
1706 {
1707 return false;
1708 }
1709
Martin Radev9d901792016-07-15 15:58:58 +03001710 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001711 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001712 return false;
1713 }
1714
Geoff Lange102fee2015-12-10 11:23:30 -05001715 return true;
1716}
1717
1718bool ValidateGetObjectPtrLabelKHR(Context *context,
1719 const void *ptr,
1720 GLsizei bufSize,
1721 GLsizei *length,
1722 GLchar *label)
1723{
1724 if (!context->getExtensions().debug)
1725 {
Jamie Madill437fa652016-05-03 15:13:24 -04001726 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001727 return false;
1728 }
1729
Geoff Lang70d0f492015-12-10 17:45:46 -05001730 if (bufSize < 0)
1731 {
Jamie Madill437fa652016-05-03 15:13:24 -04001732 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001733 return false;
1734 }
1735
1736 if (!ValidateObjectPtrName(context, ptr))
1737 {
1738 return false;
1739 }
1740
Martin Radev9d901792016-07-15 15:58:58 +03001741 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001742}
1743
1744bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1745{
1746 if (!context->getExtensions().debug)
1747 {
Jamie Madill437fa652016-05-03 15:13:24 -04001748 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001749 return false;
1750 }
1751
Geoff Lang70d0f492015-12-10 17:45:46 -05001752 // TODO: represent this in Context::getQueryParameterInfo.
1753 switch (pname)
1754 {
1755 case GL_DEBUG_CALLBACK_FUNCTION:
1756 case GL_DEBUG_CALLBACK_USER_PARAM:
1757 break;
1758
1759 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001761 return false;
1762 }
1763
Geoff Lange102fee2015-12-10 11:23:30 -05001764 return true;
1765}
Jamie Madillc29968b2016-01-20 11:17:23 -05001766
1767bool ValidateBlitFramebufferANGLE(Context *context,
1768 GLint srcX0,
1769 GLint srcY0,
1770 GLint srcX1,
1771 GLint srcY1,
1772 GLint dstX0,
1773 GLint dstY0,
1774 GLint dstX1,
1775 GLint dstY1,
1776 GLbitfield mask,
1777 GLenum filter)
1778{
1779 if (!context->getExtensions().framebufferBlit)
1780 {
Jamie Madill437fa652016-05-03 15:13:24 -04001781 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001782 return false;
1783 }
1784
1785 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1786 {
1787 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001789 GL_INVALID_OPERATION,
1790 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1791 return false;
1792 }
1793
1794 if (filter == GL_LINEAR)
1795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001797 return false;
1798 }
1799
Jamie Madill51f40ec2016-06-15 14:06:00 -04001800 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1801 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001802
1803 if (mask & GL_COLOR_BUFFER_BIT)
1804 {
1805 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1806 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1807
1808 if (readColorAttachment && drawColorAttachment)
1809 {
1810 if (!(readColorAttachment->type() == GL_TEXTURE &&
1811 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1812 readColorAttachment->type() != GL_RENDERBUFFER &&
1813 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1814 {
Jamie Madill437fa652016-05-03 15:13:24 -04001815 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 return false;
1817 }
1818
Geoff Langa15472a2015-08-11 11:48:03 -04001819 for (size_t drawbufferIdx = 0;
1820 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001821 {
Geoff Langa15472a2015-08-11 11:48:03 -04001822 const FramebufferAttachment *attachment =
1823 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1824 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001825 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001826 if (!(attachment->type() == GL_TEXTURE &&
1827 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1828 attachment->type() != GL_RENDERBUFFER &&
1829 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1830 {
Jamie Madill437fa652016-05-03 15:13:24 -04001831 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001832 return false;
1833 }
1834
1835 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001836 if (!Format::SameSized(attachment->getFormat(),
1837 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001838 {
Jamie Madill437fa652016-05-03 15:13:24 -04001839 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 return false;
1841 }
1842 }
1843 }
1844
Jamie Madill51f40ec2016-06-15 14:06:00 -04001845 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001846 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1847 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1848 {
Jamie Madill437fa652016-05-03 15:13:24 -04001849 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852 }
1853 }
1854
1855 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1856 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1857 for (size_t i = 0; i < 2; i++)
1858 {
1859 if (mask & masks[i])
1860 {
1861 const FramebufferAttachment *readBuffer =
1862 readFramebuffer->getAttachment(attachments[i]);
1863 const FramebufferAttachment *drawBuffer =
1864 drawFramebuffer->getAttachment(attachments[i]);
1865
1866 if (readBuffer && drawBuffer)
1867 {
1868 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1869 dstX0, dstY0, dstX1, dstY1))
1870 {
1871 // only whole-buffer copies are permitted
1872 ERR(
1873 "Only whole-buffer depth and stencil blits are supported by this "
1874 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001875 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 return false;
1877 }
1878
1879 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001882 return false;
1883 }
1884 }
1885 }
1886 }
1887
1888 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1889 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001890}
Jamie Madillc29968b2016-01-20 11:17:23 -05001891
1892bool ValidateClear(ValidationContext *context, GLbitfield mask)
1893{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001894 auto fbo = context->getGLState().getDrawFramebuffer();
1895 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001896 {
Jamie Madill437fa652016-05-03 15:13:24 -04001897 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001898 return false;
1899 }
1900
1901 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001904 return false;
1905 }
1906
1907 return true;
1908}
1909
1910bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1911{
1912 if (!context->getExtensions().drawBuffers)
1913 {
Jamie Madill437fa652016-05-03 15:13:24 -04001914 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001915 return false;
1916 }
1917
1918 return ValidateDrawBuffersBase(context, n, bufs);
1919}
1920
Jamie Madill73a84962016-02-12 09:27:23 -05001921bool ValidateTexImage2D(Context *context,
1922 GLenum target,
1923 GLint level,
1924 GLint internalformat,
1925 GLsizei width,
1926 GLsizei height,
1927 GLint border,
1928 GLenum format,
1929 GLenum type,
1930 const GLvoid *pixels)
1931{
Martin Radev1be913c2016-07-11 17:59:16 +03001932 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001933 {
1934 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1935 0, 0, width, height, border, format, type, pixels);
1936 }
1937
Martin Radev1be913c2016-07-11 17:59:16 +03001938 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001939 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1940 0, 0, width, height, 1, border, format, type, pixels);
1941}
1942
1943bool ValidateTexSubImage2D(Context *context,
1944 GLenum target,
1945 GLint level,
1946 GLint xoffset,
1947 GLint yoffset,
1948 GLsizei width,
1949 GLsizei height,
1950 GLenum format,
1951 GLenum type,
1952 const GLvoid *pixels)
1953{
1954
Martin Radev1be913c2016-07-11 17:59:16 +03001955 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001956 {
1957 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1958 yoffset, width, height, 0, format, type, pixels);
1959 }
1960
Martin Radev1be913c2016-07-11 17:59:16 +03001961 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001962 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1963 yoffset, 0, width, height, 1, 0, format, type, pixels);
1964}
1965
1966bool ValidateCompressedTexImage2D(Context *context,
1967 GLenum target,
1968 GLint level,
1969 GLenum internalformat,
1970 GLsizei width,
1971 GLsizei height,
1972 GLint border,
1973 GLsizei imageSize,
1974 const GLvoid *data)
1975{
Martin Radev1be913c2016-07-11 17:59:16 +03001976 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001977 {
1978 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1979 0, width, height, border, GL_NONE, GL_NONE, data))
1980 {
1981 return false;
1982 }
1983 }
1984 else
1985 {
Martin Radev1be913c2016-07-11 17:59:16 +03001986 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001987 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1988 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1989 data))
1990 {
1991 return false;
1992 }
1993 }
1994
1995 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001996 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001997 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001998 if (blockSizeOrErr.isError())
1999 {
2000 context->handleError(blockSizeOrErr.getError());
2001 return false;
2002 }
2003
2004 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002007 return false;
2008 }
2009
2010 return true;
2011}
2012
2013bool ValidateCompressedTexSubImage2D(Context *context,
2014 GLenum target,
2015 GLint level,
2016 GLint xoffset,
2017 GLint yoffset,
2018 GLsizei width,
2019 GLsizei height,
2020 GLenum format,
2021 GLsizei imageSize,
2022 const GLvoid *data)
2023{
Martin Radev1be913c2016-07-11 17:59:16 +03002024 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002025 {
2026 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2027 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2028 {
2029 return false;
2030 }
2031 }
2032 else
2033 {
Martin Radev1be913c2016-07-11 17:59:16 +03002034 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002035 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2036 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2037 data))
2038 {
2039 return false;
2040 }
2041 }
2042
2043 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002044 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002045 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002046 if (blockSizeOrErr.isError())
2047 {
2048 context->handleError(blockSizeOrErr.getError());
2049 return false;
2050 }
2051
2052 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002053 {
Jamie Madill437fa652016-05-03 15:13:24 -04002054 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002055 return false;
2056 }
2057
2058 return true;
2059}
2060
Olli Etuaho4f667482016-03-30 15:56:35 +03002061bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2062{
2063 if (!context->getExtensions().mapBuffer)
2064 {
Jamie Madill437fa652016-05-03 15:13:24 -04002065 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002066 return false;
2067 }
2068
2069 return ValidateGetBufferPointervBase(context, target, pname, params);
2070}
2071
2072bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2073{
2074 if (!context->getExtensions().mapBuffer)
2075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002077 return false;
2078 }
2079
2080 if (!ValidBufferTarget(context, target))
2081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002083 return false;
2084 }
2085
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002086 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002087
2088 if (buffer == nullptr)
2089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002091 return false;
2092 }
2093
2094 if (access != GL_WRITE_ONLY_OES)
2095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002097 return false;
2098 }
2099
2100 if (buffer->isMapped())
2101 {
Jamie Madill437fa652016-05-03 15:13:24 -04002102 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002103 return false;
2104 }
2105
2106 return true;
2107}
2108
2109bool ValidateUnmapBufferOES(Context *context, GLenum target)
2110{
2111 if (!context->getExtensions().mapBuffer)
2112 {
Jamie Madill437fa652016-05-03 15:13:24 -04002113 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002114 return false;
2115 }
2116
2117 return ValidateUnmapBufferBase(context, target);
2118}
2119
2120bool ValidateMapBufferRangeEXT(Context *context,
2121 GLenum target,
2122 GLintptr offset,
2123 GLsizeiptr length,
2124 GLbitfield access)
2125{
2126 if (!context->getExtensions().mapBufferRange)
2127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002129 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2130 return false;
2131 }
2132
2133 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2134}
2135
2136bool ValidateFlushMappedBufferRangeEXT(Context *context,
2137 GLenum target,
2138 GLintptr offset,
2139 GLsizeiptr length)
2140{
2141 if (!context->getExtensions().mapBufferRange)
2142 {
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002144 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2145 return false;
2146 }
2147
2148 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2149}
2150
Ian Ewell54f87462016-03-10 13:47:21 -05002151bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2152{
2153 Texture *textureObject = context->getTexture(texture);
2154 if (textureObject && textureObject->getTarget() != target && texture != 0)
2155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002157 return false;
2158 }
2159
2160 switch (target)
2161 {
2162 case GL_TEXTURE_2D:
2163 case GL_TEXTURE_CUBE_MAP:
2164 break;
2165
2166 case GL_TEXTURE_3D:
2167 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002168 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002169 {
Jamie Madill437fa652016-05-03 15:13:24 -04002170 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002171 return false;
2172 }
2173 break;
2174 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002175 if (!context->getExtensions().eglImageExternal &&
2176 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002179 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2180 return false;
2181 }
2182 break;
2183 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002184 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002185 return false;
2186 }
2187
2188 return true;
2189}
2190
Geoff Langd8605522016-04-13 10:19:12 -04002191bool ValidateBindUniformLocationCHROMIUM(Context *context,
2192 GLuint program,
2193 GLint location,
2194 const GLchar *name)
2195{
2196 if (!context->getExtensions().bindUniformLocation)
2197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002199 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2200 return false;
2201 }
2202
2203 Program *programObject = GetValidProgram(context, program);
2204 if (!programObject)
2205 {
2206 return false;
2207 }
2208
2209 if (location < 0)
2210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002212 return false;
2213 }
2214
2215 const Caps &caps = context->getCaps();
2216 if (static_cast<size_t>(location) >=
2217 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002220 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2221 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2222 return false;
2223 }
2224
2225 if (strncmp(name, "gl_", 3) == 0)
2226 {
Jamie Madill437fa652016-05-03 15:13:24 -04002227 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002228 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2229 return false;
2230 }
2231
2232 return true;
2233}
2234
Jamie Madille2e406c2016-06-02 13:04:10 -04002235bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002236{
2237 if (!context->getExtensions().framebufferMixedSamples)
2238 {
2239 context->handleError(
2240 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2241 return false;
2242 }
2243 switch (components)
2244 {
2245 case GL_RGB:
2246 case GL_RGBA:
2247 case GL_ALPHA:
2248 case GL_NONE:
2249 break;
2250 default:
2251 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002252 Error(GL_INVALID_ENUM,
2253 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002254 return false;
2255 }
2256
2257 return true;
2258}
2259
Sami Väisänene45e53b2016-05-25 10:36:04 +03002260// CHROMIUM_path_rendering
2261
2262bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2263{
2264 if (!context->getExtensions().pathRendering)
2265 {
2266 context->handleError(
2267 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2268 return false;
2269 }
2270 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2271 {
2272 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2273 return false;
2274 }
2275 if (matrix == nullptr)
2276 {
2277 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2278 return false;
2279 }
2280 return true;
2281}
2282
2283bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2284{
2285 if (!context->getExtensions().pathRendering)
2286 {
2287 context->handleError(
2288 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2289 return false;
2290 }
2291 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2292 {
2293 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2294 return false;
2295 }
2296 return true;
2297}
2298
2299bool ValidateGenPaths(Context *context, GLsizei range)
2300{
2301 if (!context->getExtensions().pathRendering)
2302 {
2303 context->handleError(
2304 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2305 return false;
2306 }
2307
2308 // range = 0 is undefined in NV_path_rendering.
2309 // we add stricter semantic check here and require a non zero positive range.
2310 if (range <= 0)
2311 {
2312 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2313 return false;
2314 }
2315
2316 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2317 {
2318 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2319 return false;
2320 }
2321
2322 return true;
2323}
2324
2325bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2326{
2327 if (!context->getExtensions().pathRendering)
2328 {
2329 context->handleError(
2330 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2331 return false;
2332 }
2333
2334 // range = 0 is undefined in NV_path_rendering.
2335 // we add stricter semantic check here and require a non zero positive range.
2336 if (range <= 0)
2337 {
2338 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2339 return false;
2340 }
2341
2342 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2343 checkedRange += range;
2344
2345 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2346 {
2347 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2348 return false;
2349 }
2350 return true;
2351}
2352
2353bool ValidatePathCommands(Context *context,
2354 GLuint path,
2355 GLsizei numCommands,
2356 const GLubyte *commands,
2357 GLsizei numCoords,
2358 GLenum coordType,
2359 const void *coords)
2360{
2361 if (!context->getExtensions().pathRendering)
2362 {
2363 context->handleError(
2364 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2365 return false;
2366 }
2367 if (!context->hasPath(path))
2368 {
2369 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2370 return false;
2371 }
2372
2373 if (numCommands < 0)
2374 {
2375 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2376 return false;
2377 }
2378 else if (numCommands > 0)
2379 {
2380 if (!commands)
2381 {
2382 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2383 return false;
2384 }
2385 }
2386
2387 if (numCoords < 0)
2388 {
2389 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2390 return false;
2391 }
2392 else if (numCoords > 0)
2393 {
2394 if (!coords)
2395 {
2396 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2397 return false;
2398 }
2399 }
2400
2401 std::uint32_t coordTypeSize = 0;
2402 switch (coordType)
2403 {
2404 case GL_BYTE:
2405 coordTypeSize = sizeof(GLbyte);
2406 break;
2407
2408 case GL_UNSIGNED_BYTE:
2409 coordTypeSize = sizeof(GLubyte);
2410 break;
2411
2412 case GL_SHORT:
2413 coordTypeSize = sizeof(GLshort);
2414 break;
2415
2416 case GL_UNSIGNED_SHORT:
2417 coordTypeSize = sizeof(GLushort);
2418 break;
2419
2420 case GL_FLOAT:
2421 coordTypeSize = sizeof(GLfloat);
2422 break;
2423
2424 default:
2425 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2426 return false;
2427 }
2428
2429 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2430 checkedSize += (coordTypeSize * numCoords);
2431 if (!checkedSize.IsValid())
2432 {
2433 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2434 return false;
2435 }
2436
2437 // early return skips command data validation when it doesn't exist.
2438 if (!commands)
2439 return true;
2440
2441 GLsizei expectedNumCoords = 0;
2442 for (GLsizei i = 0; i < numCommands; ++i)
2443 {
2444 switch (commands[i])
2445 {
2446 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2447 break;
2448 case GL_MOVE_TO_CHROMIUM:
2449 case GL_LINE_TO_CHROMIUM:
2450 expectedNumCoords += 2;
2451 break;
2452 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2453 expectedNumCoords += 4;
2454 break;
2455 case GL_CUBIC_CURVE_TO_CHROMIUM:
2456 expectedNumCoords += 6;
2457 break;
2458 case GL_CONIC_CURVE_TO_CHROMIUM:
2459 expectedNumCoords += 5;
2460 break;
2461 default:
2462 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2463 return false;
2464 }
2465 }
2466 if (expectedNumCoords != numCoords)
2467 {
2468 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2469 return false;
2470 }
2471
2472 return true;
2473}
2474
2475bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2476{
2477 if (!context->getExtensions().pathRendering)
2478 {
2479 context->handleError(
2480 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2481 return false;
2482 }
2483 if (!context->hasPath(path))
2484 {
2485 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2486 return false;
2487 }
2488
2489 switch (pname)
2490 {
2491 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2492 if (value < 0.0f)
2493 {
2494 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2495 return false;
2496 }
2497 break;
2498 case GL_PATH_END_CAPS_CHROMIUM:
2499 switch (static_cast<GLenum>(value))
2500 {
2501 case GL_FLAT_CHROMIUM:
2502 case GL_SQUARE_CHROMIUM:
2503 case GL_ROUND_CHROMIUM:
2504 break;
2505 default:
2506 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2507 return false;
2508 }
2509 break;
2510 case GL_PATH_JOIN_STYLE_CHROMIUM:
2511 switch (static_cast<GLenum>(value))
2512 {
2513 case GL_MITER_REVERT_CHROMIUM:
2514 case GL_BEVEL_CHROMIUM:
2515 case GL_ROUND_CHROMIUM:
2516 break;
2517 default:
2518 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2519 return false;
2520 }
2521 case GL_PATH_MITER_LIMIT_CHROMIUM:
2522 if (value < 0.0f)
2523 {
2524 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2525 return false;
2526 }
2527 break;
2528
2529 case GL_PATH_STROKE_BOUND_CHROMIUM:
2530 // no errors, only clamping.
2531 break;
2532
2533 default:
2534 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2535 return false;
2536 }
2537 return true;
2538}
2539
2540bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2541{
2542 if (!context->getExtensions().pathRendering)
2543 {
2544 context->handleError(
2545 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2546 return false;
2547 }
2548
2549 if (!context->hasPath(path))
2550 {
2551 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2552 return false;
2553 }
2554 if (!value)
2555 {
2556 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2557 return false;
2558 }
2559
2560 switch (pname)
2561 {
2562 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2563 case GL_PATH_END_CAPS_CHROMIUM:
2564 case GL_PATH_JOIN_STYLE_CHROMIUM:
2565 case GL_PATH_MITER_LIMIT_CHROMIUM:
2566 case GL_PATH_STROKE_BOUND_CHROMIUM:
2567 break;
2568
2569 default:
2570 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2571 return false;
2572 }
2573
2574 return true;
2575}
2576
2577bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2578{
2579 if (!context->getExtensions().pathRendering)
2580 {
2581 context->handleError(
2582 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2583 return false;
2584 }
2585
2586 switch (func)
2587 {
2588 case GL_NEVER:
2589 case GL_ALWAYS:
2590 case GL_LESS:
2591 case GL_LEQUAL:
2592 case GL_EQUAL:
2593 case GL_GEQUAL:
2594 case GL_GREATER:
2595 case GL_NOTEQUAL:
2596 break;
2597 default:
2598 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2599 return false;
2600 }
2601
2602 return true;
2603}
2604
2605// Note that the spec specifies that for the path drawing commands
2606// if the path object is not an existing path object the command
2607// does nothing and no error is generated.
2608// However if the path object exists but has not been specified any
2609// commands then an error is generated.
2610
2611bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2612{
2613 if (!context->getExtensions().pathRendering)
2614 {
2615 context->handleError(
2616 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2617 return false;
2618 }
2619 if (context->hasPath(path) && !context->hasPathData(path))
2620 {
2621 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2622 return false;
2623 }
2624
2625 switch (fillMode)
2626 {
2627 case GL_COUNT_UP_CHROMIUM:
2628 case GL_COUNT_DOWN_CHROMIUM:
2629 break;
2630 default:
2631 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2632 return false;
2633 }
2634
2635 if (!isPow2(mask + 1))
2636 {
2637 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2638 return false;
2639 }
2640
2641 return true;
2642}
2643
2644bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2645{
2646 if (!context->getExtensions().pathRendering)
2647 {
2648 context->handleError(
2649 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2650 return false;
2651 }
2652 if (context->hasPath(path) && !context->hasPathData(path))
2653 {
2654 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2655 return false;
2656 }
2657
2658 return true;
2659}
2660
2661bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2662{
2663 if (!context->getExtensions().pathRendering)
2664 {
2665 context->handleError(
2666 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2667 return false;
2668 }
2669 if (context->hasPath(path) && !context->hasPathData(path))
2670 {
2671 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2672 return false;
2673 }
2674
2675 switch (coverMode)
2676 {
2677 case GL_CONVEX_HULL_CHROMIUM:
2678 case GL_BOUNDING_BOX_CHROMIUM:
2679 break;
2680 default:
2681 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2682 return false;
2683 }
2684 return true;
2685}
2686
2687bool ValidateStencilThenCoverFillPath(Context *context,
2688 GLuint path,
2689 GLenum fillMode,
2690 GLuint mask,
2691 GLenum coverMode)
2692{
2693 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2694 ValidateCoverPath(context, path, coverMode);
2695}
2696
2697bool ValidateStencilThenCoverStrokePath(Context *context,
2698 GLuint path,
2699 GLint reference,
2700 GLuint mask,
2701 GLenum coverMode)
2702{
2703 return ValidateStencilStrokePath(context, path, reference, mask) &&
2704 ValidateCoverPath(context, path, coverMode);
2705}
2706
2707bool ValidateIsPath(Context *context)
2708{
2709 if (!context->getExtensions().pathRendering)
2710 {
2711 context->handleError(
2712 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2713 return false;
2714 }
2715 return true;
2716}
2717
Sami Väisänend59ca052016-06-21 16:10:00 +03002718bool ValidateCoverFillPathInstanced(Context *context,
2719 GLsizei numPaths,
2720 GLenum pathNameType,
2721 const void *paths,
2722 GLuint pathBase,
2723 GLenum coverMode,
2724 GLenum transformType,
2725 const GLfloat *transformValues)
2726{
2727 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2728 transformType, transformValues))
2729 return false;
2730
2731 switch (coverMode)
2732 {
2733 case GL_CONVEX_HULL_CHROMIUM:
2734 case GL_BOUNDING_BOX_CHROMIUM:
2735 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2736 break;
2737 default:
2738 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2739 return false;
2740 }
2741
2742 return true;
2743}
2744
2745bool ValidateCoverStrokePathInstanced(Context *context,
2746 GLsizei numPaths,
2747 GLenum pathNameType,
2748 const void *paths,
2749 GLuint pathBase,
2750 GLenum coverMode,
2751 GLenum transformType,
2752 const GLfloat *transformValues)
2753{
2754 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2755 transformType, transformValues))
2756 return false;
2757
2758 switch (coverMode)
2759 {
2760 case GL_CONVEX_HULL_CHROMIUM:
2761 case GL_BOUNDING_BOX_CHROMIUM:
2762 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2763 break;
2764 default:
2765 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2766 return false;
2767 }
2768
2769 return true;
2770}
2771
2772bool ValidateStencilFillPathInstanced(Context *context,
2773 GLsizei numPaths,
2774 GLenum pathNameType,
2775 const void *paths,
2776 GLuint pathBase,
2777 GLenum fillMode,
2778 GLuint mask,
2779 GLenum transformType,
2780 const GLfloat *transformValues)
2781{
2782
2783 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2784 transformType, transformValues))
2785 return false;
2786
2787 switch (fillMode)
2788 {
2789 case GL_COUNT_UP_CHROMIUM:
2790 case GL_COUNT_DOWN_CHROMIUM:
2791 break;
2792 default:
2793 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2794 return false;
2795 }
2796 if (!isPow2(mask + 1))
2797 {
2798 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2799 return false;
2800 }
2801 return true;
2802}
2803
2804bool ValidateStencilStrokePathInstanced(Context *context,
2805 GLsizei numPaths,
2806 GLenum pathNameType,
2807 const void *paths,
2808 GLuint pathBase,
2809 GLint reference,
2810 GLuint mask,
2811 GLenum transformType,
2812 const GLfloat *transformValues)
2813{
2814 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2815 transformType, transformValues))
2816 return false;
2817
2818 // no more validation here.
2819
2820 return true;
2821}
2822
2823bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2824 GLsizei numPaths,
2825 GLenum pathNameType,
2826 const void *paths,
2827 GLuint pathBase,
2828 GLenum fillMode,
2829 GLuint mask,
2830 GLenum coverMode,
2831 GLenum transformType,
2832 const GLfloat *transformValues)
2833{
2834 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2835 transformType, transformValues))
2836 return false;
2837
2838 switch (coverMode)
2839 {
2840 case GL_CONVEX_HULL_CHROMIUM:
2841 case GL_BOUNDING_BOX_CHROMIUM:
2842 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2843 break;
2844 default:
2845 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2846 return false;
2847 }
2848
2849 switch (fillMode)
2850 {
2851 case GL_COUNT_UP_CHROMIUM:
2852 case GL_COUNT_DOWN_CHROMIUM:
2853 break;
2854 default:
2855 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2856 return false;
2857 }
2858 if (!isPow2(mask + 1))
2859 {
2860 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2861 return false;
2862 }
2863
2864 return true;
2865}
2866
2867bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2868 GLsizei numPaths,
2869 GLenum pathNameType,
2870 const void *paths,
2871 GLuint pathBase,
2872 GLint reference,
2873 GLuint mask,
2874 GLenum coverMode,
2875 GLenum transformType,
2876 const GLfloat *transformValues)
2877{
2878 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2879 transformType, transformValues))
2880 return false;
2881
2882 switch (coverMode)
2883 {
2884 case GL_CONVEX_HULL_CHROMIUM:
2885 case GL_BOUNDING_BOX_CHROMIUM:
2886 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2887 break;
2888 default:
2889 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2890 return false;
2891 }
2892
2893 return true;
2894}
2895
Sami Väisänen46eaa942016-06-29 10:26:37 +03002896bool ValidateBindFragmentInputLocation(Context *context,
2897 GLuint program,
2898 GLint location,
2899 const GLchar *name)
2900{
2901 if (!context->getExtensions().pathRendering)
2902 {
2903 context->handleError(
2904 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2905 return false;
2906 }
2907
2908 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2909 if (location >= MaxLocation)
2910 {
2911 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2912 return false;
2913 }
2914
2915 const auto *programObject = context->getProgram(program);
2916 if (!programObject)
2917 {
2918 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2919 return false;
2920 }
2921
2922 if (!name)
2923 {
2924 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2925 return false;
2926 }
2927
2928 if (angle::BeginsWith(name, "gl_"))
2929 {
2930 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2931 return false;
2932 }
2933
2934 return true;
2935}
2936
2937bool ValidateProgramPathFragmentInputGen(Context *context,
2938 GLuint program,
2939 GLint location,
2940 GLenum genMode,
2941 GLint components,
2942 const GLfloat *coeffs)
2943{
2944 if (!context->getExtensions().pathRendering)
2945 {
2946 context->handleError(
2947 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2948 return false;
2949 }
2950
2951 const auto *programObject = context->getProgram(program);
2952 if (!programObject || programObject->isFlaggedForDeletion())
2953 {
2954 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2955 return false;
2956 }
2957
2958 if (!programObject->isLinked())
2959 {
2960 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2961 return false;
2962 }
2963
2964 switch (genMode)
2965 {
2966 case GL_NONE:
2967 if (components != 0)
2968 {
2969 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2970 return false;
2971 }
2972 break;
2973
2974 case GL_OBJECT_LINEAR_CHROMIUM:
2975 case GL_EYE_LINEAR_CHROMIUM:
2976 case GL_CONSTANT_CHROMIUM:
2977 if (components < 1 || components > 4)
2978 {
2979 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2980 return false;
2981 }
2982 if (!coeffs)
2983 {
2984 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2985 return false;
2986 }
2987 break;
2988
2989 default:
2990 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2991 return false;
2992 }
2993
2994 // If the location is -1 then the command is silently ignored
2995 // and no further validation is needed.
2996 if (location == -1)
2997 return true;
2998
2999 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3000
3001 if (!binding.valid)
3002 {
3003 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3004 return false;
3005 }
3006
3007 if (binding.type != GL_NONE)
3008 {
3009 GLint expectedComponents = 0;
3010 switch (binding.type)
3011 {
3012 case GL_FLOAT:
3013 expectedComponents = 1;
3014 break;
3015 case GL_FLOAT_VEC2:
3016 expectedComponents = 2;
3017 break;
3018 case GL_FLOAT_VEC3:
3019 expectedComponents = 3;
3020 break;
3021 case GL_FLOAT_VEC4:
3022 expectedComponents = 4;
3023 break;
3024 default:
3025 context->handleError(Error(GL_INVALID_OPERATION,
3026 "Fragment input type is not a floating point scalar or vector."));
3027 return false;
3028 }
3029 if (expectedComponents != components && genMode != GL_NONE)
3030 {
3031 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3032 return false;
3033 }
3034 }
3035 return true;
3036}
3037
Jamie Madillc29968b2016-01-20 11:17:23 -05003038} // namespace gl