blob: dc2a00883c38f1e59540beeb7011e0033e67f994 [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 Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Texture.h"
18#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
22#include "libANGLE/Uniform.h"
23#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES.h"
25#include "libANGLE/validationES3.h"
Corentin Wallez0c7baf12016-12-19 15:43:10 -050026#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
78 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
79 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
95 context->handleError(
96 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
97 return false;
98 }
99
100 if (paths == nullptr)
101 {
102 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
103 return false;
104 }
105
106 if (numPaths < 0)
107 {
108 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
114 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
160 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
188 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
193 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
202 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang97073d12016-04-20 10:42:34 -0700209bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
210{
211 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
212 switch (internalFormatInfo.format)
213 {
214 case GL_ALPHA:
215 case GL_LUMINANCE:
216 case GL_LUMINANCE_ALPHA:
217 case GL_RGB:
218 case GL_RGBA:
219 return true;
220
221 case GL_RED:
222 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
223
224 case GL_BGRA_EXT:
225 return context->getExtensions().textureFormatBGRA8888;
226
227 default:
228 return false;
229 }
230}
231
232bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
233{
234 switch (internalFormat)
235 {
236 case GL_RGB:
237 case GL_RGBA:
238 break;
239
240 case GL_BGRA_EXT:
241 return context->getExtensions().textureFormatBGRA8888;
242
243 default:
244 return false;
245 }
246
247 switch (type)
248 {
249 case GL_UNSIGNED_BYTE:
250 break;
251
252 default:
253 return false;
254 }
255
256 return true;
257}
258
259bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
260{
261 switch (target)
262 {
263 case GL_TEXTURE_2D:
264 return true;
265
266 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
267 // supported
268
269 default:
270 return false;
271 }
272}
273
274bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
275{
276 if (IsValidCopyTextureDestinationTarget(context, target))
277 {
278 return true;
279 }
280
281 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
282 // supported
283
284 return false;
285}
286
Jamie Madillc29968b2016-01-20 11:17:23 -0500287} // anonymous namespace
288
Geoff Langff5b2d52016-09-07 11:32:23 -0400289bool ValidateES2TexImageParameters(Context *context,
290 GLenum target,
291 GLint level,
292 GLenum internalformat,
293 bool isCompressed,
294 bool isSubImage,
295 GLint xoffset,
296 GLint yoffset,
297 GLsizei width,
298 GLsizei height,
299 GLint border,
300 GLenum format,
301 GLenum type,
302 GLsizei imageSize,
303 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304{
Jamie Madill6f38f822014-06-06 17:12:20 -0400305 if (!ValidTexture2DDestinationTarget(context, target))
306 {
Jamie Madill437fa652016-05-03 15:13:24 -0400307 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400308 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400309 }
310
Austin Kinross08528e12015-10-07 16:24:40 -0700311 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 {
Jamie Madill437fa652016-05-03 15:13:24 -0400313 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316
He Yunchaoced53ae2016-11-29 15:00:51 +0800317 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400318 std::numeric_limits<GLsizei>::max() - yoffset < height)
319 {
Jamie Madill437fa652016-05-03 15:13:24 -0400320 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
Geoff Lang005df412013-10-16 14:12:50 -0400324 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Jamie Madill437fa652016-05-03 15:13:24 -0400326 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 }
329
Geoff Langaae65a42014-05-26 12:43:44 -0400330 const gl::Caps &caps = context->getCaps();
331
Geoff Langa9be0dc2014-12-17 12:34:40 -0500332 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
335 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 {
Jamie Madill437fa652016-05-03 15:13:24 -0400337 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500341 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500342 {
343 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 {
Jamie Madill437fa652016-05-03 15:13:24 -0400345 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348
Geoff Langa9be0dc2014-12-17 12:34:40 -0500349 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
350 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
354 }
355 }
356 else
357 {
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400360 }
361
He Yunchaoced53ae2016-11-29 15:00:51 +0800362 gl::Texture *texture =
363 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 if (!texture)
365 {
Jamie Madill437fa652016-05-03 15:13:24 -0400366 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 }
369
Geoff Langa9be0dc2014-12-17 12:34:40 -0500370 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371 {
Geoff Langc51642b2016-11-14 16:18:26 -0500372 GLenum textureFormat = texture->getFormat(target, level).asSized();
373 if (textureFormat == GL_NONE)
374 {
375 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
376 return false;
377 }
378
Geoff Langa9be0dc2014-12-17 12:34:40 -0500379 if (format != GL_NONE)
380 {
Geoff Langc51642b2016-11-14 16:18:26 -0500381 if (gl::GetSizedInternalFormat(format, type) != textureFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500382 {
Jamie Madill437fa652016-05-03 15:13:24 -0400383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500384 return false;
385 }
386 }
387
388 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
389 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
390 {
Jamie Madill437fa652016-05-03 15:13:24 -0400391 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500392 return false;
393 }
394 }
395 else
396 {
Geoff Lang69cce582015-09-17 13:20:36 -0400397 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500398 {
Jamie Madill437fa652016-05-03 15:13:24 -0400399 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500400 return false;
401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 }
403
404 // Verify zero border
405 if (border != 0)
406 {
Jamie Madill437fa652016-05-03 15:13:24 -0400407 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409 }
410
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 if (isCompressed)
412 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400413 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400414 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415 switch (actualInternalFormat)
416 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
419 if (!context->getExtensions().textureCompressionDXT1)
420 {
421 context->handleError(Error(GL_INVALID_ENUM));
422 return false;
423 }
424 break;
425 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
426 if (!context->getExtensions().textureCompressionDXT1)
427 {
428 context->handleError(Error(GL_INVALID_ENUM));
429 return false;
430 }
431 break;
432 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
433 if (!context->getExtensions().textureCompressionDXT5)
434 {
435 context->handleError(Error(GL_INVALID_ENUM));
436 return false;
437 }
438 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800439 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
440 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
441 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
442 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
443 if (!context->getExtensions().textureCompressionS3TCsRGB)
444 {
445 context->handleError(Error(GL_INVALID_ENUM));
446 return false;
447 }
448 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 case GL_ETC1_RGB8_OES:
450 if (!context->getExtensions().compressedETC1RGB8Texture)
451 {
452 context->handleError(Error(GL_INVALID_ENUM));
453 return false;
454 }
455 break;
456 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
457 if (!context->getExtensions().lossyETCDecode)
458 {
459 context->handleError(Error(
460 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
461 return false;
462 }
463 break;
464 default:
465 context->handleError(
466 Error(GL_INVALID_ENUM,
467 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400468 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400469 }
470 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
471 {
Jamie Madill437fa652016-05-03 15:13:24 -0400472 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400473 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400474 }
475 }
476 else
477 {
478 // validate <type> by itself (used as secondary key below)
479 switch (type)
480 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800481 case GL_UNSIGNED_BYTE:
482 case GL_UNSIGNED_SHORT_5_6_5:
483 case GL_UNSIGNED_SHORT_4_4_4_4:
484 case GL_UNSIGNED_SHORT_5_5_5_1:
485 case GL_UNSIGNED_SHORT:
486 case GL_UNSIGNED_INT:
487 case GL_UNSIGNED_INT_24_8_OES:
488 case GL_HALF_FLOAT_OES:
489 case GL_FLOAT:
490 break;
491 default:
492 context->handleError(Error(GL_INVALID_ENUM));
493 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400494 }
495
496 // validate <format> + <type> combinations
497 // - invalid <format> -> sets INVALID_ENUM
498 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
499 switch (format)
500 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800501 case GL_ALPHA:
502 case GL_LUMINANCE:
503 case GL_LUMINANCE_ALPHA:
504 switch (type)
505 {
506 case GL_UNSIGNED_BYTE:
507 case GL_FLOAT:
508 case GL_HALF_FLOAT_OES:
509 break;
510 default:
511 context->handleError(Error(GL_INVALID_OPERATION));
512 return false;
513 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400514 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800515 case GL_RED:
516 case GL_RG:
517 if (!context->getExtensions().textureRG)
518 {
519 context->handleError(Error(GL_INVALID_ENUM));
520 return false;
521 }
522 switch (type)
523 {
524 case GL_UNSIGNED_BYTE:
525 case GL_FLOAT:
526 case GL_HALF_FLOAT_OES:
527 break;
528 default:
529 context->handleError(Error(GL_INVALID_OPERATION));
530 return false;
531 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400532 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800533 case GL_RGB:
534 switch (type)
535 {
536 case GL_UNSIGNED_BYTE:
537 case GL_UNSIGNED_SHORT_5_6_5:
538 case GL_FLOAT:
539 case GL_HALF_FLOAT_OES:
540 break;
541 default:
542 context->handleError(Error(GL_INVALID_OPERATION));
543 return false;
544 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400545 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800546 case GL_RGBA:
547 switch (type)
548 {
549 case GL_UNSIGNED_BYTE:
550 case GL_UNSIGNED_SHORT_4_4_4_4:
551 case GL_UNSIGNED_SHORT_5_5_5_1:
552 case GL_FLOAT:
553 case GL_HALF_FLOAT_OES:
554 break;
555 default:
556 context->handleError(Error(GL_INVALID_OPERATION));
557 return false;
558 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400559 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800560 case GL_BGRA_EXT:
561 switch (type)
562 {
563 case GL_UNSIGNED_BYTE:
564 break;
565 default:
566 context->handleError(Error(GL_INVALID_OPERATION));
567 return false;
568 }
569 break;
570 case GL_SRGB_EXT:
571 case GL_SRGB_ALPHA_EXT:
572 if (!context->getExtensions().sRGB)
573 {
574 context->handleError(Error(GL_INVALID_ENUM));
575 return false;
576 }
577 switch (type)
578 {
579 case GL_UNSIGNED_BYTE:
580 break;
581 default:
582 context->handleError(Error(GL_INVALID_OPERATION));
583 return false;
584 }
585 break;
586 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
587 // handled below
588 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
589 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
590 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
591 break;
592 case GL_DEPTH_COMPONENT:
593 switch (type)
594 {
595 case GL_UNSIGNED_SHORT:
596 case GL_UNSIGNED_INT:
597 break;
598 default:
599 context->handleError(Error(GL_INVALID_OPERATION));
600 return false;
601 }
602 break;
603 case GL_DEPTH_STENCIL_OES:
604 switch (type)
605 {
606 case GL_UNSIGNED_INT_24_8_OES:
607 break;
608 default:
609 context->handleError(Error(GL_INVALID_OPERATION));
610 return false;
611 }
612 break;
613 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400614 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400615 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 }
617
618 switch (format)
619 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800620 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
621 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
622 if (context->getExtensions().textureCompressionDXT1)
623 {
624 context->handleError(Error(GL_INVALID_OPERATION));
625 return false;
626 }
627 else
628 {
629 context->handleError(Error(GL_INVALID_ENUM));
630 return false;
631 }
632 break;
633 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
634 if (context->getExtensions().textureCompressionDXT3)
635 {
636 context->handleError(Error(GL_INVALID_OPERATION));
637 return false;
638 }
639 else
640 {
641 context->handleError(Error(GL_INVALID_ENUM));
642 return false;
643 }
644 break;
645 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
646 if (context->getExtensions().textureCompressionDXT5)
647 {
648 context->handleError(Error(GL_INVALID_OPERATION));
649 return false;
650 }
651 else
652 {
653 context->handleError(Error(GL_INVALID_ENUM));
654 return false;
655 }
656 break;
657 case GL_ETC1_RGB8_OES:
658 if (context->getExtensions().compressedETC1RGB8Texture)
659 {
660 context->handleError(Error(GL_INVALID_OPERATION));
661 return false;
662 }
663 else
664 {
665 context->handleError(Error(GL_INVALID_ENUM));
666 return false;
667 }
668 break;
669 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
670 if (context->getExtensions().lossyETCDecode)
671 {
672 context->handleError(
673 Error(GL_INVALID_OPERATION,
674 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
675 return false;
676 }
677 else
678 {
679 context->handleError(Error(
680 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
681 return false;
682 }
683 break;
684 case GL_DEPTH_COMPONENT:
685 case GL_DEPTH_STENCIL_OES:
686 if (!context->getExtensions().depthTextures)
687 {
688 context->handleError(Error(GL_INVALID_VALUE));
689 return false;
690 }
691 if (target != GL_TEXTURE_2D)
692 {
693 context->handleError(Error(GL_INVALID_OPERATION));
694 return false;
695 }
696 // OES_depth_texture supports loading depth data and multiple levels,
697 // but ANGLE_depth_texture does not
698 if (pixels != NULL || level != 0)
699 {
700 context->handleError(Error(GL_INVALID_OPERATION));
701 return false;
702 }
703 break;
704 default:
705 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400706 }
707
708 if (type == GL_FLOAT)
709 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400710 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400711 {
Jamie Madill437fa652016-05-03 15:13:24 -0400712 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400713 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400714 }
715 }
716 else if (type == GL_HALF_FLOAT_OES)
717 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400718 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 {
Jamie Madill437fa652016-05-03 15:13:24 -0400720 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400721 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 }
723 }
724 }
725
Geoff Langff5b2d52016-09-07 11:32:23 -0400726 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
727 imageSize))
728 {
729 return false;
730 }
731
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400732 return true;
733}
734
Jamie Madillc29968b2016-01-20 11:17:23 -0500735bool ValidateES2CopyTexImageParameters(ValidationContext *context,
736 GLenum target,
737 GLint level,
738 GLenum internalformat,
739 bool isSubImage,
740 GLint xoffset,
741 GLint yoffset,
742 GLint x,
743 GLint y,
744 GLsizei width,
745 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746 GLint border)
747{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500748 if (!ValidTexture2DDestinationTarget(context, target))
749 {
Jamie Madill437fa652016-05-03 15:13:24 -0400750 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500751 return false;
752 }
753
Geoff Langcc507aa2016-12-12 10:09:52 -0500754 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
755 {
756 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
757 return false;
758 }
759
Jamie Madill0c8abca2016-07-22 20:21:26 -0400760 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400761 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400762 xoffset, yoffset, 0, x, y, width, height, border,
763 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766 }
767
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700768 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400769 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400770 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771
772 // [OpenGL ES 2.0.24] table 3.9
773 if (isSubImage)
774 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400775 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800777 case GL_ALPHA:
778 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
779 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
780 {
781 context->handleError(Error(GL_INVALID_OPERATION));
782 return false;
783 }
784 break;
785 case GL_LUMINANCE:
786 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
787 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
788 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
789 colorbufferFormat != GL_RGBA8_OES)
790 {
791 context->handleError(Error(GL_INVALID_OPERATION));
792 return false;
793 }
794 break;
795 case GL_RED_EXT:
796 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
797 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
798 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
799 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
800 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
801 colorbufferFormat != GL_RGBA32F)
802 {
803 context->handleError(Error(GL_INVALID_OPERATION));
804 return false;
805 }
806 break;
807 case GL_RG_EXT:
808 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
809 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
810 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
811 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
812 colorbufferFormat != GL_RGBA32F)
813 {
814 context->handleError(Error(GL_INVALID_OPERATION));
815 return false;
816 }
817 break;
818 case GL_RGB:
819 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
820 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
821 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
822 colorbufferFormat != GL_RGBA32F)
823 {
824 context->handleError(Error(GL_INVALID_OPERATION));
825 return false;
826 }
827 break;
828 case GL_LUMINANCE_ALPHA:
829 case GL_RGBA:
830 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
831 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
832 {
833 context->handleError(Error(GL_INVALID_OPERATION));
834 return false;
835 }
836 break;
837 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
838 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
839 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
840 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
841 case GL_ETC1_RGB8_OES:
842 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400843 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400844 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800845 case GL_DEPTH_COMPONENT:
846 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800849 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400850 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400851 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400852 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500853
Jamie Madill0c8abca2016-07-22 20:21:26 -0400854 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500855 {
Jamie Madill437fa652016-05-03 15:13:24 -0400856 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500857 return false;
858 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 }
860 else
861 {
862 switch (internalformat)
863 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800864 case GL_ALPHA:
865 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
866 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
867 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
868 {
869 context->handleError(Error(GL_INVALID_OPERATION));
870 return false;
871 }
872 break;
873 case GL_LUMINANCE:
874 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
875 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
876 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
877 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
878 colorbufferFormat != GL_BGR5_A1_ANGLEX)
879 {
880 context->handleError(Error(GL_INVALID_OPERATION));
881 return false;
882 }
883 break;
884 case GL_RED_EXT:
885 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
886 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
887 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
888 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
889 colorbufferFormat != GL_BGR5_A1_ANGLEX)
890 {
891 context->handleError(Error(GL_INVALID_OPERATION));
892 return false;
893 }
894 break;
895 case GL_RG_EXT:
896 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
897 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
898 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
899 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
900 {
901 context->handleError(Error(GL_INVALID_OPERATION));
902 return false;
903 }
904 break;
905 case GL_RGB:
906 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
907 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
908 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
909 colorbufferFormat != GL_BGR5_A1_ANGLEX)
910 {
911 context->handleError(Error(GL_INVALID_OPERATION));
912 return false;
913 }
914 break;
915 case GL_LUMINANCE_ALPHA:
916 case GL_RGBA:
917 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
918 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
919 colorbufferFormat != GL_BGR5_A1_ANGLEX)
920 {
921 context->handleError(Error(GL_INVALID_OPERATION));
922 return false;
923 }
924 break;
925 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
926 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
927 if (context->getExtensions().textureCompressionDXT1)
928 {
929 context->handleError(Error(GL_INVALID_OPERATION));
930 return false;
931 }
932 else
933 {
934 context->handleError(Error(GL_INVALID_ENUM));
935 return false;
936 }
937 break;
938 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
939 if (context->getExtensions().textureCompressionDXT3)
940 {
941 context->handleError(Error(GL_INVALID_OPERATION));
942 return false;
943 }
944 else
945 {
946 context->handleError(Error(GL_INVALID_ENUM));
947 return false;
948 }
949 break;
950 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
951 if (context->getExtensions().textureCompressionDXT5)
952 {
953 context->handleError(Error(GL_INVALID_OPERATION));
954 return false;
955 }
956 else
957 {
958 context->handleError(Error(GL_INVALID_ENUM));
959 return false;
960 }
961 break;
962 case GL_ETC1_RGB8_OES:
963 if (context->getExtensions().compressedETC1RGB8Texture)
964 {
965 context->handleError(Error(GL_INVALID_OPERATION));
966 return false;
967 }
968 else
969 {
970 context->handleError(Error(GL_INVALID_ENUM));
971 return false;
972 }
973 break;
974 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
975 if (context->getExtensions().lossyETCDecode)
976 {
977 context->handleError(Error(GL_INVALID_OPERATION,
978 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
979 return false;
980 }
981 else
982 {
983 context->handleError(Error(
984 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
985 return false;
986 }
987 break;
988 case GL_DEPTH_COMPONENT:
989 case GL_DEPTH_COMPONENT16:
990 case GL_DEPTH_COMPONENT32_OES:
991 case GL_DEPTH_STENCIL_OES:
992 case GL_DEPTH24_STENCIL8_OES:
993 if (context->getExtensions().depthTextures)
994 {
995 context->handleError(Error(GL_INVALID_OPERATION));
996 return false;
997 }
998 else
999 {
1000 context->handleError(Error(GL_INVALID_ENUM));
1001 return false;
1002 }
1003 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001004 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001005 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 }
1007 }
1008
Geoff Lang784a8fd2013-09-24 12:33:16 -04001009 // If width or height is zero, it is a no-op. Return false without setting an error.
1010 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011}
1012
He Yunchaoced53ae2016-11-29 15:00:51 +08001013bool ValidateES2TexStorageParameters(Context *context,
1014 GLenum target,
1015 GLsizei levels,
1016 GLenum internalformat,
1017 GLsizei width,
1018 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019{
1020 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1021 {
Jamie Madill437fa652016-05-03 15:13:24 -04001022 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001023 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 }
1025
1026 if (width < 1 || height < 1 || levels < 1)
1027 {
Jamie Madill437fa652016-05-03 15:13:24 -04001028 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001029 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001030 }
1031
1032 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1033 {
Jamie Madill437fa652016-05-03 15:13:24 -04001034 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
1037
1038 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1039 {
Jamie Madill437fa652016-05-03 15:13:24 -04001040 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001041 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 }
1043
Geoff Lang5d601382014-07-22 15:14:06 -04001044 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1045 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 {
Jamie Madill437fa652016-05-03 15:13:24 -04001047 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001048 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 }
1050
Geoff Langaae65a42014-05-26 12:43:44 -04001051 const gl::Caps &caps = context->getCaps();
1052
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 switch (target)
1054 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001055 case GL_TEXTURE_2D:
1056 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1057 static_cast<GLuint>(height) > caps.max2DTextureSize)
1058 {
1059 context->handleError(Error(GL_INVALID_VALUE));
1060 return false;
1061 }
1062 break;
1063 case GL_TEXTURE_CUBE_MAP:
1064 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1065 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1066 {
1067 context->handleError(Error(GL_INVALID_VALUE));
1068 return false;
1069 }
1070 break;
1071 default:
1072 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001073 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 }
1075
Geoff Langc0b9ef42014-07-02 10:02:37 -04001076 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 {
1078 if (!gl::isPow2(width) || !gl::isPow2(height))
1079 {
Jamie Madill437fa652016-05-03 15:13:24 -04001080 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001081 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 }
1083 }
1084
1085 switch (internalformat)
1086 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001087 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1088 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1089 if (!context->getExtensions().textureCompressionDXT1)
1090 {
1091 context->handleError(Error(GL_INVALID_ENUM));
1092 return false;
1093 }
1094 break;
1095 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1096 if (!context->getExtensions().textureCompressionDXT3)
1097 {
1098 context->handleError(Error(GL_INVALID_ENUM));
1099 return false;
1100 }
1101 break;
1102 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1103 if (!context->getExtensions().textureCompressionDXT5)
1104 {
1105 context->handleError(Error(GL_INVALID_ENUM));
1106 return false;
1107 }
1108 break;
1109 case GL_ETC1_RGB8_OES:
1110 if (!context->getExtensions().compressedETC1RGB8Texture)
1111 {
1112 context->handleError(Error(GL_INVALID_ENUM));
1113 return false;
1114 }
1115 break;
1116 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1117 if (!context->getExtensions().lossyETCDecode)
1118 {
1119 context->handleError(
1120 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1121 return false;
1122 }
1123 break;
1124 case GL_RGBA32F_EXT:
1125 case GL_RGB32F_EXT:
1126 case GL_ALPHA32F_EXT:
1127 case GL_LUMINANCE32F_EXT:
1128 case GL_LUMINANCE_ALPHA32F_EXT:
1129 if (!context->getExtensions().textureFloat)
1130 {
1131 context->handleError(Error(GL_INVALID_ENUM));
1132 return false;
1133 }
1134 break;
1135 case GL_RGBA16F_EXT:
1136 case GL_RGB16F_EXT:
1137 case GL_ALPHA16F_EXT:
1138 case GL_LUMINANCE16F_EXT:
1139 case GL_LUMINANCE_ALPHA16F_EXT:
1140 if (!context->getExtensions().textureHalfFloat)
1141 {
1142 context->handleError(Error(GL_INVALID_ENUM));
1143 return false;
1144 }
1145 break;
1146 case GL_R8_EXT:
1147 case GL_RG8_EXT:
1148 case GL_R16F_EXT:
1149 case GL_RG16F_EXT:
1150 case GL_R32F_EXT:
1151 case GL_RG32F_EXT:
1152 if (!context->getExtensions().textureRG)
1153 {
1154 context->handleError(Error(GL_INVALID_ENUM));
1155 return false;
1156 }
1157 break;
1158 case GL_DEPTH_COMPONENT16:
1159 case GL_DEPTH_COMPONENT32_OES:
1160 case GL_DEPTH24_STENCIL8_OES:
1161 if (!context->getExtensions().depthTextures)
1162 {
1163 context->handleError(Error(GL_INVALID_ENUM));
1164 return false;
1165 }
1166 if (target != GL_TEXTURE_2D)
1167 {
1168 context->handleError(Error(GL_INVALID_OPERATION));
1169 return false;
1170 }
1171 // ANGLE_depth_texture only supports 1-level textures
1172 if (levels != 1)
1173 {
1174 context->handleError(Error(GL_INVALID_OPERATION));
1175 return false;
1176 }
1177 break;
1178 default:
1179 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 }
1181
Geoff Lang691e58c2014-12-19 17:03:25 -05001182 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183 if (!texture || texture->id() == 0)
1184 {
Jamie Madill437fa652016-05-03 15:13:24 -04001185 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001186 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001187 }
1188
Geoff Lang69cce582015-09-17 13:20:36 -04001189 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001190 {
Jamie Madill437fa652016-05-03 15:13:24 -04001191 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001192 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001193 }
1194
1195 return true;
1196}
1197
He Yunchaoced53ae2016-11-29 15:00:51 +08001198bool ValidateDiscardFramebufferEXT(Context *context,
1199 GLenum target,
1200 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001201 const GLenum *attachments)
1202{
Jamie Madillc29968b2016-01-20 11:17:23 -05001203 if (!context->getExtensions().discardFramebuffer)
1204 {
Jamie Madill437fa652016-05-03 15:13:24 -04001205 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001206 return false;
1207 }
1208
Austin Kinross08332632015-05-05 13:35:47 -07001209 bool defaultFramebuffer = false;
1210
1211 switch (target)
1212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 case GL_FRAMEBUFFER:
1214 defaultFramebuffer =
1215 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1216 break;
1217 default:
1218 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1219 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001220 }
1221
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1223 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001224}
1225
Austin Kinrossbc781f32015-10-26 09:27:38 -07001226bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1227{
1228 if (!context->getExtensions().vertexArrayObject)
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001231 return false;
1232 }
1233
1234 return ValidateBindVertexArrayBase(context, array);
1235}
1236
1237bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1238{
1239 if (!context->getExtensions().vertexArrayObject)
1240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001242 return false;
1243 }
1244
Olli Etuaho41997e72016-03-10 13:38:39 +02001245 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001246}
1247
1248bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1249{
1250 if (!context->getExtensions().vertexArrayObject)
1251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253 return false;
1254 }
1255
Olli Etuaho41997e72016-03-10 13:38:39 +02001256 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001257}
1258
1259bool ValidateIsVertexArrayOES(Context *context)
1260{
1261 if (!context->getExtensions().vertexArrayObject)
1262 {
Jamie Madill437fa652016-05-03 15:13:24 -04001263 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001264 return false;
1265 }
1266
1267 return true;
1268}
Geoff Langc5629752015-12-07 16:29:04 -05001269
1270bool ValidateProgramBinaryOES(Context *context,
1271 GLuint program,
1272 GLenum binaryFormat,
1273 const void *binary,
1274 GLint length)
1275{
1276 if (!context->getExtensions().getProgramBinary)
1277 {
Jamie Madill437fa652016-05-03 15:13:24 -04001278 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001279 return false;
1280 }
1281
1282 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1283}
1284
1285bool ValidateGetProgramBinaryOES(Context *context,
1286 GLuint program,
1287 GLsizei bufSize,
1288 GLsizei *length,
1289 GLenum *binaryFormat,
1290 void *binary)
1291{
1292 if (!context->getExtensions().getProgramBinary)
1293 {
Jamie Madill437fa652016-05-03 15:13:24 -04001294 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001295 return false;
1296 }
1297
1298 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1299}
Geoff Lange102fee2015-12-10 11:23:30 -05001300
Geoff Lang70d0f492015-12-10 17:45:46 -05001301static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1302{
1303 switch (source)
1304 {
1305 case GL_DEBUG_SOURCE_API:
1306 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1307 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1308 case GL_DEBUG_SOURCE_OTHER:
1309 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1310 return !mustBeThirdPartyOrApplication;
1311
1312 case GL_DEBUG_SOURCE_THIRD_PARTY:
1313 case GL_DEBUG_SOURCE_APPLICATION:
1314 return true;
1315
1316 default:
1317 return false;
1318 }
1319}
1320
1321static bool ValidDebugType(GLenum type)
1322{
1323 switch (type)
1324 {
1325 case GL_DEBUG_TYPE_ERROR:
1326 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1327 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1328 case GL_DEBUG_TYPE_PERFORMANCE:
1329 case GL_DEBUG_TYPE_PORTABILITY:
1330 case GL_DEBUG_TYPE_OTHER:
1331 case GL_DEBUG_TYPE_MARKER:
1332 case GL_DEBUG_TYPE_PUSH_GROUP:
1333 case GL_DEBUG_TYPE_POP_GROUP:
1334 return true;
1335
1336 default:
1337 return false;
1338 }
1339}
1340
1341static bool ValidDebugSeverity(GLenum severity)
1342{
1343 switch (severity)
1344 {
1345 case GL_DEBUG_SEVERITY_HIGH:
1346 case GL_DEBUG_SEVERITY_MEDIUM:
1347 case GL_DEBUG_SEVERITY_LOW:
1348 case GL_DEBUG_SEVERITY_NOTIFICATION:
1349 return true;
1350
1351 default:
1352 return false;
1353 }
1354}
1355
Geoff Lange102fee2015-12-10 11:23:30 -05001356bool ValidateDebugMessageControlKHR(Context *context,
1357 GLenum source,
1358 GLenum type,
1359 GLenum severity,
1360 GLsizei count,
1361 const GLuint *ids,
1362 GLboolean enabled)
1363{
1364 if (!context->getExtensions().debug)
1365 {
Jamie Madill437fa652016-05-03 15:13:24 -04001366 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001367 return false;
1368 }
1369
Geoff Lang70d0f492015-12-10 17:45:46 -05001370 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1371 {
Jamie Madill437fa652016-05-03 15:13:24 -04001372 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001373 return false;
1374 }
1375
1376 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1377 {
Jamie Madill437fa652016-05-03 15:13:24 -04001378 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001379 return false;
1380 }
1381
1382 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1383 {
Jamie Madill437fa652016-05-03 15:13:24 -04001384 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001385 return false;
1386 }
1387
1388 if (count > 0)
1389 {
1390 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1391 {
Jamie Madill437fa652016-05-03 15:13:24 -04001392 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001393 GL_INVALID_OPERATION,
1394 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1395 return false;
1396 }
1397
1398 if (severity != GL_DONT_CARE)
1399 {
Jamie Madill437fa652016-05-03 15:13:24 -04001400 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001401 Error(GL_INVALID_OPERATION,
1402 "If count is greater than zero, severity must be GL_DONT_CARE."));
1403 return false;
1404 }
1405 }
1406
Geoff Lange102fee2015-12-10 11:23:30 -05001407 return true;
1408}
1409
1410bool ValidateDebugMessageInsertKHR(Context *context,
1411 GLenum source,
1412 GLenum type,
1413 GLuint id,
1414 GLenum severity,
1415 GLsizei length,
1416 const GLchar *buf)
1417{
1418 if (!context->getExtensions().debug)
1419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001421 return false;
1422 }
1423
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001424 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001425 {
1426 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1427 // not generate an error.
1428 return false;
1429 }
1430
1431 if (!ValidDebugSeverity(severity))
1432 {
Jamie Madill437fa652016-05-03 15:13:24 -04001433 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001434 return false;
1435 }
1436
1437 if (!ValidDebugType(type))
1438 {
Jamie Madill437fa652016-05-03 15:13:24 -04001439 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001440 return false;
1441 }
1442
1443 if (!ValidDebugSource(source, true))
1444 {
Jamie Madill437fa652016-05-03 15:13:24 -04001445 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001446 return false;
1447 }
1448
1449 size_t messageLength = (length < 0) ? strlen(buf) : length;
1450 if (messageLength > context->getExtensions().maxDebugMessageLength)
1451 {
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001453 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1454 return false;
1455 }
1456
Geoff Lange102fee2015-12-10 11:23:30 -05001457 return true;
1458}
1459
1460bool ValidateDebugMessageCallbackKHR(Context *context,
1461 GLDEBUGPROCKHR callback,
1462 const void *userParam)
1463{
1464 if (!context->getExtensions().debug)
1465 {
Jamie Madill437fa652016-05-03 15:13:24 -04001466 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001467 return false;
1468 }
1469
Geoff Lange102fee2015-12-10 11:23:30 -05001470 return true;
1471}
1472
1473bool ValidateGetDebugMessageLogKHR(Context *context,
1474 GLuint count,
1475 GLsizei bufSize,
1476 GLenum *sources,
1477 GLenum *types,
1478 GLuint *ids,
1479 GLenum *severities,
1480 GLsizei *lengths,
1481 GLchar *messageLog)
1482{
1483 if (!context->getExtensions().debug)
1484 {
Jamie Madill437fa652016-05-03 15:13:24 -04001485 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001486 return false;
1487 }
1488
Geoff Lang70d0f492015-12-10 17:45:46 -05001489 if (bufSize < 0 && messageLog != nullptr)
1490 {
Jamie Madill437fa652016-05-03 15:13:24 -04001491 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001492 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1493 return false;
1494 }
1495
Geoff Lange102fee2015-12-10 11:23:30 -05001496 return true;
1497}
1498
1499bool ValidatePushDebugGroupKHR(Context *context,
1500 GLenum source,
1501 GLuint id,
1502 GLsizei length,
1503 const GLchar *message)
1504{
1505 if (!context->getExtensions().debug)
1506 {
Jamie Madill437fa652016-05-03 15:13:24 -04001507 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001508 return false;
1509 }
1510
Geoff Lang70d0f492015-12-10 17:45:46 -05001511 if (!ValidDebugSource(source, true))
1512 {
Jamie Madill437fa652016-05-03 15:13:24 -04001513 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001514 return false;
1515 }
1516
1517 size_t messageLength = (length < 0) ? strlen(message) : length;
1518 if (messageLength > context->getExtensions().maxDebugMessageLength)
1519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001521 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1522 return false;
1523 }
1524
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001525 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001526 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1527 {
Jamie Madill437fa652016-05-03 15:13:24 -04001528 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001529 Error(GL_STACK_OVERFLOW,
1530 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1531 return false;
1532 }
1533
Geoff Lange102fee2015-12-10 11:23:30 -05001534 return true;
1535}
1536
1537bool ValidatePopDebugGroupKHR(Context *context)
1538{
1539 if (!context->getExtensions().debug)
1540 {
Jamie Madill437fa652016-05-03 15:13:24 -04001541 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001542 return false;
1543 }
1544
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001545 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001546 if (currentStackSize <= 1)
1547 {
Jamie Madill437fa652016-05-03 15:13:24 -04001548 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001549 return false;
1550 }
1551
1552 return true;
1553}
1554
1555static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1556{
1557 switch (identifier)
1558 {
1559 case GL_BUFFER:
1560 if (context->getBuffer(name) == nullptr)
1561 {
Jamie Madill437fa652016-05-03 15:13:24 -04001562 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001563 return false;
1564 }
1565 return true;
1566
1567 case GL_SHADER:
1568 if (context->getShader(name) == nullptr)
1569 {
Jamie Madill437fa652016-05-03 15:13:24 -04001570 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001571 return false;
1572 }
1573 return true;
1574
1575 case GL_PROGRAM:
1576 if (context->getProgram(name) == nullptr)
1577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001579 return false;
1580 }
1581 return true;
1582
1583 case GL_VERTEX_ARRAY:
1584 if (context->getVertexArray(name) == nullptr)
1585 {
Jamie Madill437fa652016-05-03 15:13:24 -04001586 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001587 return false;
1588 }
1589 return true;
1590
1591 case GL_QUERY:
1592 if (context->getQuery(name) == nullptr)
1593 {
Jamie Madill437fa652016-05-03 15:13:24 -04001594 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001595 return false;
1596 }
1597 return true;
1598
1599 case GL_TRANSFORM_FEEDBACK:
1600 if (context->getTransformFeedback(name) == nullptr)
1601 {
Jamie Madill437fa652016-05-03 15:13:24 -04001602 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001603 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1604 return false;
1605 }
1606 return true;
1607
1608 case GL_SAMPLER:
1609 if (context->getSampler(name) == nullptr)
1610 {
Jamie Madill437fa652016-05-03 15:13:24 -04001611 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001612 return false;
1613 }
1614 return true;
1615
1616 case GL_TEXTURE:
1617 if (context->getTexture(name) == nullptr)
1618 {
Jamie Madill437fa652016-05-03 15:13:24 -04001619 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001620 return false;
1621 }
1622 return true;
1623
1624 case GL_RENDERBUFFER:
1625 if (context->getRenderbuffer(name) == nullptr)
1626 {
Jamie Madill437fa652016-05-03 15:13:24 -04001627 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001628 return false;
1629 }
1630 return true;
1631
1632 case GL_FRAMEBUFFER:
1633 if (context->getFramebuffer(name) == nullptr)
1634 {
Jamie Madill437fa652016-05-03 15:13:24 -04001635 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001636 return false;
1637 }
1638 return true;
1639
1640 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001641 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001642 return false;
1643 }
Geoff Lange102fee2015-12-10 11:23:30 -05001644}
1645
Martin Radev9d901792016-07-15 15:58:58 +03001646static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1647{
1648 size_t labelLength = 0;
1649
1650 if (length < 0)
1651 {
1652 if (label != nullptr)
1653 {
1654 labelLength = strlen(label);
1655 }
1656 }
1657 else
1658 {
1659 labelLength = static_cast<size_t>(length);
1660 }
1661
1662 if (labelLength > context->getExtensions().maxLabelLength)
1663 {
1664 context->handleError(
1665 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1666 return false;
1667 }
1668
1669 return true;
1670}
1671
Geoff Lange102fee2015-12-10 11:23:30 -05001672bool ValidateObjectLabelKHR(Context *context,
1673 GLenum identifier,
1674 GLuint name,
1675 GLsizei length,
1676 const GLchar *label)
1677{
1678 if (!context->getExtensions().debug)
1679 {
Jamie Madill437fa652016-05-03 15:13:24 -04001680 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001681 return false;
1682 }
1683
Geoff Lang70d0f492015-12-10 17:45:46 -05001684 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1685 {
1686 return false;
1687 }
1688
Martin Radev9d901792016-07-15 15:58:58 +03001689 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001690 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001691 return false;
1692 }
1693
Geoff Lange102fee2015-12-10 11:23:30 -05001694 return true;
1695}
1696
1697bool ValidateGetObjectLabelKHR(Context *context,
1698 GLenum identifier,
1699 GLuint name,
1700 GLsizei bufSize,
1701 GLsizei *length,
1702 GLchar *label)
1703{
1704 if (!context->getExtensions().debug)
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001707 return false;
1708 }
1709
Geoff Lang70d0f492015-12-10 17:45:46 -05001710 if (bufSize < 0)
1711 {
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001713 return false;
1714 }
1715
1716 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1717 {
1718 return false;
1719 }
1720
Martin Radev9d901792016-07-15 15:58:58 +03001721 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001722}
1723
1724static bool ValidateObjectPtrName(Context *context, const void *ptr)
1725{
1726 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001729 return false;
1730 }
1731
Geoff Lange102fee2015-12-10 11:23:30 -05001732 return true;
1733}
1734
1735bool ValidateObjectPtrLabelKHR(Context *context,
1736 const void *ptr,
1737 GLsizei length,
1738 const GLchar *label)
1739{
1740 if (!context->getExtensions().debug)
1741 {
Jamie Madill437fa652016-05-03 15:13:24 -04001742 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001743 return false;
1744 }
1745
Geoff Lang70d0f492015-12-10 17:45:46 -05001746 if (!ValidateObjectPtrName(context, ptr))
1747 {
1748 return false;
1749 }
1750
Martin Radev9d901792016-07-15 15:58:58 +03001751 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001752 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001753 return false;
1754 }
1755
Geoff Lange102fee2015-12-10 11:23:30 -05001756 return true;
1757}
1758
1759bool ValidateGetObjectPtrLabelKHR(Context *context,
1760 const void *ptr,
1761 GLsizei bufSize,
1762 GLsizei *length,
1763 GLchar *label)
1764{
1765 if (!context->getExtensions().debug)
1766 {
Jamie Madill437fa652016-05-03 15:13:24 -04001767 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001768 return false;
1769 }
1770
Geoff Lang70d0f492015-12-10 17:45:46 -05001771 if (bufSize < 0)
1772 {
Jamie Madill437fa652016-05-03 15:13:24 -04001773 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001774 return false;
1775 }
1776
1777 if (!ValidateObjectPtrName(context, ptr))
1778 {
1779 return false;
1780 }
1781
Martin Radev9d901792016-07-15 15:58:58 +03001782 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001783}
1784
1785bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1786{
1787 if (!context->getExtensions().debug)
1788 {
Jamie Madill437fa652016-05-03 15:13:24 -04001789 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001790 return false;
1791 }
1792
Geoff Lang70d0f492015-12-10 17:45:46 -05001793 // TODO: represent this in Context::getQueryParameterInfo.
1794 switch (pname)
1795 {
1796 case GL_DEBUG_CALLBACK_FUNCTION:
1797 case GL_DEBUG_CALLBACK_USER_PARAM:
1798 break;
1799
1800 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001802 return false;
1803 }
1804
Geoff Lange102fee2015-12-10 11:23:30 -05001805 return true;
1806}
Jamie Madillc29968b2016-01-20 11:17:23 -05001807
1808bool ValidateBlitFramebufferANGLE(Context *context,
1809 GLint srcX0,
1810 GLint srcY0,
1811 GLint srcX1,
1812 GLint srcY1,
1813 GLint dstX0,
1814 GLint dstY0,
1815 GLint dstX1,
1816 GLint dstY1,
1817 GLbitfield mask,
1818 GLenum filter)
1819{
1820 if (!context->getExtensions().framebufferBlit)
1821 {
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001823 return false;
1824 }
1825
1826 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1827 {
1828 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 GL_INVALID_OPERATION,
1831 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1832 return false;
1833 }
1834
1835 if (filter == GL_LINEAR)
1836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001838 return false;
1839 }
1840
Jamie Madill51f40ec2016-06-15 14:06:00 -04001841 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1842 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001843
1844 if (mask & GL_COLOR_BUFFER_BIT)
1845 {
1846 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1847 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1848
1849 if (readColorAttachment && drawColorAttachment)
1850 {
1851 if (!(readColorAttachment->type() == GL_TEXTURE &&
1852 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1853 readColorAttachment->type() != GL_RENDERBUFFER &&
1854 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1855 {
Jamie Madill437fa652016-05-03 15:13:24 -04001856 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001857 return false;
1858 }
1859
Geoff Langa15472a2015-08-11 11:48:03 -04001860 for (size_t drawbufferIdx = 0;
1861 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001862 {
Geoff Langa15472a2015-08-11 11:48:03 -04001863 const FramebufferAttachment *attachment =
1864 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1865 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001866 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001867 if (!(attachment->type() == GL_TEXTURE &&
1868 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1869 attachment->type() != GL_RENDERBUFFER &&
1870 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001873 return false;
1874 }
1875
1876 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001877 if (!Format::SameSized(attachment->getFormat(),
1878 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001879 {
Jamie Madill437fa652016-05-03 15:13:24 -04001880 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001881 return false;
1882 }
1883 }
1884 }
1885
Jamie Madill51f40ec2016-06-15 14:06:00 -04001886 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001887 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1888 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1889 {
Jamie Madill437fa652016-05-03 15:13:24 -04001890 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001891 return false;
1892 }
1893 }
1894 }
1895
1896 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1897 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1898 for (size_t i = 0; i < 2; i++)
1899 {
1900 if (mask & masks[i])
1901 {
1902 const FramebufferAttachment *readBuffer =
1903 readFramebuffer->getAttachment(attachments[i]);
1904 const FramebufferAttachment *drawBuffer =
1905 drawFramebuffer->getAttachment(attachments[i]);
1906
1907 if (readBuffer && drawBuffer)
1908 {
1909 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1910 dstX0, dstY0, dstX1, dstY1))
1911 {
1912 // only whole-buffer copies are permitted
He Yunchaoced53ae2016-11-29 15:00:51 +08001913 ERR("Only whole-buffer depth and stencil blits are supported by this "
Jamie Madillc29968b2016-01-20 11:17:23 -05001914 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001915 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001916 return false;
1917 }
1918
1919 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1920 {
Jamie Madill437fa652016-05-03 15:13:24 -04001921 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001922 return false;
1923 }
1924 }
1925 }
1926 }
1927
1928 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1929 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001930}
Jamie Madillc29968b2016-01-20 11:17:23 -05001931
1932bool ValidateClear(ValidationContext *context, GLbitfield mask)
1933{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001934 auto fbo = context->getGLState().getDrawFramebuffer();
1935 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001938 return false;
1939 }
1940
1941 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001944 return false;
1945 }
1946
1947 return true;
1948}
1949
1950bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1951{
1952 if (!context->getExtensions().drawBuffers)
1953 {
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001955 return false;
1956 }
1957
1958 return ValidateDrawBuffersBase(context, n, bufs);
1959}
1960
Jamie Madill73a84962016-02-12 09:27:23 -05001961bool ValidateTexImage2D(Context *context,
1962 GLenum target,
1963 GLint level,
1964 GLint internalformat,
1965 GLsizei width,
1966 GLsizei height,
1967 GLint border,
1968 GLenum format,
1969 GLenum type,
1970 const GLvoid *pixels)
1971{
Martin Radev1be913c2016-07-11 17:59:16 +03001972 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001973 {
1974 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001975 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001976 }
1977
Martin Radev1be913c2016-07-11 17:59:16 +03001978 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001979 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001980 0, 0, width, height, 1, border, format, type, -1,
1981 pixels);
1982}
1983
1984bool ValidateTexImage2DRobust(Context *context,
1985 GLenum target,
1986 GLint level,
1987 GLint internalformat,
1988 GLsizei width,
1989 GLsizei height,
1990 GLint border,
1991 GLenum format,
1992 GLenum type,
1993 GLsizei bufSize,
1994 const GLvoid *pixels)
1995{
1996 if (!ValidateRobustEntryPoint(context, bufSize))
1997 {
1998 return false;
1999 }
2000
2001 if (context->getClientMajorVersion() < 3)
2002 {
2003 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2004 0, 0, width, height, border, format, type, bufSize,
2005 pixels);
2006 }
2007
2008 ASSERT(context->getClientMajorVersion() >= 3);
2009 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2010 0, 0, width, height, 1, border, format, type, bufSize,
2011 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002012}
2013
2014bool ValidateTexSubImage2D(Context *context,
2015 GLenum target,
2016 GLint level,
2017 GLint xoffset,
2018 GLint yoffset,
2019 GLsizei width,
2020 GLsizei height,
2021 GLenum format,
2022 GLenum type,
2023 const GLvoid *pixels)
2024{
2025
Martin Radev1be913c2016-07-11 17:59:16 +03002026 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002027 {
2028 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002029 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002030 }
2031
Martin Radev1be913c2016-07-11 17:59:16 +03002032 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002033 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002034 yoffset, 0, width, height, 1, 0, format, type, -1,
2035 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002036}
2037
Geoff Langc52f6f12016-10-14 10:18:00 -04002038bool ValidateTexSubImage2DRobustANGLE(Context *context,
2039 GLenum target,
2040 GLint level,
2041 GLint xoffset,
2042 GLint yoffset,
2043 GLsizei width,
2044 GLsizei height,
2045 GLenum format,
2046 GLenum type,
2047 GLsizei bufSize,
2048 const GLvoid *pixels)
2049{
2050 if (!ValidateRobustEntryPoint(context, bufSize))
2051 {
2052 return false;
2053 }
2054
2055 if (context->getClientMajorVersion() < 3)
2056 {
2057 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2058 yoffset, width, height, 0, format, type, bufSize,
2059 pixels);
2060 }
2061
2062 ASSERT(context->getClientMajorVersion() >= 3);
2063 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2064 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2065 pixels);
2066}
2067
Jamie Madill73a84962016-02-12 09:27:23 -05002068bool ValidateCompressedTexImage2D(Context *context,
2069 GLenum target,
2070 GLint level,
2071 GLenum internalformat,
2072 GLsizei width,
2073 GLsizei height,
2074 GLint border,
2075 GLsizei imageSize,
2076 const GLvoid *data)
2077{
Martin Radev1be913c2016-07-11 17:59:16 +03002078 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002079 {
2080 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002081 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002082 {
2083 return false;
2084 }
2085 }
2086 else
2087 {
Martin Radev1be913c2016-07-11 17:59:16 +03002088 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002089 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002090 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002091 data))
2092 {
2093 return false;
2094 }
2095 }
2096
2097 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002098 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002099 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002100 if (blockSizeOrErr.isError())
2101 {
2102 context->handleError(blockSizeOrErr.getError());
2103 return false;
2104 }
2105
2106 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002107 {
Jamie Madill437fa652016-05-03 15:13:24 -04002108 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002109 return false;
2110 }
2111
2112 return true;
2113}
2114
2115bool ValidateCompressedTexSubImage2D(Context *context,
2116 GLenum target,
2117 GLint level,
2118 GLint xoffset,
2119 GLint yoffset,
2120 GLsizei width,
2121 GLsizei height,
2122 GLenum format,
2123 GLsizei imageSize,
2124 const GLvoid *data)
2125{
Martin Radev1be913c2016-07-11 17:59:16 +03002126 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002127 {
2128 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002129 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002130 {
2131 return false;
2132 }
2133 }
2134 else
2135 {
Martin Radev1be913c2016-07-11 17:59:16 +03002136 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002137 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002138 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002139 data))
2140 {
2141 return false;
2142 }
2143 }
2144
2145 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002146 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002147 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002148 if (blockSizeOrErr.isError())
2149 {
2150 context->handleError(blockSizeOrErr.getError());
2151 return false;
2152 }
2153
2154 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002157 return false;
2158 }
2159
2160 return true;
2161}
2162
Olli Etuaho4f667482016-03-30 15:56:35 +03002163bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2164{
Geoff Lang496c02d2016-10-20 11:38:11 -07002165 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002166}
2167
2168bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2169{
2170 if (!context->getExtensions().mapBuffer)
2171 {
Jamie Madill437fa652016-05-03 15:13:24 -04002172 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002173 return false;
2174 }
2175
2176 if (!ValidBufferTarget(context, target))
2177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002179 return false;
2180 }
2181
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002182 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002183
2184 if (buffer == nullptr)
2185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002187 return false;
2188 }
2189
2190 if (access != GL_WRITE_ONLY_OES)
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002193 return false;
2194 }
2195
2196 if (buffer->isMapped())
2197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002199 return false;
2200 }
2201
2202 return true;
2203}
2204
2205bool ValidateUnmapBufferOES(Context *context, GLenum target)
2206{
2207 if (!context->getExtensions().mapBuffer)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002210 return false;
2211 }
2212
2213 return ValidateUnmapBufferBase(context, target);
2214}
2215
2216bool ValidateMapBufferRangeEXT(Context *context,
2217 GLenum target,
2218 GLintptr offset,
2219 GLsizeiptr length,
2220 GLbitfield access)
2221{
2222 if (!context->getExtensions().mapBufferRange)
2223 {
Jamie Madill437fa652016-05-03 15:13:24 -04002224 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002225 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2226 return false;
2227 }
2228
2229 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2230}
2231
2232bool ValidateFlushMappedBufferRangeEXT(Context *context,
2233 GLenum target,
2234 GLintptr offset,
2235 GLsizeiptr length)
2236{
2237 if (!context->getExtensions().mapBufferRange)
2238 {
Jamie Madill437fa652016-05-03 15:13:24 -04002239 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002240 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2241 return false;
2242 }
2243
2244 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2245}
2246
Ian Ewell54f87462016-03-10 13:47:21 -05002247bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2248{
2249 Texture *textureObject = context->getTexture(texture);
2250 if (textureObject && textureObject->getTarget() != target && texture != 0)
2251 {
Jamie Madill437fa652016-05-03 15:13:24 -04002252 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002253 return false;
2254 }
2255
Geoff Langf41a7152016-09-19 15:11:17 -04002256 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2257 !context->isTextureGenerated(texture))
2258 {
2259 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2260 return false;
2261 }
2262
Ian Ewell54f87462016-03-10 13:47:21 -05002263 switch (target)
2264 {
2265 case GL_TEXTURE_2D:
2266 case GL_TEXTURE_CUBE_MAP:
2267 break;
2268
2269 case GL_TEXTURE_3D:
2270 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002271 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002272 {
Jamie Madill437fa652016-05-03 15:13:24 -04002273 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002274 return false;
2275 }
2276 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002277
2278 case GL_TEXTURE_2D_MULTISAMPLE:
2279 if (context->getClientVersion() < Version(3, 1))
2280 {
2281 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2282 return false;
2283 }
Geoff Lang3b573612016-10-31 14:08:10 -04002284 break;
2285
Ian Ewell54f87462016-03-10 13:47:21 -05002286 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002287 if (!context->getExtensions().eglImageExternal &&
2288 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002289 {
Jamie Madill437fa652016-05-03 15:13:24 -04002290 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002291 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2292 return false;
2293 }
2294 break;
2295 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002296 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002297 return false;
2298 }
2299
2300 return true;
2301}
2302
Geoff Langd8605522016-04-13 10:19:12 -04002303bool ValidateBindUniformLocationCHROMIUM(Context *context,
2304 GLuint program,
2305 GLint location,
2306 const GLchar *name)
2307{
2308 if (!context->getExtensions().bindUniformLocation)
2309 {
Jamie Madill437fa652016-05-03 15:13:24 -04002310 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002311 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2312 return false;
2313 }
2314
2315 Program *programObject = GetValidProgram(context, program);
2316 if (!programObject)
2317 {
2318 return false;
2319 }
2320
2321 if (location < 0)
2322 {
Jamie Madill437fa652016-05-03 15:13:24 -04002323 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002324 return false;
2325 }
2326
2327 const Caps &caps = context->getCaps();
2328 if (static_cast<size_t>(location) >=
2329 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2330 {
Jamie Madill437fa652016-05-03 15:13:24 -04002331 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002332 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2333 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2334 return false;
2335 }
2336
2337 if (strncmp(name, "gl_", 3) == 0)
2338 {
Jamie Madill437fa652016-05-03 15:13:24 -04002339 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002340 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2341 return false;
2342 }
2343
2344 return true;
2345}
2346
Jamie Madille2e406c2016-06-02 13:04:10 -04002347bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002348{
2349 if (!context->getExtensions().framebufferMixedSamples)
2350 {
2351 context->handleError(
2352 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2353 return false;
2354 }
2355 switch (components)
2356 {
2357 case GL_RGB:
2358 case GL_RGBA:
2359 case GL_ALPHA:
2360 case GL_NONE:
2361 break;
2362 default:
2363 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002364 Error(GL_INVALID_ENUM,
2365 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002366 return false;
2367 }
2368
2369 return true;
2370}
2371
Sami Väisänene45e53b2016-05-25 10:36:04 +03002372// CHROMIUM_path_rendering
2373
2374bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2375{
2376 if (!context->getExtensions().pathRendering)
2377 {
2378 context->handleError(
2379 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2380 return false;
2381 }
2382 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2383 {
2384 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2385 return false;
2386 }
2387 if (matrix == nullptr)
2388 {
2389 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2390 return false;
2391 }
2392 return true;
2393}
2394
2395bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2396{
2397 if (!context->getExtensions().pathRendering)
2398 {
2399 context->handleError(
2400 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2401 return false;
2402 }
2403 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2404 {
2405 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2406 return false;
2407 }
2408 return true;
2409}
2410
2411bool ValidateGenPaths(Context *context, GLsizei range)
2412{
2413 if (!context->getExtensions().pathRendering)
2414 {
2415 context->handleError(
2416 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2417 return false;
2418 }
2419
2420 // range = 0 is undefined in NV_path_rendering.
2421 // we add stricter semantic check here and require a non zero positive range.
2422 if (range <= 0)
2423 {
2424 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2425 return false;
2426 }
2427
2428 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2429 {
2430 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2431 return false;
2432 }
2433
2434 return true;
2435}
2436
2437bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2438{
2439 if (!context->getExtensions().pathRendering)
2440 {
2441 context->handleError(
2442 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2443 return false;
2444 }
2445
2446 // range = 0 is undefined in NV_path_rendering.
2447 // we add stricter semantic check here and require a non zero positive range.
2448 if (range <= 0)
2449 {
2450 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2451 return false;
2452 }
2453
2454 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2455 checkedRange += range;
2456
2457 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2458 {
2459 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2460 return false;
2461 }
2462 return true;
2463}
2464
2465bool ValidatePathCommands(Context *context,
2466 GLuint path,
2467 GLsizei numCommands,
2468 const GLubyte *commands,
2469 GLsizei numCoords,
2470 GLenum coordType,
2471 const void *coords)
2472{
2473 if (!context->getExtensions().pathRendering)
2474 {
2475 context->handleError(
2476 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2477 return false;
2478 }
2479 if (!context->hasPath(path))
2480 {
2481 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2482 return false;
2483 }
2484
2485 if (numCommands < 0)
2486 {
2487 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2488 return false;
2489 }
2490 else if (numCommands > 0)
2491 {
2492 if (!commands)
2493 {
2494 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2495 return false;
2496 }
2497 }
2498
2499 if (numCoords < 0)
2500 {
2501 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2502 return false;
2503 }
2504 else if (numCoords > 0)
2505 {
2506 if (!coords)
2507 {
2508 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2509 return false;
2510 }
2511 }
2512
2513 std::uint32_t coordTypeSize = 0;
2514 switch (coordType)
2515 {
2516 case GL_BYTE:
2517 coordTypeSize = sizeof(GLbyte);
2518 break;
2519
2520 case GL_UNSIGNED_BYTE:
2521 coordTypeSize = sizeof(GLubyte);
2522 break;
2523
2524 case GL_SHORT:
2525 coordTypeSize = sizeof(GLshort);
2526 break;
2527
2528 case GL_UNSIGNED_SHORT:
2529 coordTypeSize = sizeof(GLushort);
2530 break;
2531
2532 case GL_FLOAT:
2533 coordTypeSize = sizeof(GLfloat);
2534 break;
2535
2536 default:
2537 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2538 return false;
2539 }
2540
2541 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2542 checkedSize += (coordTypeSize * numCoords);
2543 if (!checkedSize.IsValid())
2544 {
2545 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2546 return false;
2547 }
2548
2549 // early return skips command data validation when it doesn't exist.
2550 if (!commands)
2551 return true;
2552
2553 GLsizei expectedNumCoords = 0;
2554 for (GLsizei i = 0; i < numCommands; ++i)
2555 {
2556 switch (commands[i])
2557 {
2558 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2559 break;
2560 case GL_MOVE_TO_CHROMIUM:
2561 case GL_LINE_TO_CHROMIUM:
2562 expectedNumCoords += 2;
2563 break;
2564 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2565 expectedNumCoords += 4;
2566 break;
2567 case GL_CUBIC_CURVE_TO_CHROMIUM:
2568 expectedNumCoords += 6;
2569 break;
2570 case GL_CONIC_CURVE_TO_CHROMIUM:
2571 expectedNumCoords += 5;
2572 break;
2573 default:
2574 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2575 return false;
2576 }
2577 }
2578 if (expectedNumCoords != numCoords)
2579 {
2580 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2581 return false;
2582 }
2583
2584 return true;
2585}
2586
2587bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2588{
2589 if (!context->getExtensions().pathRendering)
2590 {
2591 context->handleError(
2592 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2593 return false;
2594 }
2595 if (!context->hasPath(path))
2596 {
2597 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2598 return false;
2599 }
2600
2601 switch (pname)
2602 {
2603 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2604 if (value < 0.0f)
2605 {
2606 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2607 return false;
2608 }
2609 break;
2610 case GL_PATH_END_CAPS_CHROMIUM:
2611 switch (static_cast<GLenum>(value))
2612 {
2613 case GL_FLAT_CHROMIUM:
2614 case GL_SQUARE_CHROMIUM:
2615 case GL_ROUND_CHROMIUM:
2616 break;
2617 default:
2618 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2619 return false;
2620 }
2621 break;
2622 case GL_PATH_JOIN_STYLE_CHROMIUM:
2623 switch (static_cast<GLenum>(value))
2624 {
2625 case GL_MITER_REVERT_CHROMIUM:
2626 case GL_BEVEL_CHROMIUM:
2627 case GL_ROUND_CHROMIUM:
2628 break;
2629 default:
2630 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2631 return false;
2632 }
2633 case GL_PATH_MITER_LIMIT_CHROMIUM:
2634 if (value < 0.0f)
2635 {
2636 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2637 return false;
2638 }
2639 break;
2640
2641 case GL_PATH_STROKE_BOUND_CHROMIUM:
2642 // no errors, only clamping.
2643 break;
2644
2645 default:
2646 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2647 return false;
2648 }
2649 return true;
2650}
2651
2652bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2653{
2654 if (!context->getExtensions().pathRendering)
2655 {
2656 context->handleError(
2657 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2658 return false;
2659 }
2660
2661 if (!context->hasPath(path))
2662 {
2663 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2664 return false;
2665 }
2666 if (!value)
2667 {
2668 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2669 return false;
2670 }
2671
2672 switch (pname)
2673 {
2674 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2675 case GL_PATH_END_CAPS_CHROMIUM:
2676 case GL_PATH_JOIN_STYLE_CHROMIUM:
2677 case GL_PATH_MITER_LIMIT_CHROMIUM:
2678 case GL_PATH_STROKE_BOUND_CHROMIUM:
2679 break;
2680
2681 default:
2682 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2683 return false;
2684 }
2685
2686 return true;
2687}
2688
2689bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2690{
2691 if (!context->getExtensions().pathRendering)
2692 {
2693 context->handleError(
2694 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2695 return false;
2696 }
2697
2698 switch (func)
2699 {
2700 case GL_NEVER:
2701 case GL_ALWAYS:
2702 case GL_LESS:
2703 case GL_LEQUAL:
2704 case GL_EQUAL:
2705 case GL_GEQUAL:
2706 case GL_GREATER:
2707 case GL_NOTEQUAL:
2708 break;
2709 default:
2710 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2711 return false;
2712 }
2713
2714 return true;
2715}
2716
2717// Note that the spec specifies that for the path drawing commands
2718// if the path object is not an existing path object the command
2719// does nothing and no error is generated.
2720// However if the path object exists but has not been specified any
2721// commands then an error is generated.
2722
2723bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2724{
2725 if (!context->getExtensions().pathRendering)
2726 {
2727 context->handleError(
2728 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2729 return false;
2730 }
2731 if (context->hasPath(path) && !context->hasPathData(path))
2732 {
2733 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2734 return false;
2735 }
2736
2737 switch (fillMode)
2738 {
2739 case GL_COUNT_UP_CHROMIUM:
2740 case GL_COUNT_DOWN_CHROMIUM:
2741 break;
2742 default:
2743 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2744 return false;
2745 }
2746
2747 if (!isPow2(mask + 1))
2748 {
2749 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2750 return false;
2751 }
2752
2753 return true;
2754}
2755
2756bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2757{
2758 if (!context->getExtensions().pathRendering)
2759 {
2760 context->handleError(
2761 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2762 return false;
2763 }
2764 if (context->hasPath(path) && !context->hasPathData(path))
2765 {
2766 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2767 return false;
2768 }
2769
2770 return true;
2771}
2772
2773bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2774{
2775 if (!context->getExtensions().pathRendering)
2776 {
2777 context->handleError(
2778 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2779 return false;
2780 }
2781 if (context->hasPath(path) && !context->hasPathData(path))
2782 {
2783 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2784 return false;
2785 }
2786
2787 switch (coverMode)
2788 {
2789 case GL_CONVEX_HULL_CHROMIUM:
2790 case GL_BOUNDING_BOX_CHROMIUM:
2791 break;
2792 default:
2793 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2794 return false;
2795 }
2796 return true;
2797}
2798
2799bool ValidateStencilThenCoverFillPath(Context *context,
2800 GLuint path,
2801 GLenum fillMode,
2802 GLuint mask,
2803 GLenum coverMode)
2804{
2805 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2806 ValidateCoverPath(context, path, coverMode);
2807}
2808
2809bool ValidateStencilThenCoverStrokePath(Context *context,
2810 GLuint path,
2811 GLint reference,
2812 GLuint mask,
2813 GLenum coverMode)
2814{
2815 return ValidateStencilStrokePath(context, path, reference, mask) &&
2816 ValidateCoverPath(context, path, coverMode);
2817}
2818
2819bool ValidateIsPath(Context *context)
2820{
2821 if (!context->getExtensions().pathRendering)
2822 {
2823 context->handleError(
2824 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2825 return false;
2826 }
2827 return true;
2828}
2829
Sami Väisänend59ca052016-06-21 16:10:00 +03002830bool ValidateCoverFillPathInstanced(Context *context,
2831 GLsizei numPaths,
2832 GLenum pathNameType,
2833 const void *paths,
2834 GLuint pathBase,
2835 GLenum coverMode,
2836 GLenum transformType,
2837 const GLfloat *transformValues)
2838{
2839 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2840 transformType, transformValues))
2841 return false;
2842
2843 switch (coverMode)
2844 {
2845 case GL_CONVEX_HULL_CHROMIUM:
2846 case GL_BOUNDING_BOX_CHROMIUM:
2847 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2848 break;
2849 default:
2850 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2851 return false;
2852 }
2853
2854 return true;
2855}
2856
2857bool ValidateCoverStrokePathInstanced(Context *context,
2858 GLsizei numPaths,
2859 GLenum pathNameType,
2860 const void *paths,
2861 GLuint pathBase,
2862 GLenum coverMode,
2863 GLenum transformType,
2864 const GLfloat *transformValues)
2865{
2866 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2867 transformType, transformValues))
2868 return false;
2869
2870 switch (coverMode)
2871 {
2872 case GL_CONVEX_HULL_CHROMIUM:
2873 case GL_BOUNDING_BOX_CHROMIUM:
2874 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2875 break;
2876 default:
2877 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2878 return false;
2879 }
2880
2881 return true;
2882}
2883
2884bool ValidateStencilFillPathInstanced(Context *context,
2885 GLsizei numPaths,
2886 GLenum pathNameType,
2887 const void *paths,
2888 GLuint pathBase,
2889 GLenum fillMode,
2890 GLuint mask,
2891 GLenum transformType,
2892 const GLfloat *transformValues)
2893{
2894
2895 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2896 transformType, transformValues))
2897 return false;
2898
2899 switch (fillMode)
2900 {
2901 case GL_COUNT_UP_CHROMIUM:
2902 case GL_COUNT_DOWN_CHROMIUM:
2903 break;
2904 default:
2905 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2906 return false;
2907 }
2908 if (!isPow2(mask + 1))
2909 {
2910 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2911 return false;
2912 }
2913 return true;
2914}
2915
2916bool ValidateStencilStrokePathInstanced(Context *context,
2917 GLsizei numPaths,
2918 GLenum pathNameType,
2919 const void *paths,
2920 GLuint pathBase,
2921 GLint reference,
2922 GLuint mask,
2923 GLenum transformType,
2924 const GLfloat *transformValues)
2925{
2926 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2927 transformType, transformValues))
2928 return false;
2929
2930 // no more validation here.
2931
2932 return true;
2933}
2934
2935bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2936 GLsizei numPaths,
2937 GLenum pathNameType,
2938 const void *paths,
2939 GLuint pathBase,
2940 GLenum fillMode,
2941 GLuint mask,
2942 GLenum coverMode,
2943 GLenum transformType,
2944 const GLfloat *transformValues)
2945{
2946 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2947 transformType, transformValues))
2948 return false;
2949
2950 switch (coverMode)
2951 {
2952 case GL_CONVEX_HULL_CHROMIUM:
2953 case GL_BOUNDING_BOX_CHROMIUM:
2954 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2955 break;
2956 default:
2957 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2958 return false;
2959 }
2960
2961 switch (fillMode)
2962 {
2963 case GL_COUNT_UP_CHROMIUM:
2964 case GL_COUNT_DOWN_CHROMIUM:
2965 break;
2966 default:
2967 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2968 return false;
2969 }
2970 if (!isPow2(mask + 1))
2971 {
2972 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2973 return false;
2974 }
2975
2976 return true;
2977}
2978
2979bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2980 GLsizei numPaths,
2981 GLenum pathNameType,
2982 const void *paths,
2983 GLuint pathBase,
2984 GLint reference,
2985 GLuint mask,
2986 GLenum coverMode,
2987 GLenum transformType,
2988 const GLfloat *transformValues)
2989{
2990 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2991 transformType, transformValues))
2992 return false;
2993
2994 switch (coverMode)
2995 {
2996 case GL_CONVEX_HULL_CHROMIUM:
2997 case GL_BOUNDING_BOX_CHROMIUM:
2998 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2999 break;
3000 default:
3001 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3002 return false;
3003 }
3004
3005 return true;
3006}
3007
Sami Väisänen46eaa942016-06-29 10:26:37 +03003008bool ValidateBindFragmentInputLocation(Context *context,
3009 GLuint program,
3010 GLint location,
3011 const GLchar *name)
3012{
3013 if (!context->getExtensions().pathRendering)
3014 {
3015 context->handleError(
3016 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3017 return false;
3018 }
3019
3020 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3021 if (location >= MaxLocation)
3022 {
3023 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3024 return false;
3025 }
3026
3027 const auto *programObject = context->getProgram(program);
3028 if (!programObject)
3029 {
3030 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3031 return false;
3032 }
3033
3034 if (!name)
3035 {
3036 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3037 return false;
3038 }
3039
3040 if (angle::BeginsWith(name, "gl_"))
3041 {
3042 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3043 return false;
3044 }
3045
3046 return true;
3047}
3048
3049bool ValidateProgramPathFragmentInputGen(Context *context,
3050 GLuint program,
3051 GLint location,
3052 GLenum genMode,
3053 GLint components,
3054 const GLfloat *coeffs)
3055{
3056 if (!context->getExtensions().pathRendering)
3057 {
3058 context->handleError(
3059 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3060 return false;
3061 }
3062
3063 const auto *programObject = context->getProgram(program);
3064 if (!programObject || programObject->isFlaggedForDeletion())
3065 {
3066 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3067 return false;
3068 }
3069
3070 if (!programObject->isLinked())
3071 {
3072 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3073 return false;
3074 }
3075
3076 switch (genMode)
3077 {
3078 case GL_NONE:
3079 if (components != 0)
3080 {
3081 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3082 return false;
3083 }
3084 break;
3085
3086 case GL_OBJECT_LINEAR_CHROMIUM:
3087 case GL_EYE_LINEAR_CHROMIUM:
3088 case GL_CONSTANT_CHROMIUM:
3089 if (components < 1 || components > 4)
3090 {
3091 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3092 return false;
3093 }
3094 if (!coeffs)
3095 {
3096 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3097 return false;
3098 }
3099 break;
3100
3101 default:
3102 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3103 return false;
3104 }
3105
3106 // If the location is -1 then the command is silently ignored
3107 // and no further validation is needed.
3108 if (location == -1)
3109 return true;
3110
3111 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3112
3113 if (!binding.valid)
3114 {
3115 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3116 return false;
3117 }
3118
3119 if (binding.type != GL_NONE)
3120 {
3121 GLint expectedComponents = 0;
3122 switch (binding.type)
3123 {
3124 case GL_FLOAT:
3125 expectedComponents = 1;
3126 break;
3127 case GL_FLOAT_VEC2:
3128 expectedComponents = 2;
3129 break;
3130 case GL_FLOAT_VEC3:
3131 expectedComponents = 3;
3132 break;
3133 case GL_FLOAT_VEC4:
3134 expectedComponents = 4;
3135 break;
3136 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003137 context->handleError(
3138 Error(GL_INVALID_OPERATION,
3139 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003140 return false;
3141 }
3142 if (expectedComponents != components && genMode != GL_NONE)
3143 {
3144 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3145 return false;
3146 }
3147 }
3148 return true;
3149}
3150
Geoff Lang97073d12016-04-20 10:42:34 -07003151bool ValidateCopyTextureCHROMIUM(Context *context,
3152 GLuint sourceId,
3153 GLuint destId,
3154 GLint internalFormat,
3155 GLenum destType,
3156 GLboolean unpackFlipY,
3157 GLboolean unpackPremultiplyAlpha,
3158 GLboolean unpackUnmultiplyAlpha)
3159{
3160 if (!context->getExtensions().copyTexture)
3161 {
3162 context->handleError(
3163 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3164 return false;
3165 }
3166
3167 const gl::Texture *source = context->getTexture(sourceId);
3168 if (source == nullptr)
3169 {
3170 context->handleError(
3171 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3172 return false;
3173 }
3174
3175 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3176 {
3177 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3178 return false;
3179 }
3180
3181 GLenum sourceTarget = source->getTarget();
3182 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3183 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3184 {
3185 context->handleError(
3186 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3187 return false;
3188 }
3189
3190 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3191 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3192 {
3193 context->handleError(
3194 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3195 return false;
3196 }
3197
3198 const gl::Texture *dest = context->getTexture(destId);
3199 if (dest == nullptr)
3200 {
3201 context->handleError(
3202 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3203 return false;
3204 }
3205
3206 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3207 {
3208 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3209 return false;
3210 }
3211
3212 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3213 {
3214 context->handleError(
3215 Error(GL_INVALID_OPERATION,
3216 "Destination internal format and type combination is not valid."));
3217 return false;
3218 }
3219
3220 if (dest->getImmutableFormat())
3221 {
3222 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3223 return false;
3224 }
3225
3226 return true;
3227}
3228
3229bool ValidateCopySubTextureCHROMIUM(Context *context,
3230 GLuint sourceId,
3231 GLuint destId,
3232 GLint xoffset,
3233 GLint yoffset,
3234 GLint x,
3235 GLint y,
3236 GLsizei width,
3237 GLsizei height,
3238 GLboolean unpackFlipY,
3239 GLboolean unpackPremultiplyAlpha,
3240 GLboolean unpackUnmultiplyAlpha)
3241{
3242 if (!context->getExtensions().copyTexture)
3243 {
3244 context->handleError(
3245 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3246 return false;
3247 }
3248
3249 const gl::Texture *source = context->getTexture(sourceId);
3250 if (source == nullptr)
3251 {
3252 context->handleError(
3253 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3254 return false;
3255 }
3256
3257 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3258 {
3259 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3260 return false;
3261 }
3262
3263 GLenum sourceTarget = source->getTarget();
3264 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3265 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3266 {
3267 context->handleError(
3268 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3269 return false;
3270 }
3271
3272 if (x < 0 || y < 0)
3273 {
3274 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3275 return false;
3276 }
3277
3278 if (width < 0 || height < 0)
3279 {
3280 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3281 return false;
3282 }
3283
3284 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3285 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3286 {
3287 context->handleError(
3288 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3289 return false;
3290 }
3291
3292 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3293 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3294 {
3295 context->handleError(
3296 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3297 return false;
3298 }
3299
3300 const gl::Texture *dest = context->getTexture(destId);
3301 if (dest == nullptr)
3302 {
3303 context->handleError(
3304 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3305 return false;
3306 }
3307
3308 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3309 {
3310 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3311 return false;
3312 }
3313
3314 GLenum destTarget = dest->getTarget();
3315 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3316 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3317 {
3318 context->handleError(
3319 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3320 return false;
3321 }
3322
3323 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3324 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3325 {
3326 context->handleError(
3327 Error(GL_INVALID_OPERATION,
3328 "Destination internal format and type combination is not valid."));
3329 return false;
3330 }
3331
3332 if (xoffset < 0 || yoffset < 0)
3333 {
3334 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3335 return false;
3336 }
3337
3338 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3339 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3340 {
3341 context->handleError(
3342 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3343 return false;
3344 }
3345
3346 return true;
3347}
3348
Geoff Lang47110bf2016-04-20 11:13:22 -07003349bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3350{
3351 if (!context->getExtensions().copyCompressedTexture)
3352 {
3353 context->handleError(Error(GL_INVALID_OPERATION,
3354 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3355 return false;
3356 }
3357
3358 const gl::Texture *source = context->getTexture(sourceId);
3359 if (source == nullptr)
3360 {
3361 context->handleError(
3362 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3363 return false;
3364 }
3365
3366 if (source->getTarget() != GL_TEXTURE_2D)
3367 {
3368 context->handleError(
3369 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3370 return false;
3371 }
3372
3373 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3374 {
3375 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3376 return false;
3377 }
3378
3379 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3380 if (!sourceFormat.info->compressed)
3381 {
3382 context->handleError(
3383 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3384 return false;
3385 }
3386
3387 const gl::Texture *dest = context->getTexture(destId);
3388 if (dest == nullptr)
3389 {
3390 context->handleError(
3391 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3392 return false;
3393 }
3394
3395 if (dest->getTarget() != GL_TEXTURE_2D)
3396 {
3397 context->handleError(
3398 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3399 return false;
3400 }
3401
3402 if (dest->getImmutableFormat())
3403 {
3404 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3405 return false;
3406 }
3407
3408 return true;
3409}
3410
Martin Radev4c4c8e72016-08-04 12:25:34 +03003411bool ValidateCreateShader(Context *context, GLenum type)
3412{
3413 switch (type)
3414 {
3415 case GL_VERTEX_SHADER:
3416 case GL_FRAGMENT_SHADER:
3417 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003418
Martin Radev4c4c8e72016-08-04 12:25:34 +03003419 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003420 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003421 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003422 context->handleError(
3423 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3424 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003425 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003426 break;
3427
Martin Radev4c4c8e72016-08-04 12:25:34 +03003428 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003429 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003430 return false;
3431 }
Jamie Madill29639852016-09-02 15:00:09 -04003432
3433 return true;
3434}
3435
3436bool ValidateBufferData(ValidationContext *context,
3437 GLenum target,
3438 GLsizeiptr size,
3439 const GLvoid *data,
3440 GLenum usage)
3441{
3442 if (size < 0)
3443 {
3444 context->handleError(Error(GL_INVALID_VALUE));
3445 return false;
3446 }
3447
3448 switch (usage)
3449 {
3450 case GL_STREAM_DRAW:
3451 case GL_STATIC_DRAW:
3452 case GL_DYNAMIC_DRAW:
3453 break;
3454
3455 case GL_STREAM_READ:
3456 case GL_STREAM_COPY:
3457 case GL_STATIC_READ:
3458 case GL_STATIC_COPY:
3459 case GL_DYNAMIC_READ:
3460 case GL_DYNAMIC_COPY:
3461 if (context->getClientMajorVersion() < 3)
3462 {
3463 context->handleError(Error(GL_INVALID_ENUM));
3464 return false;
3465 }
3466 break;
3467
3468 default:
3469 context->handleError(Error(GL_INVALID_ENUM));
3470 return false;
3471 }
3472
3473 if (!ValidBufferTarget(context, target))
3474 {
3475 context->handleError(Error(GL_INVALID_ENUM));
3476 return false;
3477 }
3478
3479 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3480
3481 if (!buffer)
3482 {
3483 context->handleError(Error(GL_INVALID_OPERATION));
3484 return false;
3485 }
3486
3487 return true;
3488}
3489
3490bool ValidateBufferSubData(ValidationContext *context,
3491 GLenum target,
3492 GLintptr offset,
3493 GLsizeiptr size,
3494 const GLvoid *data)
3495{
3496 if (size < 0 || offset < 0)
3497 {
3498 context->handleError(Error(GL_INVALID_VALUE));
3499 return false;
3500 }
3501
3502 if (!ValidBufferTarget(context, target))
3503 {
3504 context->handleError(Error(GL_INVALID_ENUM));
3505 return false;
3506 }
3507
3508 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3509
3510 if (!buffer)
3511 {
3512 context->handleError(Error(GL_INVALID_OPERATION));
3513 return false;
3514 }
3515
3516 if (buffer->isMapped())
3517 {
3518 context->handleError(Error(GL_INVALID_OPERATION));
3519 return false;
3520 }
3521
3522 // Check for possible overflow of size + offset
3523 angle::CheckedNumeric<size_t> checkedSize(size);
3524 checkedSize += offset;
3525 if (!checkedSize.IsValid())
3526 {
3527 context->handleError(Error(GL_OUT_OF_MEMORY));
3528 return false;
3529 }
3530
3531 if (size + offset > buffer->getSize())
3532 {
3533 context->handleError(Error(GL_INVALID_VALUE));
3534 return false;
3535 }
3536
Martin Radev4c4c8e72016-08-04 12:25:34 +03003537 return true;
3538}
3539
Geoff Langc339c4e2016-11-29 10:37:36 -05003540bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003541{
Geoff Langc339c4e2016-11-29 10:37:36 -05003542 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003543 {
3544 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003545 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003546 return false;
3547 }
3548
3549 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3550 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003551 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003552 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003553 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003554 return false;
3555 }
3556
3557 return true;
3558}
3559
Jamie Madillef300b12016-10-07 15:12:09 -04003560bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3561{
3562 if (texture < GL_TEXTURE0 ||
3563 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3564 {
3565 context->handleError(Error(GL_INVALID_ENUM));
3566 return false;
3567 }
3568
3569 return true;
3570}
3571
3572bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3573{
3574 Program *programObject = GetValidProgram(context, program);
3575 if (!programObject)
3576 {
3577 return false;
3578 }
3579
3580 Shader *shaderObject = GetValidShader(context, shader);
3581 if (!shaderObject)
3582 {
3583 return false;
3584 }
3585
3586 switch (shaderObject->getType())
3587 {
3588 case GL_VERTEX_SHADER:
3589 {
3590 if (programObject->getAttachedVertexShader())
3591 {
3592 context->handleError(Error(GL_INVALID_OPERATION));
3593 return false;
3594 }
3595 break;
3596 }
3597 case GL_FRAGMENT_SHADER:
3598 {
3599 if (programObject->getAttachedFragmentShader())
3600 {
3601 context->handleError(Error(GL_INVALID_OPERATION));
3602 return false;
3603 }
3604 break;
3605 }
3606 case GL_COMPUTE_SHADER:
3607 {
3608 if (programObject->getAttachedComputeShader())
3609 {
3610 context->handleError(Error(GL_INVALID_OPERATION));
3611 return false;
3612 }
3613 break;
3614 }
3615 default:
3616 UNREACHABLE();
3617 break;
3618 }
3619
3620 return true;
3621}
3622
Jamie Madill01a80ee2016-11-07 12:06:18 -05003623bool ValidateBindAttribLocation(ValidationContext *context,
3624 GLuint program,
3625 GLuint index,
3626 const GLchar *name)
3627{
3628 if (index >= MAX_VERTEX_ATTRIBS)
3629 {
3630 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3631 return false;
3632 }
3633
3634 if (strncmp(name, "gl_", 3) == 0)
3635 {
3636 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3637 return false;
3638 }
3639
3640 return GetValidProgram(context, program) != nullptr;
3641}
3642
3643bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3644{
3645 if (!ValidBufferTarget(context, target))
3646 {
3647 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3648 return false;
3649 }
3650
3651 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3652 !context->isBufferGenerated(buffer))
3653 {
3654 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3655 return false;
3656 }
3657
3658 return true;
3659}
3660
3661bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3662{
3663 if (!ValidFramebufferTarget(target))
3664 {
3665 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3666 return false;
3667 }
3668
3669 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3670 !context->isFramebufferGenerated(framebuffer))
3671 {
3672 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3673 return false;
3674 }
3675
3676 return true;
3677}
3678
3679bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3680{
3681 if (target != GL_RENDERBUFFER)
3682 {
3683 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3684 return false;
3685 }
3686
3687 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3688 !context->isRenderbufferGenerated(renderbuffer))
3689 {
3690 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3691 return false;
3692 }
3693
3694 return true;
3695}
3696
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003697static bool ValidBlendEquationMode(GLenum mode)
3698{
3699 switch (mode)
3700 {
3701 case GL_FUNC_ADD:
3702 case GL_FUNC_SUBTRACT:
3703 case GL_FUNC_REVERSE_SUBTRACT:
3704 case GL_MIN:
3705 case GL_MAX:
3706 return true;
3707
3708 default:
3709 return false;
3710 }
3711}
3712
3713bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3714{
3715 if (!ValidBlendEquationMode(mode))
3716 {
3717 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3718 return false;
3719 }
3720
3721 return true;
3722}
3723
3724bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3725{
3726 if (!ValidBlendEquationMode(modeRGB))
3727 {
3728 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3729 return false;
3730 }
3731
3732 if (!ValidBlendEquationMode(modeAlpha))
3733 {
3734 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3735 return false;
3736 }
3737
3738 return true;
3739}
3740
3741bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3742{
3743 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3744}
3745
3746static bool ValidSrcBlendFunc(GLenum srcBlend)
3747{
3748 switch (srcBlend)
3749 {
3750 case GL_ZERO:
3751 case GL_ONE:
3752 case GL_SRC_COLOR:
3753 case GL_ONE_MINUS_SRC_COLOR:
3754 case GL_DST_COLOR:
3755 case GL_ONE_MINUS_DST_COLOR:
3756 case GL_SRC_ALPHA:
3757 case GL_ONE_MINUS_SRC_ALPHA:
3758 case GL_DST_ALPHA:
3759 case GL_ONE_MINUS_DST_ALPHA:
3760 case GL_CONSTANT_COLOR:
3761 case GL_ONE_MINUS_CONSTANT_COLOR:
3762 case GL_CONSTANT_ALPHA:
3763 case GL_ONE_MINUS_CONSTANT_ALPHA:
3764 case GL_SRC_ALPHA_SATURATE:
3765 return true;
3766
3767 default:
3768 return false;
3769 }
3770}
3771
3772static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3773{
3774 switch (dstBlend)
3775 {
3776 case GL_ZERO:
3777 case GL_ONE:
3778 case GL_SRC_COLOR:
3779 case GL_ONE_MINUS_SRC_COLOR:
3780 case GL_DST_COLOR:
3781 case GL_ONE_MINUS_DST_COLOR:
3782 case GL_SRC_ALPHA:
3783 case GL_ONE_MINUS_SRC_ALPHA:
3784 case GL_DST_ALPHA:
3785 case GL_ONE_MINUS_DST_ALPHA:
3786 case GL_CONSTANT_COLOR:
3787 case GL_ONE_MINUS_CONSTANT_COLOR:
3788 case GL_CONSTANT_ALPHA:
3789 case GL_ONE_MINUS_CONSTANT_ALPHA:
3790 return true;
3791
3792 case GL_SRC_ALPHA_SATURATE:
3793 return (contextMajorVersion >= 3);
3794
3795 default:
3796 return false;
3797 }
3798}
3799
3800bool ValidateBlendFuncSeparate(ValidationContext *context,
3801 GLenum srcRGB,
3802 GLenum dstRGB,
3803 GLenum srcAlpha,
3804 GLenum dstAlpha)
3805{
3806 if (!ValidSrcBlendFunc(srcRGB))
3807 {
3808 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3809 return false;
3810 }
3811
3812 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3813 {
3814 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3815 return false;
3816 }
3817
3818 if (!ValidSrcBlendFunc(srcAlpha))
3819 {
3820 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3821 return false;
3822 }
3823
3824 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3825 {
3826 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3827 return false;
3828 }
3829
3830 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3831 {
3832 bool constantColorUsed =
3833 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3834 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3835
3836 bool constantAlphaUsed =
3837 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3838 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3839
3840 if (constantColorUsed && constantAlphaUsed)
3841 {
3842 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3843 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3844 "implementation.");
3845 context->handleError(Error(GL_INVALID_OPERATION,
3846 "Simultaneous use of "
3847 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3848 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3849 "supported by this implementation."));
3850 return false;
3851 }
3852 }
3853
3854 return true;
3855}
3856
Geoff Langc339c4e2016-11-29 10:37:36 -05003857bool ValidateGetString(Context *context, GLenum name)
3858{
3859 switch (name)
3860 {
3861 case GL_VENDOR:
3862 case GL_RENDERER:
3863 case GL_VERSION:
3864 case GL_SHADING_LANGUAGE_VERSION:
3865 case GL_EXTENSIONS:
3866 break;
3867
3868 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3869 if (!context->getExtensions().requestExtension)
3870 {
3871 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3872 return false;
3873 }
3874 break;
3875
3876 default:
3877 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3878 return false;
3879 }
3880
3881 return true;
3882}
3883
Geoff Lang47c48082016-12-07 15:38:13 -05003884bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3885{
3886 if (width <= 0.0f || isNaN(width))
3887 {
3888 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3889 return false;
3890 }
3891
3892 return true;
3893}
3894
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003895bool ValidateVertexAttribPointer(ValidationContext *context,
3896 GLuint index,
3897 GLint size,
3898 GLenum type,
3899 GLboolean normalized,
3900 GLsizei stride,
3901 const GLvoid *ptr)
3902{
3903 if (index >= MAX_VERTEX_ATTRIBS)
3904 {
3905 context->handleError(Error(GL_INVALID_VALUE, "Invalid index value."));
3906 return false;
3907 }
3908
3909 if (size < 1 || size > 4)
3910 {
3911 context->handleError(Error(GL_INVALID_VALUE, "Invalide size value."));
3912 return false;
3913 }
3914
3915 switch (type)
3916 {
3917 case GL_BYTE:
3918 case GL_UNSIGNED_BYTE:
3919 case GL_SHORT:
3920 case GL_UNSIGNED_SHORT:
3921 case GL_FIXED:
3922 case GL_FLOAT:
3923 break;
3924
3925 case GL_HALF_FLOAT:
3926 case GL_INT:
3927 case GL_UNSIGNED_INT:
3928 case GL_INT_2_10_10_10_REV:
3929 case GL_UNSIGNED_INT_2_10_10_10_REV:
3930 if (context->getClientMajorVersion() < 3)
3931 {
3932 context->handleError(
3933 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
3934 return false;
3935 }
3936 break;
3937
3938 default:
3939 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
3940 return false;
3941 }
3942
3943 if (stride < 0)
3944 {
3945 context->handleError(Error(GL_INVALID_VALUE, "Invalid stride."));
3946 return false;
3947 }
3948
3949 if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
3950 {
3951 context->handleError(Error(GL_INVALID_OPERATION, "Invalid size for a sized vertex type."));
3952 return false;
3953 }
3954
3955 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3956 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3957 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3958 // and the pointer argument is not NULL.
3959 if (context->getGLState().getVertexArray()->id() != 0 &&
3960 context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
3961 {
3962 context->handleError(
3963 Error(GL_INVALID_OPERATION,
3964 "Pointer is null with a non-zero VAO bound and zero bound to GL_ARRAY_BUFFER."));
3965 return false;
3966 }
3967
3968 if (context->getExtensions().webglCompatibility)
3969 {
3970 // WebGL 1.0 [Section 6.14] Fixed point support
3971 // The WebGL API does not support the GL_FIXED data type.
3972 if (type == GL_FIXED)
3973 {
3974 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3975 return false;
3976 }
3977
3978 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
3979 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
3980 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
3981 // parameter exceeds 255.
3982 constexpr GLsizei kMaxWebGLStride = 255;
3983 if (stride > kMaxWebGLStride)
3984 {
3985 context->handleError(
3986 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
3987 return false;
3988 }
3989
3990 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
3991 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
3992 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
3993 // or an INVALID_OPERATION error is generated.
3994 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, false);
3995 size_t typeSize = GetVertexFormatTypeSize(internalType);
3996
3997 ASSERT(isPow2(typeSize) && typeSize > 0);
3998 size_t sizeMask = (typeSize - 1);
3999 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
4000 {
4001 context->handleError(
4002 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
4003 return false;
4004 }
4005
4006 if ((stride & sizeMask) != 0)
4007 {
4008 context->handleError(
4009 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
4010 return false;
4011 }
4012 }
4013
4014 return true;
4015}
4016
Jamie Madillc29968b2016-01-20 11:17:23 -05004017} // namespace gl