blob: c25d1e5b650ae06649159c5ce73d5cd89fc80d78 [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{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500633 if (!ValidTexture2DDestinationTarget(context, target))
634 {
Jamie Madill437fa652016-05-03 15:13:24 -0400635 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500636 return false;
637 }
638
Jamie Madill0c8abca2016-07-22 20:21:26 -0400639 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400640 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400641 xoffset, yoffset, 0, x, y, width, height, border,
642 &textureFormat))
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 Madill0c8abca2016-07-22 20:21:26 -0400649 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650
651 // [OpenGL ES 2.0.24] table 3.9
652 if (isSubImage)
653 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400654 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400655 {
656 case GL_ALPHA:
657 if (colorbufferFormat != GL_ALPHA8_EXT &&
658 colorbufferFormat != GL_RGBA4 &&
659 colorbufferFormat != GL_RGB5_A1 &&
660 colorbufferFormat != GL_RGBA8_OES)
661 {
Jamie Madill437fa652016-05-03 15:13:24 -0400662 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400663 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664 }
665 break;
666 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400667 if (colorbufferFormat != GL_R8_EXT &&
668 colorbufferFormat != GL_RG8_EXT &&
669 colorbufferFormat != GL_RGB565 &&
670 colorbufferFormat != GL_RGB8_OES &&
671 colorbufferFormat != GL_RGBA4 &&
672 colorbufferFormat != GL_RGB5_A1 &&
673 colorbufferFormat != GL_RGBA8_OES)
674 {
Jamie Madill437fa652016-05-03 15:13:24 -0400675 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400676 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400677 }
678 break;
679 case GL_RED_EXT:
680 if (colorbufferFormat != GL_R8_EXT &&
681 colorbufferFormat != GL_RG8_EXT &&
682 colorbufferFormat != GL_RGB565 &&
683 colorbufferFormat != GL_RGB8_OES &&
684 colorbufferFormat != GL_RGBA4 &&
685 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500686 colorbufferFormat != GL_RGBA8_OES &&
687 colorbufferFormat != GL_R32F &&
688 colorbufferFormat != GL_RG32F &&
689 colorbufferFormat != GL_RGB32F &&
690 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400691 {
Jamie Madill437fa652016-05-03 15:13:24 -0400692 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400693 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400694 }
695 break;
696 case GL_RG_EXT:
697 if (colorbufferFormat != GL_RG8_EXT &&
698 colorbufferFormat != GL_RGB565 &&
699 colorbufferFormat != GL_RGB8_OES &&
700 colorbufferFormat != GL_RGBA4 &&
701 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500702 colorbufferFormat != GL_RGBA8_OES &&
703 colorbufferFormat != GL_RG32F &&
704 colorbufferFormat != GL_RGB32F &&
705 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400706 {
Jamie Madill437fa652016-05-03 15:13:24 -0400707 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400708 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400709 }
710 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400711 case GL_RGB:
712 if (colorbufferFormat != GL_RGB565 &&
713 colorbufferFormat != GL_RGB8_OES &&
714 colorbufferFormat != GL_RGBA4 &&
715 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500716 colorbufferFormat != GL_RGBA8_OES &&
717 colorbufferFormat != GL_RGB32F &&
718 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 {
Jamie Madill437fa652016-05-03 15:13:24 -0400720 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400721 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 }
723 break;
724 case GL_LUMINANCE_ALPHA:
725 case GL_RGBA:
726 if (colorbufferFormat != GL_RGBA4 &&
727 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500728 colorbufferFormat != GL_RGBA8_OES &&
729 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400730 {
Jamie Madill437fa652016-05-03 15:13:24 -0400731 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400732 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 }
734 break;
735 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
736 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
737 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
738 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400739 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800740 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400741 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400742 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400743 case GL_DEPTH_COMPONENT:
744 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400745 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400748 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400749 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400750 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500751
Jamie Madill0c8abca2016-07-22 20:21:26 -0400752 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500753 {
Jamie Madill437fa652016-05-03 15:13:24 -0400754 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500755 return false;
756 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400757 }
758 else
759 {
760 switch (internalformat)
761 {
762 case GL_ALPHA:
763 if (colorbufferFormat != GL_ALPHA8_EXT &&
764 colorbufferFormat != GL_RGBA4 &&
765 colorbufferFormat != GL_RGB5_A1 &&
766 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500767 colorbufferFormat != GL_RGBA8_OES &&
768 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400769 {
Jamie Madill437fa652016-05-03 15:13:24 -0400770 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400771 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 }
773 break;
774 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400775 if (colorbufferFormat != GL_R8_EXT &&
776 colorbufferFormat != GL_RG8_EXT &&
777 colorbufferFormat != GL_RGB565 &&
778 colorbufferFormat != GL_RGB8_OES &&
779 colorbufferFormat != GL_RGBA4 &&
780 colorbufferFormat != GL_RGB5_A1 &&
781 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500782 colorbufferFormat != GL_RGBA8_OES &&
783 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400784 {
Jamie Madill437fa652016-05-03 15:13:24 -0400785 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400786 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400787 }
788 break;
789 case GL_RED_EXT:
790 if (colorbufferFormat != GL_R8_EXT &&
791 colorbufferFormat != GL_RG8_EXT &&
792 colorbufferFormat != GL_RGB565 &&
793 colorbufferFormat != GL_RGB8_OES &&
794 colorbufferFormat != GL_RGBA4 &&
795 colorbufferFormat != GL_RGB5_A1 &&
796 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500797 colorbufferFormat != GL_RGBA8_OES &&
798 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400799 {
Jamie Madill437fa652016-05-03 15:13:24 -0400800 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400802 }
803 break;
804 case GL_RG_EXT:
805 if (colorbufferFormat != GL_RG8_EXT &&
806 colorbufferFormat != GL_RGB565 &&
807 colorbufferFormat != GL_RGB8_OES &&
808 colorbufferFormat != GL_RGBA4 &&
809 colorbufferFormat != GL_RGB5_A1 &&
810 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500811 colorbufferFormat != GL_RGBA8_OES &&
812 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400813 {
Jamie Madill437fa652016-05-03 15:13:24 -0400814 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400815 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400816 }
817 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 case GL_RGB:
819 if (colorbufferFormat != GL_RGB565 &&
820 colorbufferFormat != GL_RGB8_OES &&
821 colorbufferFormat != GL_RGBA4 &&
822 colorbufferFormat != GL_RGB5_A1 &&
823 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500824 colorbufferFormat != GL_RGBA8_OES &&
825 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 {
Jamie Madill437fa652016-05-03 15:13:24 -0400827 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400828 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 }
830 break;
831 case GL_LUMINANCE_ALPHA:
832 case GL_RGBA:
833 if (colorbufferFormat != GL_RGBA4 &&
834 colorbufferFormat != GL_RGB5_A1 &&
835 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500836 colorbufferFormat != GL_RGBA8_OES &&
837 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 {
Jamie Madill437fa652016-05-03 15:13:24 -0400839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 }
842 break;
843 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
844 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400845 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 {
Jamie Madill437fa652016-05-03 15:13:24 -0400847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 }
850 else
851 {
Jamie Madill437fa652016-05-03 15:13:24 -0400852 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400853 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 }
855 break;
856 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400857 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 {
Jamie Madill437fa652016-05-03 15:13:24 -0400859 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400860 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 }
862 else
863 {
Jamie Madill437fa652016-05-03 15:13:24 -0400864 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400865 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 }
867 break;
868 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400869 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870 {
Jamie Madill437fa652016-05-03 15:13:24 -0400871 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400872 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400873 }
874 else
875 {
Jamie Madill437fa652016-05-03 15:13:24 -0400876 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400878 }
879 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400880 case GL_ETC1_RGB8_OES:
881 if (context->getExtensions().compressedETC1RGB8Texture)
882 {
Jamie Madill437fa652016-05-03 15:13:24 -0400883 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400884 return false;
885 }
886 else
887 {
Jamie Madill437fa652016-05-03 15:13:24 -0400888 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400889 return false;
890 }
891 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800892 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
893 if (context->getExtensions().lossyETCDecode)
894 {
Jamie Madill437fa652016-05-03 15:13:24 -0400895 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800896 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
897 return false;
898 }
899 else
900 {
Jamie Madill437fa652016-05-03 15:13:24 -0400901 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800902 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
903 return false;
904 }
905 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400906 case GL_DEPTH_COMPONENT:
907 case GL_DEPTH_COMPONENT16:
908 case GL_DEPTH_COMPONENT32_OES:
909 case GL_DEPTH_STENCIL_OES:
910 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400911 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 {
Jamie Madill437fa652016-05-03 15:13:24 -0400913 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400914 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 }
916 else
917 {
Jamie Madill437fa652016-05-03 15:13:24 -0400918 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400919 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 }
921 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
925 }
926
Geoff Lang784a8fd2013-09-24 12:33:16 -0400927 // If width or height is zero, it is a no-op. Return false without setting an error.
928 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929}
930
Geoff Langb1196682014-07-23 13:47:29 -0400931bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400932 GLsizei width, GLsizei height)
933{
934 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
935 {
Jamie Madill437fa652016-05-03 15:13:24 -0400936 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400937 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400938 }
939
940 if (width < 1 || height < 1 || levels < 1)
941 {
Jamie Madill437fa652016-05-03 15:13:24 -0400942 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945
946 if (target == GL_TEXTURE_CUBE_MAP && width != height)
947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 }
951
952 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 }
957
Geoff Lang5d601382014-07-22 15:14:06 -0400958 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
959 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 {
Jamie Madill437fa652016-05-03 15:13:24 -0400961 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 }
964
Geoff Langaae65a42014-05-26 12:43:44 -0400965 const gl::Caps &caps = context->getCaps();
966
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 switch (target)
968 {
969 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400970 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
971 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972 {
Jamie Madill437fa652016-05-03 15:13:24 -0400973 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 }
976 break;
977 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400978 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
979 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 {
Jamie Madill437fa652016-05-03 15:13:24 -0400981 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 }
984 break;
985 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400986 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400988 }
989
Geoff Langc0b9ef42014-07-02 10:02:37 -0400990 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400991 {
992 if (!gl::isPow2(width) || !gl::isPow2(height))
993 {
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 }
997 }
998
999 switch (internalformat)
1000 {
1001 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1002 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001003 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 {
Jamie Madill437fa652016-05-03 15:13:24 -04001005 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001006 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 }
1008 break;
1009 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001010 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 {
Jamie Madill437fa652016-05-03 15:13:24 -04001012 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 }
1015 break;
1016 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001017 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001018 {
Jamie Madill437fa652016-05-03 15:13:24 -04001019 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021 }
1022 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001023 case GL_ETC1_RGB8_OES:
1024 if (!context->getExtensions().compressedETC1RGB8Texture)
1025 {
Jamie Madill437fa652016-05-03 15:13:24 -04001026 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001027 return false;
1028 }
1029 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001030 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1031 if (!context->getExtensions().lossyETCDecode)
1032 {
Jamie Madill437fa652016-05-03 15:13:24 -04001033 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001034 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1035 return false;
1036 }
1037 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 case GL_RGBA32F_EXT:
1039 case GL_RGB32F_EXT:
1040 case GL_ALPHA32F_EXT:
1041 case GL_LUMINANCE32F_EXT:
1042 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001043 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001044 {
Jamie Madill437fa652016-05-03 15:13:24 -04001045 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001046 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 }
1048 break;
1049 case GL_RGBA16F_EXT:
1050 case GL_RGB16F_EXT:
1051 case GL_ALPHA16F_EXT:
1052 case GL_LUMINANCE16F_EXT:
1053 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001054 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 {
Jamie Madill437fa652016-05-03 15:13:24 -04001056 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 }
1059 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001060 case GL_R8_EXT:
1061 case GL_RG8_EXT:
1062 case GL_R16F_EXT:
1063 case GL_RG16F_EXT:
1064 case GL_R32F_EXT:
1065 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001066 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001067 {
Jamie Madill437fa652016-05-03 15:13:24 -04001068 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001069 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001070 }
1071 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001072 case GL_DEPTH_COMPONENT16:
1073 case GL_DEPTH_COMPONENT32_OES:
1074 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001075 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 {
Jamie Madill437fa652016-05-03 15:13:24 -04001077 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 }
1080 if (target != GL_TEXTURE_2D)
1081 {
Jamie Madill437fa652016-05-03 15:13:24 -04001082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001084 }
1085 // ANGLE_depth_texture only supports 1-level textures
1086 if (levels != 1)
1087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 }
1091 break;
1092 default:
1093 break;
1094 }
1095
Geoff Lang691e58c2014-12-19 17:03:25 -05001096 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 if (!texture || texture->id() == 0)
1098 {
Jamie Madill437fa652016-05-03 15:13:24 -04001099 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001100 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 }
1102
Geoff Lang69cce582015-09-17 13:20:36 -04001103 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 {
Jamie Madill437fa652016-05-03 15:13:24 -04001105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
1109 return true;
1110}
1111
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112// check for combinations of format and type that are valid for ReadPixels
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001113bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001114{
1115 switch (format)
1116 {
1117 case GL_RGBA:
1118 switch (type)
1119 {
1120 case GL_UNSIGNED_BYTE:
1121 break;
1122 default:
1123 return false;
1124 }
1125 break;
1126 case GL_BGRA_EXT:
1127 switch (type)
1128 {
1129 case GL_UNSIGNED_BYTE:
1130 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1131 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1132 break;
1133 default:
1134 return false;
1135 }
1136 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001137 case GL_RG_EXT:
1138 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001139 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001140 {
1141 return false;
1142 }
1143 switch (type)
1144 {
1145 case GL_UNSIGNED_BYTE:
1146 break;
1147 default:
1148 return false;
1149 }
1150 break;
1151
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001152 default:
1153 return false;
1154 }
1155 return true;
1156}
1157
Austin Kinross08332632015-05-05 13:35:47 -07001158bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1159 const GLenum *attachments)
1160{
Jamie Madillc29968b2016-01-20 11:17:23 -05001161 if (!context->getExtensions().discardFramebuffer)
1162 {
Jamie Madill437fa652016-05-03 15:13:24 -04001163 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001164 return false;
1165 }
1166
Austin Kinross08332632015-05-05 13:35:47 -07001167 bool defaultFramebuffer = false;
1168
1169 switch (target)
1170 {
1171 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001172 defaultFramebuffer =
1173 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1174 break;
Austin Kinross08332632015-05-05 13:35:47 -07001175 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001177 return false;
1178 }
1179
1180 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1181}
1182
Austin Kinrossbc781f32015-10-26 09:27:38 -07001183bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1184{
1185 if (!context->getExtensions().vertexArrayObject)
1186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001188 return false;
1189 }
1190
1191 return ValidateBindVertexArrayBase(context, array);
1192}
1193
1194bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1195{
1196 if (!context->getExtensions().vertexArrayObject)
1197 {
Jamie Madill437fa652016-05-03 15:13:24 -04001198 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001199 return false;
1200 }
1201
Olli Etuaho41997e72016-03-10 13:38:39 +02001202 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001203}
1204
1205bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1206{
1207 if (!context->getExtensions().vertexArrayObject)
1208 {
Jamie Madill437fa652016-05-03 15:13:24 -04001209 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001210 return false;
1211 }
1212
Olli Etuaho41997e72016-03-10 13:38:39 +02001213 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001214}
1215
1216bool ValidateIsVertexArrayOES(Context *context)
1217{
1218 if (!context->getExtensions().vertexArrayObject)
1219 {
Jamie Madill437fa652016-05-03 15:13:24 -04001220 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001221 return false;
1222 }
1223
1224 return true;
1225}
Geoff Langc5629752015-12-07 16:29:04 -05001226
1227bool ValidateProgramBinaryOES(Context *context,
1228 GLuint program,
1229 GLenum binaryFormat,
1230 const void *binary,
1231 GLint length)
1232{
1233 if (!context->getExtensions().getProgramBinary)
1234 {
Jamie Madill437fa652016-05-03 15:13:24 -04001235 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001236 return false;
1237 }
1238
1239 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1240}
1241
1242bool ValidateGetProgramBinaryOES(Context *context,
1243 GLuint program,
1244 GLsizei bufSize,
1245 GLsizei *length,
1246 GLenum *binaryFormat,
1247 void *binary)
1248{
1249 if (!context->getExtensions().getProgramBinary)
1250 {
Jamie Madill437fa652016-05-03 15:13:24 -04001251 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001252 return false;
1253 }
1254
1255 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1256}
Geoff Lange102fee2015-12-10 11:23:30 -05001257
Geoff Lang70d0f492015-12-10 17:45:46 -05001258static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1259{
1260 switch (source)
1261 {
1262 case GL_DEBUG_SOURCE_API:
1263 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1264 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1265 case GL_DEBUG_SOURCE_OTHER:
1266 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1267 return !mustBeThirdPartyOrApplication;
1268
1269 case GL_DEBUG_SOURCE_THIRD_PARTY:
1270 case GL_DEBUG_SOURCE_APPLICATION:
1271 return true;
1272
1273 default:
1274 return false;
1275 }
1276}
1277
1278static bool ValidDebugType(GLenum type)
1279{
1280 switch (type)
1281 {
1282 case GL_DEBUG_TYPE_ERROR:
1283 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1284 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1285 case GL_DEBUG_TYPE_PERFORMANCE:
1286 case GL_DEBUG_TYPE_PORTABILITY:
1287 case GL_DEBUG_TYPE_OTHER:
1288 case GL_DEBUG_TYPE_MARKER:
1289 case GL_DEBUG_TYPE_PUSH_GROUP:
1290 case GL_DEBUG_TYPE_POP_GROUP:
1291 return true;
1292
1293 default:
1294 return false;
1295 }
1296}
1297
1298static bool ValidDebugSeverity(GLenum severity)
1299{
1300 switch (severity)
1301 {
1302 case GL_DEBUG_SEVERITY_HIGH:
1303 case GL_DEBUG_SEVERITY_MEDIUM:
1304 case GL_DEBUG_SEVERITY_LOW:
1305 case GL_DEBUG_SEVERITY_NOTIFICATION:
1306 return true;
1307
1308 default:
1309 return false;
1310 }
1311}
1312
Geoff Lange102fee2015-12-10 11:23:30 -05001313bool ValidateDebugMessageControlKHR(Context *context,
1314 GLenum source,
1315 GLenum type,
1316 GLenum severity,
1317 GLsizei count,
1318 const GLuint *ids,
1319 GLboolean enabled)
1320{
1321 if (!context->getExtensions().debug)
1322 {
Jamie Madill437fa652016-05-03 15:13:24 -04001323 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001324 return false;
1325 }
1326
Geoff Lang70d0f492015-12-10 17:45:46 -05001327 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001330 return false;
1331 }
1332
1333 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1334 {
Jamie Madill437fa652016-05-03 15:13:24 -04001335 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001336 return false;
1337 }
1338
1339 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1340 {
Jamie Madill437fa652016-05-03 15:13:24 -04001341 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001342 return false;
1343 }
1344
1345 if (count > 0)
1346 {
1347 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1348 {
Jamie Madill437fa652016-05-03 15:13:24 -04001349 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001350 GL_INVALID_OPERATION,
1351 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1352 return false;
1353 }
1354
1355 if (severity != GL_DONT_CARE)
1356 {
Jamie Madill437fa652016-05-03 15:13:24 -04001357 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001358 Error(GL_INVALID_OPERATION,
1359 "If count is greater than zero, severity must be GL_DONT_CARE."));
1360 return false;
1361 }
1362 }
1363
Geoff Lange102fee2015-12-10 11:23:30 -05001364 return true;
1365}
1366
1367bool ValidateDebugMessageInsertKHR(Context *context,
1368 GLenum source,
1369 GLenum type,
1370 GLuint id,
1371 GLenum severity,
1372 GLsizei length,
1373 const GLchar *buf)
1374{
1375 if (!context->getExtensions().debug)
1376 {
Jamie Madill437fa652016-05-03 15:13:24 -04001377 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001378 return false;
1379 }
1380
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001381 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001382 {
1383 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1384 // not generate an error.
1385 return false;
1386 }
1387
1388 if (!ValidDebugSeverity(severity))
1389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001391 return false;
1392 }
1393
1394 if (!ValidDebugType(type))
1395 {
Jamie Madill437fa652016-05-03 15:13:24 -04001396 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001397 return false;
1398 }
1399
1400 if (!ValidDebugSource(source, true))
1401 {
Jamie Madill437fa652016-05-03 15:13:24 -04001402 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001403 return false;
1404 }
1405
1406 size_t messageLength = (length < 0) ? strlen(buf) : length;
1407 if (messageLength > context->getExtensions().maxDebugMessageLength)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001410 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1411 return false;
1412 }
1413
Geoff Lange102fee2015-12-10 11:23:30 -05001414 return true;
1415}
1416
1417bool ValidateDebugMessageCallbackKHR(Context *context,
1418 GLDEBUGPROCKHR callback,
1419 const void *userParam)
1420{
1421 if (!context->getExtensions().debug)
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001424 return false;
1425 }
1426
Geoff Lange102fee2015-12-10 11:23:30 -05001427 return true;
1428}
1429
1430bool ValidateGetDebugMessageLogKHR(Context *context,
1431 GLuint count,
1432 GLsizei bufSize,
1433 GLenum *sources,
1434 GLenum *types,
1435 GLuint *ids,
1436 GLenum *severities,
1437 GLsizei *lengths,
1438 GLchar *messageLog)
1439{
1440 if (!context->getExtensions().debug)
1441 {
Jamie Madill437fa652016-05-03 15:13:24 -04001442 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001443 return false;
1444 }
1445
Geoff Lang70d0f492015-12-10 17:45:46 -05001446 if (bufSize < 0 && messageLog != nullptr)
1447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001449 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1450 return false;
1451 }
1452
Geoff Lange102fee2015-12-10 11:23:30 -05001453 return true;
1454}
1455
1456bool ValidatePushDebugGroupKHR(Context *context,
1457 GLenum source,
1458 GLuint id,
1459 GLsizei length,
1460 const GLchar *message)
1461{
1462 if (!context->getExtensions().debug)
1463 {
Jamie Madill437fa652016-05-03 15:13:24 -04001464 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001465 return false;
1466 }
1467
Geoff Lang70d0f492015-12-10 17:45:46 -05001468 if (!ValidDebugSource(source, true))
1469 {
Jamie Madill437fa652016-05-03 15:13:24 -04001470 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001471 return false;
1472 }
1473
1474 size_t messageLength = (length < 0) ? strlen(message) : length;
1475 if (messageLength > context->getExtensions().maxDebugMessageLength)
1476 {
Jamie Madill437fa652016-05-03 15:13:24 -04001477 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001478 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1479 return false;
1480 }
1481
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001482 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001483 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1484 {
Jamie Madill437fa652016-05-03 15:13:24 -04001485 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001486 Error(GL_STACK_OVERFLOW,
1487 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1488 return false;
1489 }
1490
Geoff Lange102fee2015-12-10 11:23:30 -05001491 return true;
1492}
1493
1494bool ValidatePopDebugGroupKHR(Context *context)
1495{
1496 if (!context->getExtensions().debug)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001499 return false;
1500 }
1501
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001502 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001503 if (currentStackSize <= 1)
1504 {
Jamie Madill437fa652016-05-03 15:13:24 -04001505 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001506 return false;
1507 }
1508
1509 return true;
1510}
1511
1512static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1513{
1514 switch (identifier)
1515 {
1516 case GL_BUFFER:
1517 if (context->getBuffer(name) == nullptr)
1518 {
Jamie Madill437fa652016-05-03 15:13:24 -04001519 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001520 return false;
1521 }
1522 return true;
1523
1524 case GL_SHADER:
1525 if (context->getShader(name) == nullptr)
1526 {
Jamie Madill437fa652016-05-03 15:13:24 -04001527 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001528 return false;
1529 }
1530 return true;
1531
1532 case GL_PROGRAM:
1533 if (context->getProgram(name) == nullptr)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001536 return false;
1537 }
1538 return true;
1539
1540 case GL_VERTEX_ARRAY:
1541 if (context->getVertexArray(name) == nullptr)
1542 {
Jamie Madill437fa652016-05-03 15:13:24 -04001543 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001544 return false;
1545 }
1546 return true;
1547
1548 case GL_QUERY:
1549 if (context->getQuery(name) == nullptr)
1550 {
Jamie Madill437fa652016-05-03 15:13:24 -04001551 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001552 return false;
1553 }
1554 return true;
1555
1556 case GL_TRANSFORM_FEEDBACK:
1557 if (context->getTransformFeedback(name) == nullptr)
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001560 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1561 return false;
1562 }
1563 return true;
1564
1565 case GL_SAMPLER:
1566 if (context->getSampler(name) == nullptr)
1567 {
Jamie Madill437fa652016-05-03 15:13:24 -04001568 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001569 return false;
1570 }
1571 return true;
1572
1573 case GL_TEXTURE:
1574 if (context->getTexture(name) == nullptr)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001577 return false;
1578 }
1579 return true;
1580
1581 case GL_RENDERBUFFER:
1582 if (context->getRenderbuffer(name) == nullptr)
1583 {
Jamie Madill437fa652016-05-03 15:13:24 -04001584 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001585 return false;
1586 }
1587 return true;
1588
1589 case GL_FRAMEBUFFER:
1590 if (context->getFramebuffer(name) == nullptr)
1591 {
Jamie Madill437fa652016-05-03 15:13:24 -04001592 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001593 return false;
1594 }
1595 return true;
1596
1597 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001598 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001599 return false;
1600 }
Geoff Lange102fee2015-12-10 11:23:30 -05001601}
1602
Martin Radev9d901792016-07-15 15:58:58 +03001603static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1604{
1605 size_t labelLength = 0;
1606
1607 if (length < 0)
1608 {
1609 if (label != nullptr)
1610 {
1611 labelLength = strlen(label);
1612 }
1613 }
1614 else
1615 {
1616 labelLength = static_cast<size_t>(length);
1617 }
1618
1619 if (labelLength > context->getExtensions().maxLabelLength)
1620 {
1621 context->handleError(
1622 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1623 return false;
1624 }
1625
1626 return true;
1627}
1628
Geoff Lange102fee2015-12-10 11:23:30 -05001629bool ValidateObjectLabelKHR(Context *context,
1630 GLenum identifier,
1631 GLuint name,
1632 GLsizei length,
1633 const GLchar *label)
1634{
1635 if (!context->getExtensions().debug)
1636 {
Jamie Madill437fa652016-05-03 15:13:24 -04001637 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001638 return false;
1639 }
1640
Geoff Lang70d0f492015-12-10 17:45:46 -05001641 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1642 {
1643 return false;
1644 }
1645
Martin Radev9d901792016-07-15 15:58:58 +03001646 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001647 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001648 return false;
1649 }
1650
Geoff Lange102fee2015-12-10 11:23:30 -05001651 return true;
1652}
1653
1654bool ValidateGetObjectLabelKHR(Context *context,
1655 GLenum identifier,
1656 GLuint name,
1657 GLsizei bufSize,
1658 GLsizei *length,
1659 GLchar *label)
1660{
1661 if (!context->getExtensions().debug)
1662 {
Jamie Madill437fa652016-05-03 15:13:24 -04001663 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001664 return false;
1665 }
1666
Geoff Lang70d0f492015-12-10 17:45:46 -05001667 if (bufSize < 0)
1668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001670 return false;
1671 }
1672
1673 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1674 {
1675 return false;
1676 }
1677
Martin Radev9d901792016-07-15 15:58:58 +03001678 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001679}
1680
1681static bool ValidateObjectPtrName(Context *context, const void *ptr)
1682{
1683 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001686 return false;
1687 }
1688
Geoff Lange102fee2015-12-10 11:23:30 -05001689 return true;
1690}
1691
1692bool ValidateObjectPtrLabelKHR(Context *context,
1693 const void *ptr,
1694 GLsizei length,
1695 const GLchar *label)
1696{
1697 if (!context->getExtensions().debug)
1698 {
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001700 return false;
1701 }
1702
Geoff Lang70d0f492015-12-10 17:45:46 -05001703 if (!ValidateObjectPtrName(context, ptr))
1704 {
1705 return false;
1706 }
1707
Martin Radev9d901792016-07-15 15:58:58 +03001708 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001709 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001710 return false;
1711 }
1712
Geoff Lange102fee2015-12-10 11:23:30 -05001713 return true;
1714}
1715
1716bool ValidateGetObjectPtrLabelKHR(Context *context,
1717 const void *ptr,
1718 GLsizei bufSize,
1719 GLsizei *length,
1720 GLchar *label)
1721{
1722 if (!context->getExtensions().debug)
1723 {
Jamie Madill437fa652016-05-03 15:13:24 -04001724 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001725 return false;
1726 }
1727
Geoff Lang70d0f492015-12-10 17:45:46 -05001728 if (bufSize < 0)
1729 {
Jamie Madill437fa652016-05-03 15:13:24 -04001730 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001731 return false;
1732 }
1733
1734 if (!ValidateObjectPtrName(context, ptr))
1735 {
1736 return false;
1737 }
1738
Martin Radev9d901792016-07-15 15:58:58 +03001739 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001740}
1741
1742bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1743{
1744 if (!context->getExtensions().debug)
1745 {
Jamie Madill437fa652016-05-03 15:13:24 -04001746 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001747 return false;
1748 }
1749
Geoff Lang70d0f492015-12-10 17:45:46 -05001750 // TODO: represent this in Context::getQueryParameterInfo.
1751 switch (pname)
1752 {
1753 case GL_DEBUG_CALLBACK_FUNCTION:
1754 case GL_DEBUG_CALLBACK_USER_PARAM:
1755 break;
1756
1757 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001759 return false;
1760 }
1761
Geoff Lange102fee2015-12-10 11:23:30 -05001762 return true;
1763}
Jamie Madillc29968b2016-01-20 11:17:23 -05001764
1765bool ValidateBlitFramebufferANGLE(Context *context,
1766 GLint srcX0,
1767 GLint srcY0,
1768 GLint srcX1,
1769 GLint srcY1,
1770 GLint dstX0,
1771 GLint dstY0,
1772 GLint dstX1,
1773 GLint dstY1,
1774 GLbitfield mask,
1775 GLenum filter)
1776{
1777 if (!context->getExtensions().framebufferBlit)
1778 {
Jamie Madill437fa652016-05-03 15:13:24 -04001779 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001780 return false;
1781 }
1782
1783 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1784 {
1785 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001787 GL_INVALID_OPERATION,
1788 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1789 return false;
1790 }
1791
1792 if (filter == GL_LINEAR)
1793 {
Jamie Madill437fa652016-05-03 15:13:24 -04001794 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001795 return false;
1796 }
1797
Jamie Madill51f40ec2016-06-15 14:06:00 -04001798 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1799 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001800
1801 if (mask & GL_COLOR_BUFFER_BIT)
1802 {
1803 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1804 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1805
1806 if (readColorAttachment && drawColorAttachment)
1807 {
1808 if (!(readColorAttachment->type() == GL_TEXTURE &&
1809 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1810 readColorAttachment->type() != GL_RENDERBUFFER &&
1811 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1812 {
Jamie Madill437fa652016-05-03 15:13:24 -04001813 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001814 return false;
1815 }
1816
Geoff Langa15472a2015-08-11 11:48:03 -04001817 for (size_t drawbufferIdx = 0;
1818 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001819 {
Geoff Langa15472a2015-08-11 11:48:03 -04001820 const FramebufferAttachment *attachment =
1821 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1822 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001823 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 if (!(attachment->type() == GL_TEXTURE &&
1825 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1826 attachment->type() != GL_RENDERBUFFER &&
1827 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832
1833 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001834 if (!Format::SameSized(attachment->getFormat(),
1835 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001838 return false;
1839 }
1840 }
1841 }
1842
Jamie Madill51f40ec2016-06-15 14:06:00 -04001843 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001844 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1845 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1846 {
Jamie Madill437fa652016-05-03 15:13:24 -04001847 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001848 return false;
1849 }
1850 }
1851 }
1852
1853 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1854 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1855 for (size_t i = 0; i < 2; i++)
1856 {
1857 if (mask & masks[i])
1858 {
1859 const FramebufferAttachment *readBuffer =
1860 readFramebuffer->getAttachment(attachments[i]);
1861 const FramebufferAttachment *drawBuffer =
1862 drawFramebuffer->getAttachment(attachments[i]);
1863
1864 if (readBuffer && drawBuffer)
1865 {
1866 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1867 dstX0, dstY0, dstX1, dstY1))
1868 {
1869 // only whole-buffer copies are permitted
1870 ERR(
1871 "Only whole-buffer depth and stencil blits are supported by this "
1872 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001873 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001874 return false;
1875 }
1876
1877 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882 }
1883 }
1884 }
1885
1886 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1887 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001888}
Jamie Madillc29968b2016-01-20 11:17:23 -05001889
1890bool ValidateClear(ValidationContext *context, GLbitfield mask)
1891{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001892 auto fbo = context->getGLState().getDrawFramebuffer();
1893 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001894 {
Jamie Madill437fa652016-05-03 15:13:24 -04001895 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001896 return false;
1897 }
1898
1899 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1900 {
Jamie Madill437fa652016-05-03 15:13:24 -04001901 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001902 return false;
1903 }
1904
1905 return true;
1906}
1907
1908bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1909{
1910 if (!context->getExtensions().drawBuffers)
1911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001913 return false;
1914 }
1915
1916 return ValidateDrawBuffersBase(context, n, bufs);
1917}
1918
Jamie Madill73a84962016-02-12 09:27:23 -05001919bool ValidateTexImage2D(Context *context,
1920 GLenum target,
1921 GLint level,
1922 GLint internalformat,
1923 GLsizei width,
1924 GLsizei height,
1925 GLint border,
1926 GLenum format,
1927 GLenum type,
1928 const GLvoid *pixels)
1929{
Martin Radev1be913c2016-07-11 17:59:16 +03001930 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001931 {
1932 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1933 0, 0, width, height, border, format, type, pixels);
1934 }
1935
Martin Radev1be913c2016-07-11 17:59:16 +03001936 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001937 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1938 0, 0, width, height, 1, border, format, type, pixels);
1939}
1940
1941bool ValidateTexSubImage2D(Context *context,
1942 GLenum target,
1943 GLint level,
1944 GLint xoffset,
1945 GLint yoffset,
1946 GLsizei width,
1947 GLsizei height,
1948 GLenum format,
1949 GLenum type,
1950 const GLvoid *pixels)
1951{
1952
Martin Radev1be913c2016-07-11 17:59:16 +03001953 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001954 {
1955 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1956 yoffset, width, height, 0, format, type, pixels);
1957 }
1958
Martin Radev1be913c2016-07-11 17:59:16 +03001959 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001960 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1961 yoffset, 0, width, height, 1, 0, format, type, pixels);
1962}
1963
1964bool ValidateCompressedTexImage2D(Context *context,
1965 GLenum target,
1966 GLint level,
1967 GLenum internalformat,
1968 GLsizei width,
1969 GLsizei height,
1970 GLint border,
1971 GLsizei imageSize,
1972 const GLvoid *data)
1973{
Martin Radev1be913c2016-07-11 17:59:16 +03001974 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001975 {
1976 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1977 0, width, height, border, GL_NONE, GL_NONE, data))
1978 {
1979 return false;
1980 }
1981 }
1982 else
1983 {
Martin Radev1be913c2016-07-11 17:59:16 +03001984 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001985 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1986 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1987 data))
1988 {
1989 return false;
1990 }
1991 }
1992
1993 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001994 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001995 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001996 if (blockSizeOrErr.isError())
1997 {
1998 context->handleError(blockSizeOrErr.getError());
1999 return false;
2000 }
2001
2002 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002003 {
Jamie Madill437fa652016-05-03 15:13:24 -04002004 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002005 return false;
2006 }
2007
2008 return true;
2009}
2010
2011bool ValidateCompressedTexSubImage2D(Context *context,
2012 GLenum target,
2013 GLint level,
2014 GLint xoffset,
2015 GLint yoffset,
2016 GLsizei width,
2017 GLsizei height,
2018 GLenum format,
2019 GLsizei imageSize,
2020 const GLvoid *data)
2021{
Martin Radev1be913c2016-07-11 17:59:16 +03002022 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002023 {
2024 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2025 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2026 {
2027 return false;
2028 }
2029 }
2030 else
2031 {
Martin Radev1be913c2016-07-11 17:59:16 +03002032 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002033 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2034 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2035 data))
2036 {
2037 return false;
2038 }
2039 }
2040
2041 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002042 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002043 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002044 if (blockSizeOrErr.isError())
2045 {
2046 context->handleError(blockSizeOrErr.getError());
2047 return false;
2048 }
2049
2050 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002053 return false;
2054 }
2055
2056 return true;
2057}
2058
Olli Etuaho4f667482016-03-30 15:56:35 +03002059bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2060{
2061 if (!context->getExtensions().mapBuffer)
2062 {
Jamie Madill437fa652016-05-03 15:13:24 -04002063 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002064 return false;
2065 }
2066
2067 return ValidateGetBufferPointervBase(context, target, pname, params);
2068}
2069
2070bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2071{
2072 if (!context->getExtensions().mapBuffer)
2073 {
Jamie Madill437fa652016-05-03 15:13:24 -04002074 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002075 return false;
2076 }
2077
2078 if (!ValidBufferTarget(context, target))
2079 {
Jamie Madill437fa652016-05-03 15:13:24 -04002080 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002081 return false;
2082 }
2083
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002084 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002085
2086 if (buffer == nullptr)
2087 {
Jamie Madill437fa652016-05-03 15:13:24 -04002088 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002089 return false;
2090 }
2091
2092 if (access != GL_WRITE_ONLY_OES)
2093 {
Jamie Madill437fa652016-05-03 15:13:24 -04002094 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002095 return false;
2096 }
2097
2098 if (buffer->isMapped())
2099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002101 return false;
2102 }
2103
2104 return true;
2105}
2106
2107bool ValidateUnmapBufferOES(Context *context, GLenum target)
2108{
2109 if (!context->getExtensions().mapBuffer)
2110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002112 return false;
2113 }
2114
2115 return ValidateUnmapBufferBase(context, target);
2116}
2117
2118bool ValidateMapBufferRangeEXT(Context *context,
2119 GLenum target,
2120 GLintptr offset,
2121 GLsizeiptr length,
2122 GLbitfield access)
2123{
2124 if (!context->getExtensions().mapBufferRange)
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002127 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2128 return false;
2129 }
2130
2131 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2132}
2133
2134bool ValidateFlushMappedBufferRangeEXT(Context *context,
2135 GLenum target,
2136 GLintptr offset,
2137 GLsizeiptr length)
2138{
2139 if (!context->getExtensions().mapBufferRange)
2140 {
Jamie Madill437fa652016-05-03 15:13:24 -04002141 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002142 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2143 return false;
2144 }
2145
2146 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2147}
2148
Ian Ewell54f87462016-03-10 13:47:21 -05002149bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2150{
2151 Texture *textureObject = context->getTexture(texture);
2152 if (textureObject && textureObject->getTarget() != target && texture != 0)
2153 {
Jamie Madill437fa652016-05-03 15:13:24 -04002154 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002155 return false;
2156 }
2157
2158 switch (target)
2159 {
2160 case GL_TEXTURE_2D:
2161 case GL_TEXTURE_CUBE_MAP:
2162 break;
2163
2164 case GL_TEXTURE_3D:
2165 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002166 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002167 {
Jamie Madill437fa652016-05-03 15:13:24 -04002168 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002169 return false;
2170 }
2171 break;
2172 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002173 if (!context->getExtensions().eglImageExternal &&
2174 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002175 {
Jamie Madill437fa652016-05-03 15:13:24 -04002176 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002177 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2178 return false;
2179 }
2180 break;
2181 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002183 return false;
2184 }
2185
2186 return true;
2187}
2188
Geoff Langd8605522016-04-13 10:19:12 -04002189bool ValidateBindUniformLocationCHROMIUM(Context *context,
2190 GLuint program,
2191 GLint location,
2192 const GLchar *name)
2193{
2194 if (!context->getExtensions().bindUniformLocation)
2195 {
Jamie Madill437fa652016-05-03 15:13:24 -04002196 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002197 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2198 return false;
2199 }
2200
2201 Program *programObject = GetValidProgram(context, program);
2202 if (!programObject)
2203 {
2204 return false;
2205 }
2206
2207 if (location < 0)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002210 return false;
2211 }
2212
2213 const Caps &caps = context->getCaps();
2214 if (static_cast<size_t>(location) >=
2215 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002218 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2219 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2220 return false;
2221 }
2222
2223 if (strncmp(name, "gl_", 3) == 0)
2224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002226 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2227 return false;
2228 }
2229
2230 return true;
2231}
2232
Jamie Madille2e406c2016-06-02 13:04:10 -04002233bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002234{
2235 if (!context->getExtensions().framebufferMixedSamples)
2236 {
2237 context->handleError(
2238 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2239 return false;
2240 }
2241 switch (components)
2242 {
2243 case GL_RGB:
2244 case GL_RGBA:
2245 case GL_ALPHA:
2246 case GL_NONE:
2247 break;
2248 default:
2249 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002250 Error(GL_INVALID_ENUM,
2251 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002252 return false;
2253 }
2254
2255 return true;
2256}
2257
Sami Väisänene45e53b2016-05-25 10:36:04 +03002258// CHROMIUM_path_rendering
2259
2260bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2261{
2262 if (!context->getExtensions().pathRendering)
2263 {
2264 context->handleError(
2265 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2266 return false;
2267 }
2268 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2269 {
2270 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2271 return false;
2272 }
2273 if (matrix == nullptr)
2274 {
2275 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2276 return false;
2277 }
2278 return true;
2279}
2280
2281bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2282{
2283 if (!context->getExtensions().pathRendering)
2284 {
2285 context->handleError(
2286 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2287 return false;
2288 }
2289 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2290 {
2291 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2292 return false;
2293 }
2294 return true;
2295}
2296
2297bool ValidateGenPaths(Context *context, GLsizei range)
2298{
2299 if (!context->getExtensions().pathRendering)
2300 {
2301 context->handleError(
2302 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2303 return false;
2304 }
2305
2306 // range = 0 is undefined in NV_path_rendering.
2307 // we add stricter semantic check here and require a non zero positive range.
2308 if (range <= 0)
2309 {
2310 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2311 return false;
2312 }
2313
2314 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2315 {
2316 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2317 return false;
2318 }
2319
2320 return true;
2321}
2322
2323bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2324{
2325 if (!context->getExtensions().pathRendering)
2326 {
2327 context->handleError(
2328 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2329 return false;
2330 }
2331
2332 // range = 0 is undefined in NV_path_rendering.
2333 // we add stricter semantic check here and require a non zero positive range.
2334 if (range <= 0)
2335 {
2336 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2337 return false;
2338 }
2339
2340 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2341 checkedRange += range;
2342
2343 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2344 {
2345 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2346 return false;
2347 }
2348 return true;
2349}
2350
2351bool ValidatePathCommands(Context *context,
2352 GLuint path,
2353 GLsizei numCommands,
2354 const GLubyte *commands,
2355 GLsizei numCoords,
2356 GLenum coordType,
2357 const void *coords)
2358{
2359 if (!context->getExtensions().pathRendering)
2360 {
2361 context->handleError(
2362 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2363 return false;
2364 }
2365 if (!context->hasPath(path))
2366 {
2367 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2368 return false;
2369 }
2370
2371 if (numCommands < 0)
2372 {
2373 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2374 return false;
2375 }
2376 else if (numCommands > 0)
2377 {
2378 if (!commands)
2379 {
2380 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2381 return false;
2382 }
2383 }
2384
2385 if (numCoords < 0)
2386 {
2387 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2388 return false;
2389 }
2390 else if (numCoords > 0)
2391 {
2392 if (!coords)
2393 {
2394 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2395 return false;
2396 }
2397 }
2398
2399 std::uint32_t coordTypeSize = 0;
2400 switch (coordType)
2401 {
2402 case GL_BYTE:
2403 coordTypeSize = sizeof(GLbyte);
2404 break;
2405
2406 case GL_UNSIGNED_BYTE:
2407 coordTypeSize = sizeof(GLubyte);
2408 break;
2409
2410 case GL_SHORT:
2411 coordTypeSize = sizeof(GLshort);
2412 break;
2413
2414 case GL_UNSIGNED_SHORT:
2415 coordTypeSize = sizeof(GLushort);
2416 break;
2417
2418 case GL_FLOAT:
2419 coordTypeSize = sizeof(GLfloat);
2420 break;
2421
2422 default:
2423 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2424 return false;
2425 }
2426
2427 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2428 checkedSize += (coordTypeSize * numCoords);
2429 if (!checkedSize.IsValid())
2430 {
2431 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2432 return false;
2433 }
2434
2435 // early return skips command data validation when it doesn't exist.
2436 if (!commands)
2437 return true;
2438
2439 GLsizei expectedNumCoords = 0;
2440 for (GLsizei i = 0; i < numCommands; ++i)
2441 {
2442 switch (commands[i])
2443 {
2444 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2445 break;
2446 case GL_MOVE_TO_CHROMIUM:
2447 case GL_LINE_TO_CHROMIUM:
2448 expectedNumCoords += 2;
2449 break;
2450 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2451 expectedNumCoords += 4;
2452 break;
2453 case GL_CUBIC_CURVE_TO_CHROMIUM:
2454 expectedNumCoords += 6;
2455 break;
2456 case GL_CONIC_CURVE_TO_CHROMIUM:
2457 expectedNumCoords += 5;
2458 break;
2459 default:
2460 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2461 return false;
2462 }
2463 }
2464 if (expectedNumCoords != numCoords)
2465 {
2466 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2467 return false;
2468 }
2469
2470 return true;
2471}
2472
2473bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2474{
2475 if (!context->getExtensions().pathRendering)
2476 {
2477 context->handleError(
2478 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2479 return false;
2480 }
2481 if (!context->hasPath(path))
2482 {
2483 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2484 return false;
2485 }
2486
2487 switch (pname)
2488 {
2489 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2490 if (value < 0.0f)
2491 {
2492 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2493 return false;
2494 }
2495 break;
2496 case GL_PATH_END_CAPS_CHROMIUM:
2497 switch (static_cast<GLenum>(value))
2498 {
2499 case GL_FLAT_CHROMIUM:
2500 case GL_SQUARE_CHROMIUM:
2501 case GL_ROUND_CHROMIUM:
2502 break;
2503 default:
2504 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2505 return false;
2506 }
2507 break;
2508 case GL_PATH_JOIN_STYLE_CHROMIUM:
2509 switch (static_cast<GLenum>(value))
2510 {
2511 case GL_MITER_REVERT_CHROMIUM:
2512 case GL_BEVEL_CHROMIUM:
2513 case GL_ROUND_CHROMIUM:
2514 break;
2515 default:
2516 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2517 return false;
2518 }
2519 case GL_PATH_MITER_LIMIT_CHROMIUM:
2520 if (value < 0.0f)
2521 {
2522 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2523 return false;
2524 }
2525 break;
2526
2527 case GL_PATH_STROKE_BOUND_CHROMIUM:
2528 // no errors, only clamping.
2529 break;
2530
2531 default:
2532 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2533 return false;
2534 }
2535 return true;
2536}
2537
2538bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2539{
2540 if (!context->getExtensions().pathRendering)
2541 {
2542 context->handleError(
2543 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2544 return false;
2545 }
2546
2547 if (!context->hasPath(path))
2548 {
2549 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2550 return false;
2551 }
2552 if (!value)
2553 {
2554 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2555 return false;
2556 }
2557
2558 switch (pname)
2559 {
2560 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2561 case GL_PATH_END_CAPS_CHROMIUM:
2562 case GL_PATH_JOIN_STYLE_CHROMIUM:
2563 case GL_PATH_MITER_LIMIT_CHROMIUM:
2564 case GL_PATH_STROKE_BOUND_CHROMIUM:
2565 break;
2566
2567 default:
2568 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2569 return false;
2570 }
2571
2572 return true;
2573}
2574
2575bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2576{
2577 if (!context->getExtensions().pathRendering)
2578 {
2579 context->handleError(
2580 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2581 return false;
2582 }
2583
2584 switch (func)
2585 {
2586 case GL_NEVER:
2587 case GL_ALWAYS:
2588 case GL_LESS:
2589 case GL_LEQUAL:
2590 case GL_EQUAL:
2591 case GL_GEQUAL:
2592 case GL_GREATER:
2593 case GL_NOTEQUAL:
2594 break;
2595 default:
2596 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2597 return false;
2598 }
2599
2600 return true;
2601}
2602
2603// Note that the spec specifies that for the path drawing commands
2604// if the path object is not an existing path object the command
2605// does nothing and no error is generated.
2606// However if the path object exists but has not been specified any
2607// commands then an error is generated.
2608
2609bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2610{
2611 if (!context->getExtensions().pathRendering)
2612 {
2613 context->handleError(
2614 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2615 return false;
2616 }
2617 if (context->hasPath(path) && !context->hasPathData(path))
2618 {
2619 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2620 return false;
2621 }
2622
2623 switch (fillMode)
2624 {
2625 case GL_COUNT_UP_CHROMIUM:
2626 case GL_COUNT_DOWN_CHROMIUM:
2627 break;
2628 default:
2629 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2630 return false;
2631 }
2632
2633 if (!isPow2(mask + 1))
2634 {
2635 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2636 return false;
2637 }
2638
2639 return true;
2640}
2641
2642bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2643{
2644 if (!context->getExtensions().pathRendering)
2645 {
2646 context->handleError(
2647 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2648 return false;
2649 }
2650 if (context->hasPath(path) && !context->hasPathData(path))
2651 {
2652 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2653 return false;
2654 }
2655
2656 return true;
2657}
2658
2659bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2660{
2661 if (!context->getExtensions().pathRendering)
2662 {
2663 context->handleError(
2664 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2665 return false;
2666 }
2667 if (context->hasPath(path) && !context->hasPathData(path))
2668 {
2669 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2670 return false;
2671 }
2672
2673 switch (coverMode)
2674 {
2675 case GL_CONVEX_HULL_CHROMIUM:
2676 case GL_BOUNDING_BOX_CHROMIUM:
2677 break;
2678 default:
2679 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2680 return false;
2681 }
2682 return true;
2683}
2684
2685bool ValidateStencilThenCoverFillPath(Context *context,
2686 GLuint path,
2687 GLenum fillMode,
2688 GLuint mask,
2689 GLenum coverMode)
2690{
2691 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2692 ValidateCoverPath(context, path, coverMode);
2693}
2694
2695bool ValidateStencilThenCoverStrokePath(Context *context,
2696 GLuint path,
2697 GLint reference,
2698 GLuint mask,
2699 GLenum coverMode)
2700{
2701 return ValidateStencilStrokePath(context, path, reference, mask) &&
2702 ValidateCoverPath(context, path, coverMode);
2703}
2704
2705bool ValidateIsPath(Context *context)
2706{
2707 if (!context->getExtensions().pathRendering)
2708 {
2709 context->handleError(
2710 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2711 return false;
2712 }
2713 return true;
2714}
2715
Sami Väisänend59ca052016-06-21 16:10:00 +03002716bool ValidateCoverFillPathInstanced(Context *context,
2717 GLsizei numPaths,
2718 GLenum pathNameType,
2719 const void *paths,
2720 GLuint pathBase,
2721 GLenum coverMode,
2722 GLenum transformType,
2723 const GLfloat *transformValues)
2724{
2725 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2726 transformType, transformValues))
2727 return false;
2728
2729 switch (coverMode)
2730 {
2731 case GL_CONVEX_HULL_CHROMIUM:
2732 case GL_BOUNDING_BOX_CHROMIUM:
2733 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2734 break;
2735 default:
2736 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2737 return false;
2738 }
2739
2740 return true;
2741}
2742
2743bool ValidateCoverStrokePathInstanced(Context *context,
2744 GLsizei numPaths,
2745 GLenum pathNameType,
2746 const void *paths,
2747 GLuint pathBase,
2748 GLenum coverMode,
2749 GLenum transformType,
2750 const GLfloat *transformValues)
2751{
2752 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2753 transformType, transformValues))
2754 return false;
2755
2756 switch (coverMode)
2757 {
2758 case GL_CONVEX_HULL_CHROMIUM:
2759 case GL_BOUNDING_BOX_CHROMIUM:
2760 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2761 break;
2762 default:
2763 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2764 return false;
2765 }
2766
2767 return true;
2768}
2769
2770bool ValidateStencilFillPathInstanced(Context *context,
2771 GLsizei numPaths,
2772 GLenum pathNameType,
2773 const void *paths,
2774 GLuint pathBase,
2775 GLenum fillMode,
2776 GLuint mask,
2777 GLenum transformType,
2778 const GLfloat *transformValues)
2779{
2780
2781 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2782 transformType, transformValues))
2783 return false;
2784
2785 switch (fillMode)
2786 {
2787 case GL_COUNT_UP_CHROMIUM:
2788 case GL_COUNT_DOWN_CHROMIUM:
2789 break;
2790 default:
2791 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2792 return false;
2793 }
2794 if (!isPow2(mask + 1))
2795 {
2796 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2797 return false;
2798 }
2799 return true;
2800}
2801
2802bool ValidateStencilStrokePathInstanced(Context *context,
2803 GLsizei numPaths,
2804 GLenum pathNameType,
2805 const void *paths,
2806 GLuint pathBase,
2807 GLint reference,
2808 GLuint mask,
2809 GLenum transformType,
2810 const GLfloat *transformValues)
2811{
2812 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2813 transformType, transformValues))
2814 return false;
2815
2816 // no more validation here.
2817
2818 return true;
2819}
2820
2821bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2822 GLsizei numPaths,
2823 GLenum pathNameType,
2824 const void *paths,
2825 GLuint pathBase,
2826 GLenum fillMode,
2827 GLuint mask,
2828 GLenum coverMode,
2829 GLenum transformType,
2830 const GLfloat *transformValues)
2831{
2832 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2833 transformType, transformValues))
2834 return false;
2835
2836 switch (coverMode)
2837 {
2838 case GL_CONVEX_HULL_CHROMIUM:
2839 case GL_BOUNDING_BOX_CHROMIUM:
2840 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2841 break;
2842 default:
2843 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2844 return false;
2845 }
2846
2847 switch (fillMode)
2848 {
2849 case GL_COUNT_UP_CHROMIUM:
2850 case GL_COUNT_DOWN_CHROMIUM:
2851 break;
2852 default:
2853 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2854 return false;
2855 }
2856 if (!isPow2(mask + 1))
2857 {
2858 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2859 return false;
2860 }
2861
2862 return true;
2863}
2864
2865bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2866 GLsizei numPaths,
2867 GLenum pathNameType,
2868 const void *paths,
2869 GLuint pathBase,
2870 GLint reference,
2871 GLuint mask,
2872 GLenum coverMode,
2873 GLenum transformType,
2874 const GLfloat *transformValues)
2875{
2876 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2877 transformType, transformValues))
2878 return false;
2879
2880 switch (coverMode)
2881 {
2882 case GL_CONVEX_HULL_CHROMIUM:
2883 case GL_BOUNDING_BOX_CHROMIUM:
2884 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2885 break;
2886 default:
2887 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2888 return false;
2889 }
2890
2891 return true;
2892}
2893
Sami Väisänen46eaa942016-06-29 10:26:37 +03002894bool ValidateBindFragmentInputLocation(Context *context,
2895 GLuint program,
2896 GLint location,
2897 const GLchar *name)
2898{
2899 if (!context->getExtensions().pathRendering)
2900 {
2901 context->handleError(
2902 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2903 return false;
2904 }
2905
2906 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2907 if (location >= MaxLocation)
2908 {
2909 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2910 return false;
2911 }
2912
2913 const auto *programObject = context->getProgram(program);
2914 if (!programObject)
2915 {
2916 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2917 return false;
2918 }
2919
2920 if (!name)
2921 {
2922 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2923 return false;
2924 }
2925
2926 if (angle::BeginsWith(name, "gl_"))
2927 {
2928 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2929 return false;
2930 }
2931
2932 return true;
2933}
2934
2935bool ValidateProgramPathFragmentInputGen(Context *context,
2936 GLuint program,
2937 GLint location,
2938 GLenum genMode,
2939 GLint components,
2940 const GLfloat *coeffs)
2941{
2942 if (!context->getExtensions().pathRendering)
2943 {
2944 context->handleError(
2945 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2946 return false;
2947 }
2948
2949 const auto *programObject = context->getProgram(program);
2950 if (!programObject || programObject->isFlaggedForDeletion())
2951 {
2952 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2953 return false;
2954 }
2955
2956 if (!programObject->isLinked())
2957 {
2958 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2959 return false;
2960 }
2961
2962 switch (genMode)
2963 {
2964 case GL_NONE:
2965 if (components != 0)
2966 {
2967 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2968 return false;
2969 }
2970 break;
2971
2972 case GL_OBJECT_LINEAR_CHROMIUM:
2973 case GL_EYE_LINEAR_CHROMIUM:
2974 case GL_CONSTANT_CHROMIUM:
2975 if (components < 1 || components > 4)
2976 {
2977 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2978 return false;
2979 }
2980 if (!coeffs)
2981 {
2982 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2983 return false;
2984 }
2985 break;
2986
2987 default:
2988 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2989 return false;
2990 }
2991
2992 // If the location is -1 then the command is silently ignored
2993 // and no further validation is needed.
2994 if (location == -1)
2995 return true;
2996
2997 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2998
2999 if (!binding.valid)
3000 {
3001 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3002 return false;
3003 }
3004
3005 if (binding.type != GL_NONE)
3006 {
3007 GLint expectedComponents = 0;
3008 switch (binding.type)
3009 {
3010 case GL_FLOAT:
3011 expectedComponents = 1;
3012 break;
3013 case GL_FLOAT_VEC2:
3014 expectedComponents = 2;
3015 break;
3016 case GL_FLOAT_VEC3:
3017 expectedComponents = 3;
3018 break;
3019 case GL_FLOAT_VEC4:
3020 expectedComponents = 4;
3021 break;
3022 default:
3023 context->handleError(Error(GL_INVALID_OPERATION,
3024 "Fragment input type is not a floating point scalar or vector."));
3025 return false;
3026 }
3027 if (expectedComponents != components && genMode != GL_NONE)
3028 {
3029 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3030 return false;
3031 }
3032 }
3033 return true;
3034}
3035
Jamie Madillc29968b2016-01-20 11:17:23 -05003036} // namespace gl