blob: 4deb90ab45fbfecc4577e3cc02d4ba15ae3c0782 [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;
439 case GL_ETC1_RGB8_OES:
440 if (!context->getExtensions().compressedETC1RGB8Texture)
441 {
442 context->handleError(Error(GL_INVALID_ENUM));
443 return false;
444 }
445 break;
446 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
447 if (!context->getExtensions().lossyETCDecode)
448 {
449 context->handleError(Error(
450 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
451 return false;
452 }
453 break;
454 default:
455 context->handleError(
456 Error(GL_INVALID_ENUM,
457 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400458 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400459 }
460 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
461 {
Jamie Madill437fa652016-05-03 15:13:24 -0400462 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400463 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400464 }
465 }
466 else
467 {
468 // validate <type> by itself (used as secondary key below)
469 switch (type)
470 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800471 case GL_UNSIGNED_BYTE:
472 case GL_UNSIGNED_SHORT_5_6_5:
473 case GL_UNSIGNED_SHORT_4_4_4_4:
474 case GL_UNSIGNED_SHORT_5_5_5_1:
475 case GL_UNSIGNED_SHORT:
476 case GL_UNSIGNED_INT:
477 case GL_UNSIGNED_INT_24_8_OES:
478 case GL_HALF_FLOAT_OES:
479 case GL_FLOAT:
480 break;
481 default:
482 context->handleError(Error(GL_INVALID_ENUM));
483 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400484 }
485
486 // validate <format> + <type> combinations
487 // - invalid <format> -> sets INVALID_ENUM
488 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
489 switch (format)
490 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800491 case GL_ALPHA:
492 case GL_LUMINANCE:
493 case GL_LUMINANCE_ALPHA:
494 switch (type)
495 {
496 case GL_UNSIGNED_BYTE:
497 case GL_FLOAT:
498 case GL_HALF_FLOAT_OES:
499 break;
500 default:
501 context->handleError(Error(GL_INVALID_OPERATION));
502 return false;
503 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400504 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800505 case GL_RED:
506 case GL_RG:
507 if (!context->getExtensions().textureRG)
508 {
509 context->handleError(Error(GL_INVALID_ENUM));
510 return false;
511 }
512 switch (type)
513 {
514 case GL_UNSIGNED_BYTE:
515 case GL_FLOAT:
516 case GL_HALF_FLOAT_OES:
517 break;
518 default:
519 context->handleError(Error(GL_INVALID_OPERATION));
520 return false;
521 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400522 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800523 case GL_RGB:
524 switch (type)
525 {
526 case GL_UNSIGNED_BYTE:
527 case GL_UNSIGNED_SHORT_5_6_5:
528 case GL_FLOAT:
529 case GL_HALF_FLOAT_OES:
530 break;
531 default:
532 context->handleError(Error(GL_INVALID_OPERATION));
533 return false;
534 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400535 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800536 case GL_RGBA:
537 switch (type)
538 {
539 case GL_UNSIGNED_BYTE:
540 case GL_UNSIGNED_SHORT_4_4_4_4:
541 case GL_UNSIGNED_SHORT_5_5_5_1:
542 case GL_FLOAT:
543 case GL_HALF_FLOAT_OES:
544 break;
545 default:
546 context->handleError(Error(GL_INVALID_OPERATION));
547 return false;
548 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400549 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800550 case GL_BGRA_EXT:
551 switch (type)
552 {
553 case GL_UNSIGNED_BYTE:
554 break;
555 default:
556 context->handleError(Error(GL_INVALID_OPERATION));
557 return false;
558 }
559 break;
560 case GL_SRGB_EXT:
561 case GL_SRGB_ALPHA_EXT:
562 if (!context->getExtensions().sRGB)
563 {
564 context->handleError(Error(GL_INVALID_ENUM));
565 return false;
566 }
567 switch (type)
568 {
569 case GL_UNSIGNED_BYTE:
570 break;
571 default:
572 context->handleError(Error(GL_INVALID_OPERATION));
573 return false;
574 }
575 break;
576 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
577 // handled below
578 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
579 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
580 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
581 break;
582 case GL_DEPTH_COMPONENT:
583 switch (type)
584 {
585 case GL_UNSIGNED_SHORT:
586 case GL_UNSIGNED_INT:
587 break;
588 default:
589 context->handleError(Error(GL_INVALID_OPERATION));
590 return false;
591 }
592 break;
593 case GL_DEPTH_STENCIL_OES:
594 switch (type)
595 {
596 case GL_UNSIGNED_INT_24_8_OES:
597 break;
598 default:
599 context->handleError(Error(GL_INVALID_OPERATION));
600 return false;
601 }
602 break;
603 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400604 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400606 }
607
608 switch (format)
609 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800610 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
611 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
612 if (context->getExtensions().textureCompressionDXT1)
613 {
614 context->handleError(Error(GL_INVALID_OPERATION));
615 return false;
616 }
617 else
618 {
619 context->handleError(Error(GL_INVALID_ENUM));
620 return false;
621 }
622 break;
623 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
624 if (context->getExtensions().textureCompressionDXT3)
625 {
626 context->handleError(Error(GL_INVALID_OPERATION));
627 return false;
628 }
629 else
630 {
631 context->handleError(Error(GL_INVALID_ENUM));
632 return false;
633 }
634 break;
635 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
636 if (context->getExtensions().textureCompressionDXT5)
637 {
638 context->handleError(Error(GL_INVALID_OPERATION));
639 return false;
640 }
641 else
642 {
643 context->handleError(Error(GL_INVALID_ENUM));
644 return false;
645 }
646 break;
647 case GL_ETC1_RGB8_OES:
648 if (context->getExtensions().compressedETC1RGB8Texture)
649 {
650 context->handleError(Error(GL_INVALID_OPERATION));
651 return false;
652 }
653 else
654 {
655 context->handleError(Error(GL_INVALID_ENUM));
656 return false;
657 }
658 break;
659 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
660 if (context->getExtensions().lossyETCDecode)
661 {
662 context->handleError(
663 Error(GL_INVALID_OPERATION,
664 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
665 return false;
666 }
667 else
668 {
669 context->handleError(Error(
670 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
671 return false;
672 }
673 break;
674 case GL_DEPTH_COMPONENT:
675 case GL_DEPTH_STENCIL_OES:
676 if (!context->getExtensions().depthTextures)
677 {
678 context->handleError(Error(GL_INVALID_VALUE));
679 return false;
680 }
681 if (target != GL_TEXTURE_2D)
682 {
683 context->handleError(Error(GL_INVALID_OPERATION));
684 return false;
685 }
686 // OES_depth_texture supports loading depth data and multiple levels,
687 // but ANGLE_depth_texture does not
688 if (pixels != NULL || level != 0)
689 {
690 context->handleError(Error(GL_INVALID_OPERATION));
691 return false;
692 }
693 break;
694 default:
695 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696 }
697
698 if (type == GL_FLOAT)
699 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400700 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701 {
Jamie Madill437fa652016-05-03 15:13:24 -0400702 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400703 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400704 }
705 }
706 else if (type == GL_HALF_FLOAT_OES)
707 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400708 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400709 {
Jamie Madill437fa652016-05-03 15:13:24 -0400710 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400711 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712 }
713 }
714 }
715
Geoff Langff5b2d52016-09-07 11:32:23 -0400716 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
717 imageSize))
718 {
719 return false;
720 }
721
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 return true;
723}
724
Jamie Madillc29968b2016-01-20 11:17:23 -0500725bool ValidateES2CopyTexImageParameters(ValidationContext *context,
726 GLenum target,
727 GLint level,
728 GLenum internalformat,
729 bool isSubImage,
730 GLint xoffset,
731 GLint yoffset,
732 GLint x,
733 GLint y,
734 GLsizei width,
735 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400736 GLint border)
737{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500738 if (!ValidTexture2DDestinationTarget(context, target))
739 {
Jamie Madill437fa652016-05-03 15:13:24 -0400740 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500741 return false;
742 }
743
Geoff Langcc507aa2016-12-12 10:09:52 -0500744 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
745 {
746 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
747 return false;
748 }
749
Jamie Madill0c8abca2016-07-22 20:21:26 -0400750 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400751 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400752 xoffset, yoffset, 0, x, y, width, height, border,
753 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400755 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400756 }
757
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700758 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400759 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400760 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400761
762 // [OpenGL ES 2.0.24] table 3.9
763 if (isSubImage)
764 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400765 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800767 case GL_ALPHA:
768 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
769 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
770 {
771 context->handleError(Error(GL_INVALID_OPERATION));
772 return false;
773 }
774 break;
775 case GL_LUMINANCE:
776 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
777 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
778 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
779 colorbufferFormat != GL_RGBA8_OES)
780 {
781 context->handleError(Error(GL_INVALID_OPERATION));
782 return false;
783 }
784 break;
785 case GL_RED_EXT:
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 && colorbufferFormat != GL_R32F &&
790 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
791 colorbufferFormat != GL_RGBA32F)
792 {
793 context->handleError(Error(GL_INVALID_OPERATION));
794 return false;
795 }
796 break;
797 case GL_RG_EXT:
798 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
799 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
800 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
801 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
802 colorbufferFormat != GL_RGBA32F)
803 {
804 context->handleError(Error(GL_INVALID_OPERATION));
805 return false;
806 }
807 break;
808 case GL_RGB:
809 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
810 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
811 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
812 colorbufferFormat != GL_RGBA32F)
813 {
814 context->handleError(Error(GL_INVALID_OPERATION));
815 return false;
816 }
817 break;
818 case GL_LUMINANCE_ALPHA:
819 case GL_RGBA:
820 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
821 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
822 {
823 context->handleError(Error(GL_INVALID_OPERATION));
824 return false;
825 }
826 break;
827 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
828 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
829 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
830 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
831 case GL_ETC1_RGB8_OES:
832 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400833 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400834 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800835 case GL_DEPTH_COMPONENT:
836 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400837 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400838 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800839 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400840 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400841 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500843
Jamie Madill0c8abca2016-07-22 20:21:26 -0400844 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500845 {
Jamie Madill437fa652016-05-03 15:13:24 -0400846 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500847 return false;
848 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 }
850 else
851 {
852 switch (internalformat)
853 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800854 case GL_ALPHA:
855 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
856 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
857 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
858 {
859 context->handleError(Error(GL_INVALID_OPERATION));
860 return false;
861 }
862 break;
863 case GL_LUMINANCE:
864 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
865 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
866 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
867 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
868 colorbufferFormat != GL_BGR5_A1_ANGLEX)
869 {
870 context->handleError(Error(GL_INVALID_OPERATION));
871 return false;
872 }
873 break;
874 case GL_RED_EXT:
875 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
876 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
877 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
878 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
879 colorbufferFormat != GL_BGR5_A1_ANGLEX)
880 {
881 context->handleError(Error(GL_INVALID_OPERATION));
882 return false;
883 }
884 break;
885 case GL_RG_EXT:
886 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
887 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
888 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
889 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
890 {
891 context->handleError(Error(GL_INVALID_OPERATION));
892 return false;
893 }
894 break;
895 case GL_RGB:
896 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
897 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
898 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
899 colorbufferFormat != GL_BGR5_A1_ANGLEX)
900 {
901 context->handleError(Error(GL_INVALID_OPERATION));
902 return false;
903 }
904 break;
905 case GL_LUMINANCE_ALPHA:
906 case GL_RGBA:
907 if (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_COMPRESSED_RGB_S3TC_DXT1_EXT:
916 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
917 if (context->getExtensions().textureCompressionDXT1)
918 {
919 context->handleError(Error(GL_INVALID_OPERATION));
920 return false;
921 }
922 else
923 {
924 context->handleError(Error(GL_INVALID_ENUM));
925 return false;
926 }
927 break;
928 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
929 if (context->getExtensions().textureCompressionDXT3)
930 {
931 context->handleError(Error(GL_INVALID_OPERATION));
932 return false;
933 }
934 else
935 {
936 context->handleError(Error(GL_INVALID_ENUM));
937 return false;
938 }
939 break;
940 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
941 if (context->getExtensions().textureCompressionDXT5)
942 {
943 context->handleError(Error(GL_INVALID_OPERATION));
944 return false;
945 }
946 else
947 {
948 context->handleError(Error(GL_INVALID_ENUM));
949 return false;
950 }
951 break;
952 case GL_ETC1_RGB8_OES:
953 if (context->getExtensions().compressedETC1RGB8Texture)
954 {
955 context->handleError(Error(GL_INVALID_OPERATION));
956 return false;
957 }
958 else
959 {
960 context->handleError(Error(GL_INVALID_ENUM));
961 return false;
962 }
963 break;
964 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
965 if (context->getExtensions().lossyETCDecode)
966 {
967 context->handleError(Error(GL_INVALID_OPERATION,
968 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
969 return false;
970 }
971 else
972 {
973 context->handleError(Error(
974 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
975 return false;
976 }
977 break;
978 case GL_DEPTH_COMPONENT:
979 case GL_DEPTH_COMPONENT16:
980 case GL_DEPTH_COMPONENT32_OES:
981 case GL_DEPTH_STENCIL_OES:
982 case GL_DEPTH24_STENCIL8_OES:
983 if (context->getExtensions().depthTextures)
984 {
985 context->handleError(Error(GL_INVALID_OPERATION));
986 return false;
987 }
988 else
989 {
990 context->handleError(Error(GL_INVALID_ENUM));
991 return false;
992 }
993 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400994 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400996 }
997 }
998
Geoff Lang784a8fd2013-09-24 12:33:16 -0400999 // If width or height is zero, it is a no-op. Return false without setting an error.
1000 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001001}
1002
He Yunchaoced53ae2016-11-29 15:00:51 +08001003bool ValidateES2TexStorageParameters(Context *context,
1004 GLenum target,
1005 GLsizei levels,
1006 GLenum internalformat,
1007 GLsizei width,
1008 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001009{
1010 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1011 {
Jamie Madill437fa652016-05-03 15:13:24 -04001012 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 }
1015
1016 if (width < 1 || height < 1 || levels < 1)
1017 {
Jamie Madill437fa652016-05-03 15:13:24 -04001018 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001019 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 }
1021
1022 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1023 {
Jamie Madill437fa652016-05-03 15:13:24 -04001024 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 }
1027
1028 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1029 {
Jamie Madill437fa652016-05-03 15:13:24 -04001030 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 }
1033
Geoff Lang5d601382014-07-22 15:14:06 -04001034 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1035 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 {
Jamie Madill437fa652016-05-03 15:13:24 -04001037 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001038 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 }
1040
Geoff Langaae65a42014-05-26 12:43:44 -04001041 const gl::Caps &caps = context->getCaps();
1042
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001043 switch (target)
1044 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001045 case GL_TEXTURE_2D:
1046 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1047 static_cast<GLuint>(height) > caps.max2DTextureSize)
1048 {
1049 context->handleError(Error(GL_INVALID_VALUE));
1050 return false;
1051 }
1052 break;
1053 case GL_TEXTURE_CUBE_MAP:
1054 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1055 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1056 {
1057 context->handleError(Error(GL_INVALID_VALUE));
1058 return false;
1059 }
1060 break;
1061 default:
1062 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001063 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 }
1065
Geoff Langc0b9ef42014-07-02 10:02:37 -04001066 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001067 {
1068 if (!gl::isPow2(width) || !gl::isPow2(height))
1069 {
Jamie Madill437fa652016-05-03 15:13:24 -04001070 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001072 }
1073 }
1074
1075 switch (internalformat)
1076 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1078 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1079 if (!context->getExtensions().textureCompressionDXT1)
1080 {
1081 context->handleError(Error(GL_INVALID_ENUM));
1082 return false;
1083 }
1084 break;
1085 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1086 if (!context->getExtensions().textureCompressionDXT3)
1087 {
1088 context->handleError(Error(GL_INVALID_ENUM));
1089 return false;
1090 }
1091 break;
1092 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1093 if (!context->getExtensions().textureCompressionDXT5)
1094 {
1095 context->handleError(Error(GL_INVALID_ENUM));
1096 return false;
1097 }
1098 break;
1099 case GL_ETC1_RGB8_OES:
1100 if (!context->getExtensions().compressedETC1RGB8Texture)
1101 {
1102 context->handleError(Error(GL_INVALID_ENUM));
1103 return false;
1104 }
1105 break;
1106 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1107 if (!context->getExtensions().lossyETCDecode)
1108 {
1109 context->handleError(
1110 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1111 return false;
1112 }
1113 break;
1114 case GL_RGBA32F_EXT:
1115 case GL_RGB32F_EXT:
1116 case GL_ALPHA32F_EXT:
1117 case GL_LUMINANCE32F_EXT:
1118 case GL_LUMINANCE_ALPHA32F_EXT:
1119 if (!context->getExtensions().textureFloat)
1120 {
1121 context->handleError(Error(GL_INVALID_ENUM));
1122 return false;
1123 }
1124 break;
1125 case GL_RGBA16F_EXT:
1126 case GL_RGB16F_EXT:
1127 case GL_ALPHA16F_EXT:
1128 case GL_LUMINANCE16F_EXT:
1129 case GL_LUMINANCE_ALPHA16F_EXT:
1130 if (!context->getExtensions().textureHalfFloat)
1131 {
1132 context->handleError(Error(GL_INVALID_ENUM));
1133 return false;
1134 }
1135 break;
1136 case GL_R8_EXT:
1137 case GL_RG8_EXT:
1138 case GL_R16F_EXT:
1139 case GL_RG16F_EXT:
1140 case GL_R32F_EXT:
1141 case GL_RG32F_EXT:
1142 if (!context->getExtensions().textureRG)
1143 {
1144 context->handleError(Error(GL_INVALID_ENUM));
1145 return false;
1146 }
1147 break;
1148 case GL_DEPTH_COMPONENT16:
1149 case GL_DEPTH_COMPONENT32_OES:
1150 case GL_DEPTH24_STENCIL8_OES:
1151 if (!context->getExtensions().depthTextures)
1152 {
1153 context->handleError(Error(GL_INVALID_ENUM));
1154 return false;
1155 }
1156 if (target != GL_TEXTURE_2D)
1157 {
1158 context->handleError(Error(GL_INVALID_OPERATION));
1159 return false;
1160 }
1161 // ANGLE_depth_texture only supports 1-level textures
1162 if (levels != 1)
1163 {
1164 context->handleError(Error(GL_INVALID_OPERATION));
1165 return false;
1166 }
1167 break;
1168 default:
1169 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 }
1171
Geoff Lang691e58c2014-12-19 17:03:25 -05001172 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 if (!texture || texture->id() == 0)
1174 {
Jamie Madill437fa652016-05-03 15:13:24 -04001175 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001176 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001177 }
1178
Geoff Lang69cce582015-09-17 13:20:36 -04001179 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 {
Jamie Madill437fa652016-05-03 15:13:24 -04001181 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001182 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183 }
1184
1185 return true;
1186}
1187
He Yunchaoced53ae2016-11-29 15:00:51 +08001188bool ValidateDiscardFramebufferEXT(Context *context,
1189 GLenum target,
1190 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001191 const GLenum *attachments)
1192{
Jamie Madillc29968b2016-01-20 11:17:23 -05001193 if (!context->getExtensions().discardFramebuffer)
1194 {
Jamie Madill437fa652016-05-03 15:13:24 -04001195 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001196 return false;
1197 }
1198
Austin Kinross08332632015-05-05 13:35:47 -07001199 bool defaultFramebuffer = false;
1200
1201 switch (target)
1202 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 case GL_FRAMEBUFFER:
1204 defaultFramebuffer =
1205 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1206 break;
1207 default:
1208 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1209 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001210 }
1211
He Yunchaoced53ae2016-11-29 15:00:51 +08001212 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1213 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001214}
1215
Austin Kinrossbc781f32015-10-26 09:27:38 -07001216bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1217{
1218 if (!context->getExtensions().vertexArrayObject)
1219 {
Jamie Madill437fa652016-05-03 15:13:24 -04001220 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001221 return false;
1222 }
1223
1224 return ValidateBindVertexArrayBase(context, array);
1225}
1226
1227bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1228{
1229 if (!context->getExtensions().vertexArrayObject)
1230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001232 return false;
1233 }
1234
Olli Etuaho41997e72016-03-10 13:38:39 +02001235 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001236}
1237
1238bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1239{
1240 if (!context->getExtensions().vertexArrayObject)
1241 {
Jamie Madill437fa652016-05-03 15:13:24 -04001242 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001243 return false;
1244 }
1245
Olli Etuaho41997e72016-03-10 13:38:39 +02001246 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001247}
1248
1249bool ValidateIsVertexArrayOES(Context *context)
1250{
1251 if (!context->getExtensions().vertexArrayObject)
1252 {
Jamie Madill437fa652016-05-03 15:13:24 -04001253 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001254 return false;
1255 }
1256
1257 return true;
1258}
Geoff Langc5629752015-12-07 16:29:04 -05001259
1260bool ValidateProgramBinaryOES(Context *context,
1261 GLuint program,
1262 GLenum binaryFormat,
1263 const void *binary,
1264 GLint length)
1265{
1266 if (!context->getExtensions().getProgramBinary)
1267 {
Jamie Madill437fa652016-05-03 15:13:24 -04001268 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001269 return false;
1270 }
1271
1272 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1273}
1274
1275bool ValidateGetProgramBinaryOES(Context *context,
1276 GLuint program,
1277 GLsizei bufSize,
1278 GLsizei *length,
1279 GLenum *binaryFormat,
1280 void *binary)
1281{
1282 if (!context->getExtensions().getProgramBinary)
1283 {
Jamie Madill437fa652016-05-03 15:13:24 -04001284 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001285 return false;
1286 }
1287
1288 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1289}
Geoff Lange102fee2015-12-10 11:23:30 -05001290
Geoff Lang70d0f492015-12-10 17:45:46 -05001291static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1292{
1293 switch (source)
1294 {
1295 case GL_DEBUG_SOURCE_API:
1296 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1297 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1298 case GL_DEBUG_SOURCE_OTHER:
1299 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1300 return !mustBeThirdPartyOrApplication;
1301
1302 case GL_DEBUG_SOURCE_THIRD_PARTY:
1303 case GL_DEBUG_SOURCE_APPLICATION:
1304 return true;
1305
1306 default:
1307 return false;
1308 }
1309}
1310
1311static bool ValidDebugType(GLenum type)
1312{
1313 switch (type)
1314 {
1315 case GL_DEBUG_TYPE_ERROR:
1316 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1317 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1318 case GL_DEBUG_TYPE_PERFORMANCE:
1319 case GL_DEBUG_TYPE_PORTABILITY:
1320 case GL_DEBUG_TYPE_OTHER:
1321 case GL_DEBUG_TYPE_MARKER:
1322 case GL_DEBUG_TYPE_PUSH_GROUP:
1323 case GL_DEBUG_TYPE_POP_GROUP:
1324 return true;
1325
1326 default:
1327 return false;
1328 }
1329}
1330
1331static bool ValidDebugSeverity(GLenum severity)
1332{
1333 switch (severity)
1334 {
1335 case GL_DEBUG_SEVERITY_HIGH:
1336 case GL_DEBUG_SEVERITY_MEDIUM:
1337 case GL_DEBUG_SEVERITY_LOW:
1338 case GL_DEBUG_SEVERITY_NOTIFICATION:
1339 return true;
1340
1341 default:
1342 return false;
1343 }
1344}
1345
Geoff Lange102fee2015-12-10 11:23:30 -05001346bool ValidateDebugMessageControlKHR(Context *context,
1347 GLenum source,
1348 GLenum type,
1349 GLenum severity,
1350 GLsizei count,
1351 const GLuint *ids,
1352 GLboolean enabled)
1353{
1354 if (!context->getExtensions().debug)
1355 {
Jamie Madill437fa652016-05-03 15:13:24 -04001356 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001357 return false;
1358 }
1359
Geoff Lang70d0f492015-12-10 17:45:46 -05001360 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1361 {
Jamie Madill437fa652016-05-03 15:13:24 -04001362 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001363 return false;
1364 }
1365
1366 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1367 {
Jamie Madill437fa652016-05-03 15:13:24 -04001368 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001369 return false;
1370 }
1371
1372 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1373 {
Jamie Madill437fa652016-05-03 15:13:24 -04001374 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001375 return false;
1376 }
1377
1378 if (count > 0)
1379 {
1380 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1381 {
Jamie Madill437fa652016-05-03 15:13:24 -04001382 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001383 GL_INVALID_OPERATION,
1384 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1385 return false;
1386 }
1387
1388 if (severity != GL_DONT_CARE)
1389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001391 Error(GL_INVALID_OPERATION,
1392 "If count is greater than zero, severity must be GL_DONT_CARE."));
1393 return false;
1394 }
1395 }
1396
Geoff Lange102fee2015-12-10 11:23:30 -05001397 return true;
1398}
1399
1400bool ValidateDebugMessageInsertKHR(Context *context,
1401 GLenum source,
1402 GLenum type,
1403 GLuint id,
1404 GLenum severity,
1405 GLsizei length,
1406 const GLchar *buf)
1407{
1408 if (!context->getExtensions().debug)
1409 {
Jamie Madill437fa652016-05-03 15:13:24 -04001410 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001411 return false;
1412 }
1413
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001414 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001415 {
1416 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1417 // not generate an error.
1418 return false;
1419 }
1420
1421 if (!ValidDebugSeverity(severity))
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001424 return false;
1425 }
1426
1427 if (!ValidDebugType(type))
1428 {
Jamie Madill437fa652016-05-03 15:13:24 -04001429 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001430 return false;
1431 }
1432
1433 if (!ValidDebugSource(source, true))
1434 {
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001436 return false;
1437 }
1438
1439 size_t messageLength = (length < 0) ? strlen(buf) : length;
1440 if (messageLength > context->getExtensions().maxDebugMessageLength)
1441 {
Jamie Madill437fa652016-05-03 15:13:24 -04001442 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001443 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1444 return false;
1445 }
1446
Geoff Lange102fee2015-12-10 11:23:30 -05001447 return true;
1448}
1449
1450bool ValidateDebugMessageCallbackKHR(Context *context,
1451 GLDEBUGPROCKHR callback,
1452 const void *userParam)
1453{
1454 if (!context->getExtensions().debug)
1455 {
Jamie Madill437fa652016-05-03 15:13:24 -04001456 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001457 return false;
1458 }
1459
Geoff Lange102fee2015-12-10 11:23:30 -05001460 return true;
1461}
1462
1463bool ValidateGetDebugMessageLogKHR(Context *context,
1464 GLuint count,
1465 GLsizei bufSize,
1466 GLenum *sources,
1467 GLenum *types,
1468 GLuint *ids,
1469 GLenum *severities,
1470 GLsizei *lengths,
1471 GLchar *messageLog)
1472{
1473 if (!context->getExtensions().debug)
1474 {
Jamie Madill437fa652016-05-03 15:13:24 -04001475 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001476 return false;
1477 }
1478
Geoff Lang70d0f492015-12-10 17:45:46 -05001479 if (bufSize < 0 && messageLog != nullptr)
1480 {
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001482 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1483 return false;
1484 }
1485
Geoff Lange102fee2015-12-10 11:23:30 -05001486 return true;
1487}
1488
1489bool ValidatePushDebugGroupKHR(Context *context,
1490 GLenum source,
1491 GLuint id,
1492 GLsizei length,
1493 const GLchar *message)
1494{
1495 if (!context->getExtensions().debug)
1496 {
Jamie Madill437fa652016-05-03 15:13:24 -04001497 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001498 return false;
1499 }
1500
Geoff Lang70d0f492015-12-10 17:45:46 -05001501 if (!ValidDebugSource(source, true))
1502 {
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001504 return false;
1505 }
1506
1507 size_t messageLength = (length < 0) ? strlen(message) : length;
1508 if (messageLength > context->getExtensions().maxDebugMessageLength)
1509 {
Jamie Madill437fa652016-05-03 15:13:24 -04001510 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001511 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1512 return false;
1513 }
1514
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001515 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001516 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1517 {
Jamie Madill437fa652016-05-03 15:13:24 -04001518 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001519 Error(GL_STACK_OVERFLOW,
1520 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1521 return false;
1522 }
1523
Geoff Lange102fee2015-12-10 11:23:30 -05001524 return true;
1525}
1526
1527bool ValidatePopDebugGroupKHR(Context *context)
1528{
1529 if (!context->getExtensions().debug)
1530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001532 return false;
1533 }
1534
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001535 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001536 if (currentStackSize <= 1)
1537 {
Jamie Madill437fa652016-05-03 15:13:24 -04001538 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001539 return false;
1540 }
1541
1542 return true;
1543}
1544
1545static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1546{
1547 switch (identifier)
1548 {
1549 case GL_BUFFER:
1550 if (context->getBuffer(name) == nullptr)
1551 {
Jamie Madill437fa652016-05-03 15:13:24 -04001552 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001553 return false;
1554 }
1555 return true;
1556
1557 case GL_SHADER:
1558 if (context->getShader(name) == nullptr)
1559 {
Jamie Madill437fa652016-05-03 15:13:24 -04001560 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001561 return false;
1562 }
1563 return true;
1564
1565 case GL_PROGRAM:
1566 if (context->getProgram(name) == nullptr)
1567 {
Jamie Madill437fa652016-05-03 15:13:24 -04001568 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001569 return false;
1570 }
1571 return true;
1572
1573 case GL_VERTEX_ARRAY:
1574 if (context->getVertexArray(name) == nullptr)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001577 return false;
1578 }
1579 return true;
1580
1581 case GL_QUERY:
1582 if (context->getQuery(name) == nullptr)
1583 {
Jamie Madill437fa652016-05-03 15:13:24 -04001584 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001585 return false;
1586 }
1587 return true;
1588
1589 case GL_TRANSFORM_FEEDBACK:
1590 if (context->getTransformFeedback(name) == nullptr)
1591 {
Jamie Madill437fa652016-05-03 15:13:24 -04001592 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001593 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1594 return false;
1595 }
1596 return true;
1597
1598 case GL_SAMPLER:
1599 if (context->getSampler(name) == nullptr)
1600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001602 return false;
1603 }
1604 return true;
1605
1606 case GL_TEXTURE:
1607 if (context->getTexture(name) == nullptr)
1608 {
Jamie Madill437fa652016-05-03 15:13:24 -04001609 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001610 return false;
1611 }
1612 return true;
1613
1614 case GL_RENDERBUFFER:
1615 if (context->getRenderbuffer(name) == nullptr)
1616 {
Jamie Madill437fa652016-05-03 15:13:24 -04001617 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001618 return false;
1619 }
1620 return true;
1621
1622 case GL_FRAMEBUFFER:
1623 if (context->getFramebuffer(name) == nullptr)
1624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001626 return false;
1627 }
1628 return true;
1629
1630 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001631 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001632 return false;
1633 }
Geoff Lange102fee2015-12-10 11:23:30 -05001634}
1635
Martin Radev9d901792016-07-15 15:58:58 +03001636static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1637{
1638 size_t labelLength = 0;
1639
1640 if (length < 0)
1641 {
1642 if (label != nullptr)
1643 {
1644 labelLength = strlen(label);
1645 }
1646 }
1647 else
1648 {
1649 labelLength = static_cast<size_t>(length);
1650 }
1651
1652 if (labelLength > context->getExtensions().maxLabelLength)
1653 {
1654 context->handleError(
1655 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1656 return false;
1657 }
1658
1659 return true;
1660}
1661
Geoff Lange102fee2015-12-10 11:23:30 -05001662bool ValidateObjectLabelKHR(Context *context,
1663 GLenum identifier,
1664 GLuint name,
1665 GLsizei length,
1666 const GLchar *label)
1667{
1668 if (!context->getExtensions().debug)
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001671 return false;
1672 }
1673
Geoff Lang70d0f492015-12-10 17:45:46 -05001674 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1675 {
1676 return false;
1677 }
1678
Martin Radev9d901792016-07-15 15:58:58 +03001679 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001680 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001681 return false;
1682 }
1683
Geoff Lange102fee2015-12-10 11:23:30 -05001684 return true;
1685}
1686
1687bool ValidateGetObjectLabelKHR(Context *context,
1688 GLenum identifier,
1689 GLuint name,
1690 GLsizei bufSize,
1691 GLsizei *length,
1692 GLchar *label)
1693{
1694 if (!context->getExtensions().debug)
1695 {
Jamie Madill437fa652016-05-03 15:13:24 -04001696 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001697 return false;
1698 }
1699
Geoff Lang70d0f492015-12-10 17:45:46 -05001700 if (bufSize < 0)
1701 {
Jamie Madill437fa652016-05-03 15:13:24 -04001702 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001703 return false;
1704 }
1705
1706 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1707 {
1708 return false;
1709 }
1710
Martin Radev9d901792016-07-15 15:58:58 +03001711 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001712}
1713
1714static bool ValidateObjectPtrName(Context *context, const void *ptr)
1715{
1716 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001719 return false;
1720 }
1721
Geoff Lange102fee2015-12-10 11:23:30 -05001722 return true;
1723}
1724
1725bool ValidateObjectPtrLabelKHR(Context *context,
1726 const void *ptr,
1727 GLsizei length,
1728 const GLchar *label)
1729{
1730 if (!context->getExtensions().debug)
1731 {
Jamie Madill437fa652016-05-03 15:13:24 -04001732 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001733 return false;
1734 }
1735
Geoff Lang70d0f492015-12-10 17:45:46 -05001736 if (!ValidateObjectPtrName(context, ptr))
1737 {
1738 return false;
1739 }
1740
Martin Radev9d901792016-07-15 15:58:58 +03001741 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001743 return false;
1744 }
1745
Geoff Lange102fee2015-12-10 11:23:30 -05001746 return true;
1747}
1748
1749bool ValidateGetObjectPtrLabelKHR(Context *context,
1750 const void *ptr,
1751 GLsizei bufSize,
1752 GLsizei *length,
1753 GLchar *label)
1754{
1755 if (!context->getExtensions().debug)
1756 {
Jamie Madill437fa652016-05-03 15:13:24 -04001757 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001758 return false;
1759 }
1760
Geoff Lang70d0f492015-12-10 17:45:46 -05001761 if (bufSize < 0)
1762 {
Jamie Madill437fa652016-05-03 15:13:24 -04001763 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001764 return false;
1765 }
1766
1767 if (!ValidateObjectPtrName(context, ptr))
1768 {
1769 return false;
1770 }
1771
Martin Radev9d901792016-07-15 15:58:58 +03001772 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001773}
1774
1775bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1776{
1777 if (!context->getExtensions().debug)
1778 {
Jamie Madill437fa652016-05-03 15:13:24 -04001779 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001780 return false;
1781 }
1782
Geoff Lang70d0f492015-12-10 17:45:46 -05001783 // TODO: represent this in Context::getQueryParameterInfo.
1784 switch (pname)
1785 {
1786 case GL_DEBUG_CALLBACK_FUNCTION:
1787 case GL_DEBUG_CALLBACK_USER_PARAM:
1788 break;
1789
1790 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001791 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001792 return false;
1793 }
1794
Geoff Lange102fee2015-12-10 11:23:30 -05001795 return true;
1796}
Jamie Madillc29968b2016-01-20 11:17:23 -05001797
1798bool ValidateBlitFramebufferANGLE(Context *context,
1799 GLint srcX0,
1800 GLint srcY0,
1801 GLint srcX1,
1802 GLint srcY1,
1803 GLint dstX0,
1804 GLint dstY0,
1805 GLint dstX1,
1806 GLint dstY1,
1807 GLbitfield mask,
1808 GLenum filter)
1809{
1810 if (!context->getExtensions().framebufferBlit)
1811 {
Jamie Madill437fa652016-05-03 15:13:24 -04001812 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 return false;
1814 }
1815
1816 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1817 {
1818 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001819 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001820 GL_INVALID_OPERATION,
1821 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1822 return false;
1823 }
1824
1825 if (filter == GL_LINEAR)
1826 {
Jamie Madill437fa652016-05-03 15:13:24 -04001827 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 return false;
1829 }
1830
Jamie Madill51f40ec2016-06-15 14:06:00 -04001831 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1832 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001833
1834 if (mask & GL_COLOR_BUFFER_BIT)
1835 {
1836 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1837 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1838
1839 if (readColorAttachment && drawColorAttachment)
1840 {
1841 if (!(readColorAttachment->type() == GL_TEXTURE &&
1842 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1843 readColorAttachment->type() != GL_RENDERBUFFER &&
1844 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1845 {
Jamie Madill437fa652016-05-03 15:13:24 -04001846 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001847 return false;
1848 }
1849
Geoff Langa15472a2015-08-11 11:48:03 -04001850 for (size_t drawbufferIdx = 0;
1851 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001852 {
Geoff Langa15472a2015-08-11 11:48:03 -04001853 const FramebufferAttachment *attachment =
1854 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1855 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001857 if (!(attachment->type() == GL_TEXTURE &&
1858 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1859 attachment->type() != GL_RENDERBUFFER &&
1860 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 return false;
1864 }
1865
1866 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001867 if (!Format::SameSized(attachment->getFormat(),
1868 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 {
Jamie Madill437fa652016-05-03 15:13:24 -04001870 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001871 return false;
1872 }
1873 }
1874 }
1875
Jamie Madill51f40ec2016-06-15 14:06:00 -04001876 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001877 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1878 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1879 {
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
1886 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1887 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1888 for (size_t i = 0; i < 2; i++)
1889 {
1890 if (mask & masks[i])
1891 {
1892 const FramebufferAttachment *readBuffer =
1893 readFramebuffer->getAttachment(attachments[i]);
1894 const FramebufferAttachment *drawBuffer =
1895 drawFramebuffer->getAttachment(attachments[i]);
1896
1897 if (readBuffer && drawBuffer)
1898 {
1899 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1900 dstX0, dstY0, dstX1, dstY1))
1901 {
1902 // only whole-buffer copies are permitted
He Yunchaoced53ae2016-11-29 15:00:51 +08001903 ERR("Only whole-buffer depth and stencil blits are supported by this "
Jamie Madillc29968b2016-01-20 11:17:23 -05001904 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001906 return false;
1907 }
1908
1909 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1910 {
Jamie Madill437fa652016-05-03 15:13:24 -04001911 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001912 return false;
1913 }
1914 }
1915 }
1916 }
1917
1918 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1919 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001920}
Jamie Madillc29968b2016-01-20 11:17:23 -05001921
1922bool ValidateClear(ValidationContext *context, GLbitfield mask)
1923{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001924 auto fbo = context->getGLState().getDrawFramebuffer();
1925 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001928 return false;
1929 }
1930
1931 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1932 {
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001934 return false;
1935 }
1936
1937 return true;
1938}
1939
1940bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1941{
1942 if (!context->getExtensions().drawBuffers)
1943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001945 return false;
1946 }
1947
1948 return ValidateDrawBuffersBase(context, n, bufs);
1949}
1950
Jamie Madill73a84962016-02-12 09:27:23 -05001951bool ValidateTexImage2D(Context *context,
1952 GLenum target,
1953 GLint level,
1954 GLint internalformat,
1955 GLsizei width,
1956 GLsizei height,
1957 GLint border,
1958 GLenum format,
1959 GLenum type,
1960 const GLvoid *pixels)
1961{
Martin Radev1be913c2016-07-11 17:59:16 +03001962 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001963 {
1964 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001965 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001966 }
1967
Martin Radev1be913c2016-07-11 17:59:16 +03001968 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001969 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001970 0, 0, width, height, 1, border, format, type, -1,
1971 pixels);
1972}
1973
1974bool ValidateTexImage2DRobust(Context *context,
1975 GLenum target,
1976 GLint level,
1977 GLint internalformat,
1978 GLsizei width,
1979 GLsizei height,
1980 GLint border,
1981 GLenum format,
1982 GLenum type,
1983 GLsizei bufSize,
1984 const GLvoid *pixels)
1985{
1986 if (!ValidateRobustEntryPoint(context, bufSize))
1987 {
1988 return false;
1989 }
1990
1991 if (context->getClientMajorVersion() < 3)
1992 {
1993 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1994 0, 0, width, height, border, format, type, bufSize,
1995 pixels);
1996 }
1997
1998 ASSERT(context->getClientMajorVersion() >= 3);
1999 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2000 0, 0, width, height, 1, border, format, type, bufSize,
2001 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002002}
2003
2004bool ValidateTexSubImage2D(Context *context,
2005 GLenum target,
2006 GLint level,
2007 GLint xoffset,
2008 GLint yoffset,
2009 GLsizei width,
2010 GLsizei height,
2011 GLenum format,
2012 GLenum type,
2013 const GLvoid *pixels)
2014{
2015
Martin Radev1be913c2016-07-11 17:59:16 +03002016 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002017 {
2018 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002019 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002020 }
2021
Martin Radev1be913c2016-07-11 17:59:16 +03002022 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002023 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002024 yoffset, 0, width, height, 1, 0, format, type, -1,
2025 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002026}
2027
Geoff Langc52f6f12016-10-14 10:18:00 -04002028bool ValidateTexSubImage2DRobustANGLE(Context *context,
2029 GLenum target,
2030 GLint level,
2031 GLint xoffset,
2032 GLint yoffset,
2033 GLsizei width,
2034 GLsizei height,
2035 GLenum format,
2036 GLenum type,
2037 GLsizei bufSize,
2038 const GLvoid *pixels)
2039{
2040 if (!ValidateRobustEntryPoint(context, bufSize))
2041 {
2042 return false;
2043 }
2044
2045 if (context->getClientMajorVersion() < 3)
2046 {
2047 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2048 yoffset, width, height, 0, format, type, bufSize,
2049 pixels);
2050 }
2051
2052 ASSERT(context->getClientMajorVersion() >= 3);
2053 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2054 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2055 pixels);
2056}
2057
Jamie Madill73a84962016-02-12 09:27:23 -05002058bool ValidateCompressedTexImage2D(Context *context,
2059 GLenum target,
2060 GLint level,
2061 GLenum internalformat,
2062 GLsizei width,
2063 GLsizei height,
2064 GLint border,
2065 GLsizei imageSize,
2066 const GLvoid *data)
2067{
Martin Radev1be913c2016-07-11 17:59:16 +03002068 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002069 {
2070 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002071 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002072 {
2073 return false;
2074 }
2075 }
2076 else
2077 {
Martin Radev1be913c2016-07-11 17:59:16 +03002078 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002079 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002080 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002081 data))
2082 {
2083 return false;
2084 }
2085 }
2086
2087 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002088 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002089 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002090 if (blockSizeOrErr.isError())
2091 {
2092 context->handleError(blockSizeOrErr.getError());
2093 return false;
2094 }
2095
2096 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002097 {
Jamie Madill437fa652016-05-03 15:13:24 -04002098 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002099 return false;
2100 }
2101
2102 return true;
2103}
2104
2105bool ValidateCompressedTexSubImage2D(Context *context,
2106 GLenum target,
2107 GLint level,
2108 GLint xoffset,
2109 GLint yoffset,
2110 GLsizei width,
2111 GLsizei height,
2112 GLenum format,
2113 GLsizei imageSize,
2114 const GLvoid *data)
2115{
Martin Radev1be913c2016-07-11 17:59:16 +03002116 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002117 {
2118 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002119 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002120 {
2121 return false;
2122 }
2123 }
2124 else
2125 {
Martin Radev1be913c2016-07-11 17:59:16 +03002126 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002127 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002128 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002129 data))
2130 {
2131 return false;
2132 }
2133 }
2134
2135 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002136 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002137 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002138 if (blockSizeOrErr.isError())
2139 {
2140 context->handleError(blockSizeOrErr.getError());
2141 return false;
2142 }
2143
2144 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002145 {
Jamie Madill437fa652016-05-03 15:13:24 -04002146 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002147 return false;
2148 }
2149
2150 return true;
2151}
2152
Olli Etuaho4f667482016-03-30 15:56:35 +03002153bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2154{
Geoff Lang496c02d2016-10-20 11:38:11 -07002155 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002156}
2157
2158bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2159{
2160 if (!context->getExtensions().mapBuffer)
2161 {
Jamie Madill437fa652016-05-03 15:13:24 -04002162 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002163 return false;
2164 }
2165
2166 if (!ValidBufferTarget(context, target))
2167 {
Jamie Madill437fa652016-05-03 15:13:24 -04002168 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002169 return false;
2170 }
2171
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002172 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002173
2174 if (buffer == nullptr)
2175 {
Jamie Madill437fa652016-05-03 15:13:24 -04002176 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002177 return false;
2178 }
2179
2180 if (access != GL_WRITE_ONLY_OES)
2181 {
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002183 return false;
2184 }
2185
2186 if (buffer->isMapped())
2187 {
Jamie Madill437fa652016-05-03 15:13:24 -04002188 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002189 return false;
2190 }
2191
2192 return true;
2193}
2194
2195bool ValidateUnmapBufferOES(Context *context, GLenum target)
2196{
2197 if (!context->getExtensions().mapBuffer)
2198 {
Jamie Madill437fa652016-05-03 15:13:24 -04002199 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002200 return false;
2201 }
2202
2203 return ValidateUnmapBufferBase(context, target);
2204}
2205
2206bool ValidateMapBufferRangeEXT(Context *context,
2207 GLenum target,
2208 GLintptr offset,
2209 GLsizeiptr length,
2210 GLbitfield access)
2211{
2212 if (!context->getExtensions().mapBufferRange)
2213 {
Jamie Madill437fa652016-05-03 15:13:24 -04002214 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002215 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2216 return false;
2217 }
2218
2219 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2220}
2221
2222bool ValidateFlushMappedBufferRangeEXT(Context *context,
2223 GLenum target,
2224 GLintptr offset,
2225 GLsizeiptr length)
2226{
2227 if (!context->getExtensions().mapBufferRange)
2228 {
Jamie Madill437fa652016-05-03 15:13:24 -04002229 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002230 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2231 return false;
2232 }
2233
2234 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2235}
2236
Ian Ewell54f87462016-03-10 13:47:21 -05002237bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2238{
2239 Texture *textureObject = context->getTexture(texture);
2240 if (textureObject && textureObject->getTarget() != target && texture != 0)
2241 {
Jamie Madill437fa652016-05-03 15:13:24 -04002242 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002243 return false;
2244 }
2245
Geoff Langf41a7152016-09-19 15:11:17 -04002246 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2247 !context->isTextureGenerated(texture))
2248 {
2249 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2250 return false;
2251 }
2252
Ian Ewell54f87462016-03-10 13:47:21 -05002253 switch (target)
2254 {
2255 case GL_TEXTURE_2D:
2256 case GL_TEXTURE_CUBE_MAP:
2257 break;
2258
2259 case GL_TEXTURE_3D:
2260 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002261 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002262 {
Jamie Madill437fa652016-05-03 15:13:24 -04002263 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002264 return false;
2265 }
2266 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002267
2268 case GL_TEXTURE_2D_MULTISAMPLE:
2269 if (context->getClientVersion() < Version(3, 1))
2270 {
2271 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2272 return false;
2273 }
Geoff Lang3b573612016-10-31 14:08:10 -04002274 break;
2275
Ian Ewell54f87462016-03-10 13:47:21 -05002276 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002277 if (!context->getExtensions().eglImageExternal &&
2278 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002281 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2282 return false;
2283 }
2284 break;
2285 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002286 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002287 return false;
2288 }
2289
2290 return true;
2291}
2292
Geoff Langd8605522016-04-13 10:19:12 -04002293bool ValidateBindUniformLocationCHROMIUM(Context *context,
2294 GLuint program,
2295 GLint location,
2296 const GLchar *name)
2297{
2298 if (!context->getExtensions().bindUniformLocation)
2299 {
Jamie Madill437fa652016-05-03 15:13:24 -04002300 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002301 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2302 return false;
2303 }
2304
2305 Program *programObject = GetValidProgram(context, program);
2306 if (!programObject)
2307 {
2308 return false;
2309 }
2310
2311 if (location < 0)
2312 {
Jamie Madill437fa652016-05-03 15:13:24 -04002313 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002314 return false;
2315 }
2316
2317 const Caps &caps = context->getCaps();
2318 if (static_cast<size_t>(location) >=
2319 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2320 {
Jamie Madill437fa652016-05-03 15:13:24 -04002321 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002322 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2323 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2324 return false;
2325 }
2326
2327 if (strncmp(name, "gl_", 3) == 0)
2328 {
Jamie Madill437fa652016-05-03 15:13:24 -04002329 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002330 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2331 return false;
2332 }
2333
2334 return true;
2335}
2336
Jamie Madille2e406c2016-06-02 13:04:10 -04002337bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002338{
2339 if (!context->getExtensions().framebufferMixedSamples)
2340 {
2341 context->handleError(
2342 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2343 return false;
2344 }
2345 switch (components)
2346 {
2347 case GL_RGB:
2348 case GL_RGBA:
2349 case GL_ALPHA:
2350 case GL_NONE:
2351 break;
2352 default:
2353 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002354 Error(GL_INVALID_ENUM,
2355 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002356 return false;
2357 }
2358
2359 return true;
2360}
2361
Sami Väisänene45e53b2016-05-25 10:36:04 +03002362// CHROMIUM_path_rendering
2363
2364bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2365{
2366 if (!context->getExtensions().pathRendering)
2367 {
2368 context->handleError(
2369 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2370 return false;
2371 }
2372 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2373 {
2374 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2375 return false;
2376 }
2377 if (matrix == nullptr)
2378 {
2379 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2380 return false;
2381 }
2382 return true;
2383}
2384
2385bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2386{
2387 if (!context->getExtensions().pathRendering)
2388 {
2389 context->handleError(
2390 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2391 return false;
2392 }
2393 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2394 {
2395 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2396 return false;
2397 }
2398 return true;
2399}
2400
2401bool ValidateGenPaths(Context *context, GLsizei range)
2402{
2403 if (!context->getExtensions().pathRendering)
2404 {
2405 context->handleError(
2406 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2407 return false;
2408 }
2409
2410 // range = 0 is undefined in NV_path_rendering.
2411 // we add stricter semantic check here and require a non zero positive range.
2412 if (range <= 0)
2413 {
2414 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2415 return false;
2416 }
2417
2418 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2419 {
2420 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2421 return false;
2422 }
2423
2424 return true;
2425}
2426
2427bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2428{
2429 if (!context->getExtensions().pathRendering)
2430 {
2431 context->handleError(
2432 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2433 return false;
2434 }
2435
2436 // range = 0 is undefined in NV_path_rendering.
2437 // we add stricter semantic check here and require a non zero positive range.
2438 if (range <= 0)
2439 {
2440 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2441 return false;
2442 }
2443
2444 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2445 checkedRange += range;
2446
2447 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2448 {
2449 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2450 return false;
2451 }
2452 return true;
2453}
2454
2455bool ValidatePathCommands(Context *context,
2456 GLuint path,
2457 GLsizei numCommands,
2458 const GLubyte *commands,
2459 GLsizei numCoords,
2460 GLenum coordType,
2461 const void *coords)
2462{
2463 if (!context->getExtensions().pathRendering)
2464 {
2465 context->handleError(
2466 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2467 return false;
2468 }
2469 if (!context->hasPath(path))
2470 {
2471 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2472 return false;
2473 }
2474
2475 if (numCommands < 0)
2476 {
2477 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2478 return false;
2479 }
2480 else if (numCommands > 0)
2481 {
2482 if (!commands)
2483 {
2484 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2485 return false;
2486 }
2487 }
2488
2489 if (numCoords < 0)
2490 {
2491 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2492 return false;
2493 }
2494 else if (numCoords > 0)
2495 {
2496 if (!coords)
2497 {
2498 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2499 return false;
2500 }
2501 }
2502
2503 std::uint32_t coordTypeSize = 0;
2504 switch (coordType)
2505 {
2506 case GL_BYTE:
2507 coordTypeSize = sizeof(GLbyte);
2508 break;
2509
2510 case GL_UNSIGNED_BYTE:
2511 coordTypeSize = sizeof(GLubyte);
2512 break;
2513
2514 case GL_SHORT:
2515 coordTypeSize = sizeof(GLshort);
2516 break;
2517
2518 case GL_UNSIGNED_SHORT:
2519 coordTypeSize = sizeof(GLushort);
2520 break;
2521
2522 case GL_FLOAT:
2523 coordTypeSize = sizeof(GLfloat);
2524 break;
2525
2526 default:
2527 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2528 return false;
2529 }
2530
2531 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2532 checkedSize += (coordTypeSize * numCoords);
2533 if (!checkedSize.IsValid())
2534 {
2535 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2536 return false;
2537 }
2538
2539 // early return skips command data validation when it doesn't exist.
2540 if (!commands)
2541 return true;
2542
2543 GLsizei expectedNumCoords = 0;
2544 for (GLsizei i = 0; i < numCommands; ++i)
2545 {
2546 switch (commands[i])
2547 {
2548 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2549 break;
2550 case GL_MOVE_TO_CHROMIUM:
2551 case GL_LINE_TO_CHROMIUM:
2552 expectedNumCoords += 2;
2553 break;
2554 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2555 expectedNumCoords += 4;
2556 break;
2557 case GL_CUBIC_CURVE_TO_CHROMIUM:
2558 expectedNumCoords += 6;
2559 break;
2560 case GL_CONIC_CURVE_TO_CHROMIUM:
2561 expectedNumCoords += 5;
2562 break;
2563 default:
2564 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2565 return false;
2566 }
2567 }
2568 if (expectedNumCoords != numCoords)
2569 {
2570 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2571 return false;
2572 }
2573
2574 return true;
2575}
2576
2577bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2578{
2579 if (!context->getExtensions().pathRendering)
2580 {
2581 context->handleError(
2582 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2583 return false;
2584 }
2585 if (!context->hasPath(path))
2586 {
2587 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2588 return false;
2589 }
2590
2591 switch (pname)
2592 {
2593 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2594 if (value < 0.0f)
2595 {
2596 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2597 return false;
2598 }
2599 break;
2600 case GL_PATH_END_CAPS_CHROMIUM:
2601 switch (static_cast<GLenum>(value))
2602 {
2603 case GL_FLAT_CHROMIUM:
2604 case GL_SQUARE_CHROMIUM:
2605 case GL_ROUND_CHROMIUM:
2606 break;
2607 default:
2608 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2609 return false;
2610 }
2611 break;
2612 case GL_PATH_JOIN_STYLE_CHROMIUM:
2613 switch (static_cast<GLenum>(value))
2614 {
2615 case GL_MITER_REVERT_CHROMIUM:
2616 case GL_BEVEL_CHROMIUM:
2617 case GL_ROUND_CHROMIUM:
2618 break;
2619 default:
2620 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2621 return false;
2622 }
2623 case GL_PATH_MITER_LIMIT_CHROMIUM:
2624 if (value < 0.0f)
2625 {
2626 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2627 return false;
2628 }
2629 break;
2630
2631 case GL_PATH_STROKE_BOUND_CHROMIUM:
2632 // no errors, only clamping.
2633 break;
2634
2635 default:
2636 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2637 return false;
2638 }
2639 return true;
2640}
2641
2642bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2643{
2644 if (!context->getExtensions().pathRendering)
2645 {
2646 context->handleError(
2647 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2648 return false;
2649 }
2650
2651 if (!context->hasPath(path))
2652 {
2653 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2654 return false;
2655 }
2656 if (!value)
2657 {
2658 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2659 return false;
2660 }
2661
2662 switch (pname)
2663 {
2664 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2665 case GL_PATH_END_CAPS_CHROMIUM:
2666 case GL_PATH_JOIN_STYLE_CHROMIUM:
2667 case GL_PATH_MITER_LIMIT_CHROMIUM:
2668 case GL_PATH_STROKE_BOUND_CHROMIUM:
2669 break;
2670
2671 default:
2672 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2673 return false;
2674 }
2675
2676 return true;
2677}
2678
2679bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2680{
2681 if (!context->getExtensions().pathRendering)
2682 {
2683 context->handleError(
2684 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2685 return false;
2686 }
2687
2688 switch (func)
2689 {
2690 case GL_NEVER:
2691 case GL_ALWAYS:
2692 case GL_LESS:
2693 case GL_LEQUAL:
2694 case GL_EQUAL:
2695 case GL_GEQUAL:
2696 case GL_GREATER:
2697 case GL_NOTEQUAL:
2698 break;
2699 default:
2700 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2701 return false;
2702 }
2703
2704 return true;
2705}
2706
2707// Note that the spec specifies that for the path drawing commands
2708// if the path object is not an existing path object the command
2709// does nothing and no error is generated.
2710// However if the path object exists but has not been specified any
2711// commands then an error is generated.
2712
2713bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2714{
2715 if (!context->getExtensions().pathRendering)
2716 {
2717 context->handleError(
2718 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2719 return false;
2720 }
2721 if (context->hasPath(path) && !context->hasPathData(path))
2722 {
2723 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2724 return false;
2725 }
2726
2727 switch (fillMode)
2728 {
2729 case GL_COUNT_UP_CHROMIUM:
2730 case GL_COUNT_DOWN_CHROMIUM:
2731 break;
2732 default:
2733 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2734 return false;
2735 }
2736
2737 if (!isPow2(mask + 1))
2738 {
2739 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2740 return false;
2741 }
2742
2743 return true;
2744}
2745
2746bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2747{
2748 if (!context->getExtensions().pathRendering)
2749 {
2750 context->handleError(
2751 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2752 return false;
2753 }
2754 if (context->hasPath(path) && !context->hasPathData(path))
2755 {
2756 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2757 return false;
2758 }
2759
2760 return true;
2761}
2762
2763bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2764{
2765 if (!context->getExtensions().pathRendering)
2766 {
2767 context->handleError(
2768 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2769 return false;
2770 }
2771 if (context->hasPath(path) && !context->hasPathData(path))
2772 {
2773 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2774 return false;
2775 }
2776
2777 switch (coverMode)
2778 {
2779 case GL_CONVEX_HULL_CHROMIUM:
2780 case GL_BOUNDING_BOX_CHROMIUM:
2781 break;
2782 default:
2783 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2784 return false;
2785 }
2786 return true;
2787}
2788
2789bool ValidateStencilThenCoverFillPath(Context *context,
2790 GLuint path,
2791 GLenum fillMode,
2792 GLuint mask,
2793 GLenum coverMode)
2794{
2795 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2796 ValidateCoverPath(context, path, coverMode);
2797}
2798
2799bool ValidateStencilThenCoverStrokePath(Context *context,
2800 GLuint path,
2801 GLint reference,
2802 GLuint mask,
2803 GLenum coverMode)
2804{
2805 return ValidateStencilStrokePath(context, path, reference, mask) &&
2806 ValidateCoverPath(context, path, coverMode);
2807}
2808
2809bool ValidateIsPath(Context *context)
2810{
2811 if (!context->getExtensions().pathRendering)
2812 {
2813 context->handleError(
2814 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2815 return false;
2816 }
2817 return true;
2818}
2819
Sami Väisänend59ca052016-06-21 16:10:00 +03002820bool ValidateCoverFillPathInstanced(Context *context,
2821 GLsizei numPaths,
2822 GLenum pathNameType,
2823 const void *paths,
2824 GLuint pathBase,
2825 GLenum coverMode,
2826 GLenum transformType,
2827 const GLfloat *transformValues)
2828{
2829 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2830 transformType, transformValues))
2831 return false;
2832
2833 switch (coverMode)
2834 {
2835 case GL_CONVEX_HULL_CHROMIUM:
2836 case GL_BOUNDING_BOX_CHROMIUM:
2837 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2838 break;
2839 default:
2840 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2841 return false;
2842 }
2843
2844 return true;
2845}
2846
2847bool ValidateCoverStrokePathInstanced(Context *context,
2848 GLsizei numPaths,
2849 GLenum pathNameType,
2850 const void *paths,
2851 GLuint pathBase,
2852 GLenum coverMode,
2853 GLenum transformType,
2854 const GLfloat *transformValues)
2855{
2856 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2857 transformType, transformValues))
2858 return false;
2859
2860 switch (coverMode)
2861 {
2862 case GL_CONVEX_HULL_CHROMIUM:
2863 case GL_BOUNDING_BOX_CHROMIUM:
2864 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2865 break;
2866 default:
2867 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2868 return false;
2869 }
2870
2871 return true;
2872}
2873
2874bool ValidateStencilFillPathInstanced(Context *context,
2875 GLsizei numPaths,
2876 GLenum pathNameType,
2877 const void *paths,
2878 GLuint pathBase,
2879 GLenum fillMode,
2880 GLuint mask,
2881 GLenum transformType,
2882 const GLfloat *transformValues)
2883{
2884
2885 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2886 transformType, transformValues))
2887 return false;
2888
2889 switch (fillMode)
2890 {
2891 case GL_COUNT_UP_CHROMIUM:
2892 case GL_COUNT_DOWN_CHROMIUM:
2893 break;
2894 default:
2895 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2896 return false;
2897 }
2898 if (!isPow2(mask + 1))
2899 {
2900 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2901 return false;
2902 }
2903 return true;
2904}
2905
2906bool ValidateStencilStrokePathInstanced(Context *context,
2907 GLsizei numPaths,
2908 GLenum pathNameType,
2909 const void *paths,
2910 GLuint pathBase,
2911 GLint reference,
2912 GLuint mask,
2913 GLenum transformType,
2914 const GLfloat *transformValues)
2915{
2916 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2917 transformType, transformValues))
2918 return false;
2919
2920 // no more validation here.
2921
2922 return true;
2923}
2924
2925bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2926 GLsizei numPaths,
2927 GLenum pathNameType,
2928 const void *paths,
2929 GLuint pathBase,
2930 GLenum fillMode,
2931 GLuint mask,
2932 GLenum coverMode,
2933 GLenum transformType,
2934 const GLfloat *transformValues)
2935{
2936 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2937 transformType, transformValues))
2938 return false;
2939
2940 switch (coverMode)
2941 {
2942 case GL_CONVEX_HULL_CHROMIUM:
2943 case GL_BOUNDING_BOX_CHROMIUM:
2944 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2945 break;
2946 default:
2947 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2948 return false;
2949 }
2950
2951 switch (fillMode)
2952 {
2953 case GL_COUNT_UP_CHROMIUM:
2954 case GL_COUNT_DOWN_CHROMIUM:
2955 break;
2956 default:
2957 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2958 return false;
2959 }
2960 if (!isPow2(mask + 1))
2961 {
2962 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2963 return false;
2964 }
2965
2966 return true;
2967}
2968
2969bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2970 GLsizei numPaths,
2971 GLenum pathNameType,
2972 const void *paths,
2973 GLuint pathBase,
2974 GLint reference,
2975 GLuint mask,
2976 GLenum coverMode,
2977 GLenum transformType,
2978 const GLfloat *transformValues)
2979{
2980 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2981 transformType, transformValues))
2982 return false;
2983
2984 switch (coverMode)
2985 {
2986 case GL_CONVEX_HULL_CHROMIUM:
2987 case GL_BOUNDING_BOX_CHROMIUM:
2988 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2989 break;
2990 default:
2991 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2992 return false;
2993 }
2994
2995 return true;
2996}
2997
Sami Väisänen46eaa942016-06-29 10:26:37 +03002998bool ValidateBindFragmentInputLocation(Context *context,
2999 GLuint program,
3000 GLint location,
3001 const GLchar *name)
3002{
3003 if (!context->getExtensions().pathRendering)
3004 {
3005 context->handleError(
3006 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3007 return false;
3008 }
3009
3010 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3011 if (location >= MaxLocation)
3012 {
3013 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3014 return false;
3015 }
3016
3017 const auto *programObject = context->getProgram(program);
3018 if (!programObject)
3019 {
3020 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3021 return false;
3022 }
3023
3024 if (!name)
3025 {
3026 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3027 return false;
3028 }
3029
3030 if (angle::BeginsWith(name, "gl_"))
3031 {
3032 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3033 return false;
3034 }
3035
3036 return true;
3037}
3038
3039bool ValidateProgramPathFragmentInputGen(Context *context,
3040 GLuint program,
3041 GLint location,
3042 GLenum genMode,
3043 GLint components,
3044 const GLfloat *coeffs)
3045{
3046 if (!context->getExtensions().pathRendering)
3047 {
3048 context->handleError(
3049 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3050 return false;
3051 }
3052
3053 const auto *programObject = context->getProgram(program);
3054 if (!programObject || programObject->isFlaggedForDeletion())
3055 {
3056 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3057 return false;
3058 }
3059
3060 if (!programObject->isLinked())
3061 {
3062 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3063 return false;
3064 }
3065
3066 switch (genMode)
3067 {
3068 case GL_NONE:
3069 if (components != 0)
3070 {
3071 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3072 return false;
3073 }
3074 break;
3075
3076 case GL_OBJECT_LINEAR_CHROMIUM:
3077 case GL_EYE_LINEAR_CHROMIUM:
3078 case GL_CONSTANT_CHROMIUM:
3079 if (components < 1 || components > 4)
3080 {
3081 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3082 return false;
3083 }
3084 if (!coeffs)
3085 {
3086 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3087 return false;
3088 }
3089 break;
3090
3091 default:
3092 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3093 return false;
3094 }
3095
3096 // If the location is -1 then the command is silently ignored
3097 // and no further validation is needed.
3098 if (location == -1)
3099 return true;
3100
3101 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3102
3103 if (!binding.valid)
3104 {
3105 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3106 return false;
3107 }
3108
3109 if (binding.type != GL_NONE)
3110 {
3111 GLint expectedComponents = 0;
3112 switch (binding.type)
3113 {
3114 case GL_FLOAT:
3115 expectedComponents = 1;
3116 break;
3117 case GL_FLOAT_VEC2:
3118 expectedComponents = 2;
3119 break;
3120 case GL_FLOAT_VEC3:
3121 expectedComponents = 3;
3122 break;
3123 case GL_FLOAT_VEC4:
3124 expectedComponents = 4;
3125 break;
3126 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003127 context->handleError(
3128 Error(GL_INVALID_OPERATION,
3129 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003130 return false;
3131 }
3132 if (expectedComponents != components && genMode != GL_NONE)
3133 {
3134 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3135 return false;
3136 }
3137 }
3138 return true;
3139}
3140
Geoff Lang97073d12016-04-20 10:42:34 -07003141bool ValidateCopyTextureCHROMIUM(Context *context,
3142 GLuint sourceId,
3143 GLuint destId,
3144 GLint internalFormat,
3145 GLenum destType,
3146 GLboolean unpackFlipY,
3147 GLboolean unpackPremultiplyAlpha,
3148 GLboolean unpackUnmultiplyAlpha)
3149{
3150 if (!context->getExtensions().copyTexture)
3151 {
3152 context->handleError(
3153 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3154 return false;
3155 }
3156
3157 const gl::Texture *source = context->getTexture(sourceId);
3158 if (source == nullptr)
3159 {
3160 context->handleError(
3161 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3162 return false;
3163 }
3164
3165 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3166 {
3167 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3168 return false;
3169 }
3170
3171 GLenum sourceTarget = source->getTarget();
3172 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3173 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3174 {
3175 context->handleError(
3176 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3177 return false;
3178 }
3179
3180 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3181 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3182 {
3183 context->handleError(
3184 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3185 return false;
3186 }
3187
3188 const gl::Texture *dest = context->getTexture(destId);
3189 if (dest == nullptr)
3190 {
3191 context->handleError(
3192 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3193 return false;
3194 }
3195
3196 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3197 {
3198 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3199 return false;
3200 }
3201
3202 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3203 {
3204 context->handleError(
3205 Error(GL_INVALID_OPERATION,
3206 "Destination internal format and type combination is not valid."));
3207 return false;
3208 }
3209
3210 if (dest->getImmutableFormat())
3211 {
3212 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3213 return false;
3214 }
3215
3216 return true;
3217}
3218
3219bool ValidateCopySubTextureCHROMIUM(Context *context,
3220 GLuint sourceId,
3221 GLuint destId,
3222 GLint xoffset,
3223 GLint yoffset,
3224 GLint x,
3225 GLint y,
3226 GLsizei width,
3227 GLsizei height,
3228 GLboolean unpackFlipY,
3229 GLboolean unpackPremultiplyAlpha,
3230 GLboolean unpackUnmultiplyAlpha)
3231{
3232 if (!context->getExtensions().copyTexture)
3233 {
3234 context->handleError(
3235 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3236 return false;
3237 }
3238
3239 const gl::Texture *source = context->getTexture(sourceId);
3240 if (source == nullptr)
3241 {
3242 context->handleError(
3243 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3244 return false;
3245 }
3246
3247 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3248 {
3249 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3250 return false;
3251 }
3252
3253 GLenum sourceTarget = source->getTarget();
3254 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3255 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3256 {
3257 context->handleError(
3258 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3259 return false;
3260 }
3261
3262 if (x < 0 || y < 0)
3263 {
3264 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3265 return false;
3266 }
3267
3268 if (width < 0 || height < 0)
3269 {
3270 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3271 return false;
3272 }
3273
3274 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3275 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3276 {
3277 context->handleError(
3278 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3279 return false;
3280 }
3281
3282 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3283 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3284 {
3285 context->handleError(
3286 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3287 return false;
3288 }
3289
3290 const gl::Texture *dest = context->getTexture(destId);
3291 if (dest == nullptr)
3292 {
3293 context->handleError(
3294 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3295 return false;
3296 }
3297
3298 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3299 {
3300 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3301 return false;
3302 }
3303
3304 GLenum destTarget = dest->getTarget();
3305 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3306 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3307 {
3308 context->handleError(
3309 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3310 return false;
3311 }
3312
3313 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3314 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3315 {
3316 context->handleError(
3317 Error(GL_INVALID_OPERATION,
3318 "Destination internal format and type combination is not valid."));
3319 return false;
3320 }
3321
3322 if (xoffset < 0 || yoffset < 0)
3323 {
3324 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3325 return false;
3326 }
3327
3328 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3329 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3330 {
3331 context->handleError(
3332 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3333 return false;
3334 }
3335
3336 return true;
3337}
3338
Geoff Lang47110bf2016-04-20 11:13:22 -07003339bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3340{
3341 if (!context->getExtensions().copyCompressedTexture)
3342 {
3343 context->handleError(Error(GL_INVALID_OPERATION,
3344 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3345 return false;
3346 }
3347
3348 const gl::Texture *source = context->getTexture(sourceId);
3349 if (source == nullptr)
3350 {
3351 context->handleError(
3352 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3353 return false;
3354 }
3355
3356 if (source->getTarget() != GL_TEXTURE_2D)
3357 {
3358 context->handleError(
3359 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3360 return false;
3361 }
3362
3363 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3364 {
3365 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3366 return false;
3367 }
3368
3369 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3370 if (!sourceFormat.info->compressed)
3371 {
3372 context->handleError(
3373 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3374 return false;
3375 }
3376
3377 const gl::Texture *dest = context->getTexture(destId);
3378 if (dest == nullptr)
3379 {
3380 context->handleError(
3381 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3382 return false;
3383 }
3384
3385 if (dest->getTarget() != GL_TEXTURE_2D)
3386 {
3387 context->handleError(
3388 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3389 return false;
3390 }
3391
3392 if (dest->getImmutableFormat())
3393 {
3394 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3395 return false;
3396 }
3397
3398 return true;
3399}
3400
Martin Radev4c4c8e72016-08-04 12:25:34 +03003401bool ValidateCreateShader(Context *context, GLenum type)
3402{
3403 switch (type)
3404 {
3405 case GL_VERTEX_SHADER:
3406 case GL_FRAGMENT_SHADER:
3407 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003408
Martin Radev4c4c8e72016-08-04 12:25:34 +03003409 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003410 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003411 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003412 context->handleError(
3413 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3414 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003415 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003416 break;
3417
Martin Radev4c4c8e72016-08-04 12:25:34 +03003418 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003419 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003420 return false;
3421 }
Jamie Madill29639852016-09-02 15:00:09 -04003422
3423 return true;
3424}
3425
3426bool ValidateBufferData(ValidationContext *context,
3427 GLenum target,
3428 GLsizeiptr size,
3429 const GLvoid *data,
3430 GLenum usage)
3431{
3432 if (size < 0)
3433 {
3434 context->handleError(Error(GL_INVALID_VALUE));
3435 return false;
3436 }
3437
3438 switch (usage)
3439 {
3440 case GL_STREAM_DRAW:
3441 case GL_STATIC_DRAW:
3442 case GL_DYNAMIC_DRAW:
3443 break;
3444
3445 case GL_STREAM_READ:
3446 case GL_STREAM_COPY:
3447 case GL_STATIC_READ:
3448 case GL_STATIC_COPY:
3449 case GL_DYNAMIC_READ:
3450 case GL_DYNAMIC_COPY:
3451 if (context->getClientMajorVersion() < 3)
3452 {
3453 context->handleError(Error(GL_INVALID_ENUM));
3454 return false;
3455 }
3456 break;
3457
3458 default:
3459 context->handleError(Error(GL_INVALID_ENUM));
3460 return false;
3461 }
3462
3463 if (!ValidBufferTarget(context, target))
3464 {
3465 context->handleError(Error(GL_INVALID_ENUM));
3466 return false;
3467 }
3468
3469 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3470
3471 if (!buffer)
3472 {
3473 context->handleError(Error(GL_INVALID_OPERATION));
3474 return false;
3475 }
3476
3477 return true;
3478}
3479
3480bool ValidateBufferSubData(ValidationContext *context,
3481 GLenum target,
3482 GLintptr offset,
3483 GLsizeiptr size,
3484 const GLvoid *data)
3485{
3486 if (size < 0 || offset < 0)
3487 {
3488 context->handleError(Error(GL_INVALID_VALUE));
3489 return false;
3490 }
3491
3492 if (!ValidBufferTarget(context, target))
3493 {
3494 context->handleError(Error(GL_INVALID_ENUM));
3495 return false;
3496 }
3497
3498 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3499
3500 if (!buffer)
3501 {
3502 context->handleError(Error(GL_INVALID_OPERATION));
3503 return false;
3504 }
3505
3506 if (buffer->isMapped())
3507 {
3508 context->handleError(Error(GL_INVALID_OPERATION));
3509 return false;
3510 }
3511
3512 // Check for possible overflow of size + offset
3513 angle::CheckedNumeric<size_t> checkedSize(size);
3514 checkedSize += offset;
3515 if (!checkedSize.IsValid())
3516 {
3517 context->handleError(Error(GL_OUT_OF_MEMORY));
3518 return false;
3519 }
3520
3521 if (size + offset > buffer->getSize())
3522 {
3523 context->handleError(Error(GL_INVALID_VALUE));
3524 return false;
3525 }
3526
Martin Radev4c4c8e72016-08-04 12:25:34 +03003527 return true;
3528}
3529
Geoff Langc339c4e2016-11-29 10:37:36 -05003530bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003531{
Geoff Langc339c4e2016-11-29 10:37:36 -05003532 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003533 {
3534 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003535 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003536 return false;
3537 }
3538
3539 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3540 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003541 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003542 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003543 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003544 return false;
3545 }
3546
3547 return true;
3548}
3549
Jamie Madillef300b12016-10-07 15:12:09 -04003550bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3551{
3552 if (texture < GL_TEXTURE0 ||
3553 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3554 {
3555 context->handleError(Error(GL_INVALID_ENUM));
3556 return false;
3557 }
3558
3559 return true;
3560}
3561
3562bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3563{
3564 Program *programObject = GetValidProgram(context, program);
3565 if (!programObject)
3566 {
3567 return false;
3568 }
3569
3570 Shader *shaderObject = GetValidShader(context, shader);
3571 if (!shaderObject)
3572 {
3573 return false;
3574 }
3575
3576 switch (shaderObject->getType())
3577 {
3578 case GL_VERTEX_SHADER:
3579 {
3580 if (programObject->getAttachedVertexShader())
3581 {
3582 context->handleError(Error(GL_INVALID_OPERATION));
3583 return false;
3584 }
3585 break;
3586 }
3587 case GL_FRAGMENT_SHADER:
3588 {
3589 if (programObject->getAttachedFragmentShader())
3590 {
3591 context->handleError(Error(GL_INVALID_OPERATION));
3592 return false;
3593 }
3594 break;
3595 }
3596 case GL_COMPUTE_SHADER:
3597 {
3598 if (programObject->getAttachedComputeShader())
3599 {
3600 context->handleError(Error(GL_INVALID_OPERATION));
3601 return false;
3602 }
3603 break;
3604 }
3605 default:
3606 UNREACHABLE();
3607 break;
3608 }
3609
3610 return true;
3611}
3612
Jamie Madill01a80ee2016-11-07 12:06:18 -05003613bool ValidateBindAttribLocation(ValidationContext *context,
3614 GLuint program,
3615 GLuint index,
3616 const GLchar *name)
3617{
3618 if (index >= MAX_VERTEX_ATTRIBS)
3619 {
3620 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3621 return false;
3622 }
3623
3624 if (strncmp(name, "gl_", 3) == 0)
3625 {
3626 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3627 return false;
3628 }
3629
3630 return GetValidProgram(context, program) != nullptr;
3631}
3632
3633bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3634{
3635 if (!ValidBufferTarget(context, target))
3636 {
3637 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3638 return false;
3639 }
3640
3641 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3642 !context->isBufferGenerated(buffer))
3643 {
3644 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3645 return false;
3646 }
3647
3648 return true;
3649}
3650
3651bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3652{
3653 if (!ValidFramebufferTarget(target))
3654 {
3655 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3656 return false;
3657 }
3658
3659 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3660 !context->isFramebufferGenerated(framebuffer))
3661 {
3662 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3663 return false;
3664 }
3665
3666 return true;
3667}
3668
3669bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3670{
3671 if (target != GL_RENDERBUFFER)
3672 {
3673 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3674 return false;
3675 }
3676
3677 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3678 !context->isRenderbufferGenerated(renderbuffer))
3679 {
3680 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3681 return false;
3682 }
3683
3684 return true;
3685}
3686
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003687static bool ValidBlendEquationMode(GLenum mode)
3688{
3689 switch (mode)
3690 {
3691 case GL_FUNC_ADD:
3692 case GL_FUNC_SUBTRACT:
3693 case GL_FUNC_REVERSE_SUBTRACT:
3694 case GL_MIN:
3695 case GL_MAX:
3696 return true;
3697
3698 default:
3699 return false;
3700 }
3701}
3702
3703bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3704{
3705 if (!ValidBlendEquationMode(mode))
3706 {
3707 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3708 return false;
3709 }
3710
3711 return true;
3712}
3713
3714bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3715{
3716 if (!ValidBlendEquationMode(modeRGB))
3717 {
3718 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3719 return false;
3720 }
3721
3722 if (!ValidBlendEquationMode(modeAlpha))
3723 {
3724 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3725 return false;
3726 }
3727
3728 return true;
3729}
3730
3731bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3732{
3733 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3734}
3735
3736static bool ValidSrcBlendFunc(GLenum srcBlend)
3737{
3738 switch (srcBlend)
3739 {
3740 case GL_ZERO:
3741 case GL_ONE:
3742 case GL_SRC_COLOR:
3743 case GL_ONE_MINUS_SRC_COLOR:
3744 case GL_DST_COLOR:
3745 case GL_ONE_MINUS_DST_COLOR:
3746 case GL_SRC_ALPHA:
3747 case GL_ONE_MINUS_SRC_ALPHA:
3748 case GL_DST_ALPHA:
3749 case GL_ONE_MINUS_DST_ALPHA:
3750 case GL_CONSTANT_COLOR:
3751 case GL_ONE_MINUS_CONSTANT_COLOR:
3752 case GL_CONSTANT_ALPHA:
3753 case GL_ONE_MINUS_CONSTANT_ALPHA:
3754 case GL_SRC_ALPHA_SATURATE:
3755 return true;
3756
3757 default:
3758 return false;
3759 }
3760}
3761
3762static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3763{
3764 switch (dstBlend)
3765 {
3766 case GL_ZERO:
3767 case GL_ONE:
3768 case GL_SRC_COLOR:
3769 case GL_ONE_MINUS_SRC_COLOR:
3770 case GL_DST_COLOR:
3771 case GL_ONE_MINUS_DST_COLOR:
3772 case GL_SRC_ALPHA:
3773 case GL_ONE_MINUS_SRC_ALPHA:
3774 case GL_DST_ALPHA:
3775 case GL_ONE_MINUS_DST_ALPHA:
3776 case GL_CONSTANT_COLOR:
3777 case GL_ONE_MINUS_CONSTANT_COLOR:
3778 case GL_CONSTANT_ALPHA:
3779 case GL_ONE_MINUS_CONSTANT_ALPHA:
3780 return true;
3781
3782 case GL_SRC_ALPHA_SATURATE:
3783 return (contextMajorVersion >= 3);
3784
3785 default:
3786 return false;
3787 }
3788}
3789
3790bool ValidateBlendFuncSeparate(ValidationContext *context,
3791 GLenum srcRGB,
3792 GLenum dstRGB,
3793 GLenum srcAlpha,
3794 GLenum dstAlpha)
3795{
3796 if (!ValidSrcBlendFunc(srcRGB))
3797 {
3798 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3799 return false;
3800 }
3801
3802 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3803 {
3804 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3805 return false;
3806 }
3807
3808 if (!ValidSrcBlendFunc(srcAlpha))
3809 {
3810 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3811 return false;
3812 }
3813
3814 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3815 {
3816 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3817 return false;
3818 }
3819
3820 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3821 {
3822 bool constantColorUsed =
3823 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3824 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3825
3826 bool constantAlphaUsed =
3827 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3828 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3829
3830 if (constantColorUsed && constantAlphaUsed)
3831 {
3832 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3833 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3834 "implementation.");
3835 context->handleError(Error(GL_INVALID_OPERATION,
3836 "Simultaneous use of "
3837 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3838 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3839 "supported by this implementation."));
3840 return false;
3841 }
3842 }
3843
3844 return true;
3845}
3846
Geoff Langc339c4e2016-11-29 10:37:36 -05003847bool ValidateGetString(Context *context, GLenum name)
3848{
3849 switch (name)
3850 {
3851 case GL_VENDOR:
3852 case GL_RENDERER:
3853 case GL_VERSION:
3854 case GL_SHADING_LANGUAGE_VERSION:
3855 case GL_EXTENSIONS:
3856 break;
3857
3858 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3859 if (!context->getExtensions().requestExtension)
3860 {
3861 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3862 return false;
3863 }
3864 break;
3865
3866 default:
3867 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3868 return false;
3869 }
3870
3871 return true;
3872}
3873
Geoff Lang47c48082016-12-07 15:38:13 -05003874bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3875{
3876 if (width <= 0.0f || isNaN(width))
3877 {
3878 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3879 return false;
3880 }
3881
3882 return true;
3883}
3884
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003885bool ValidateVertexAttribPointer(ValidationContext *context,
3886 GLuint index,
3887 GLint size,
3888 GLenum type,
3889 GLboolean normalized,
3890 GLsizei stride,
3891 const GLvoid *ptr)
3892{
3893 if (index >= MAX_VERTEX_ATTRIBS)
3894 {
3895 context->handleError(Error(GL_INVALID_VALUE, "Invalid index value."));
3896 return false;
3897 }
3898
3899 if (size < 1 || size > 4)
3900 {
3901 context->handleError(Error(GL_INVALID_VALUE, "Invalide size value."));
3902 return false;
3903 }
3904
3905 switch (type)
3906 {
3907 case GL_BYTE:
3908 case GL_UNSIGNED_BYTE:
3909 case GL_SHORT:
3910 case GL_UNSIGNED_SHORT:
3911 case GL_FIXED:
3912 case GL_FLOAT:
3913 break;
3914
3915 case GL_HALF_FLOAT:
3916 case GL_INT:
3917 case GL_UNSIGNED_INT:
3918 case GL_INT_2_10_10_10_REV:
3919 case GL_UNSIGNED_INT_2_10_10_10_REV:
3920 if (context->getClientMajorVersion() < 3)
3921 {
3922 context->handleError(
3923 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
3924 return false;
3925 }
3926 break;
3927
3928 default:
3929 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
3930 return false;
3931 }
3932
3933 if (stride < 0)
3934 {
3935 context->handleError(Error(GL_INVALID_VALUE, "Invalid stride."));
3936 return false;
3937 }
3938
3939 if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
3940 {
3941 context->handleError(Error(GL_INVALID_OPERATION, "Invalid size for a sized vertex type."));
3942 return false;
3943 }
3944
3945 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3946 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3947 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3948 // and the pointer argument is not NULL.
3949 if (context->getGLState().getVertexArray()->id() != 0 &&
3950 context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
3951 {
3952 context->handleError(
3953 Error(GL_INVALID_OPERATION,
3954 "Pointer is null with a non-zero VAO bound and zero bound to GL_ARRAY_BUFFER."));
3955 return false;
3956 }
3957
3958 if (context->getExtensions().webglCompatibility)
3959 {
3960 // WebGL 1.0 [Section 6.14] Fixed point support
3961 // The WebGL API does not support the GL_FIXED data type.
3962 if (type == GL_FIXED)
3963 {
3964 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3965 return false;
3966 }
3967
3968 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
3969 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
3970 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
3971 // parameter exceeds 255.
3972 constexpr GLsizei kMaxWebGLStride = 255;
3973 if (stride > kMaxWebGLStride)
3974 {
3975 context->handleError(
3976 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
3977 return false;
3978 }
3979
3980 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
3981 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
3982 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
3983 // or an INVALID_OPERATION error is generated.
3984 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, false);
3985 size_t typeSize = GetVertexFormatTypeSize(internalType);
3986
3987 ASSERT(isPow2(typeSize) && typeSize > 0);
3988 size_t sizeMask = (typeSize - 1);
3989 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
3990 {
3991 context->handleError(
3992 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
3993 return false;
3994 }
3995
3996 if ((stride & sizeMask) != 0)
3997 {
3998 context->handleError(
3999 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
4000 return false;
4001 }
4002 }
4003
4004 return true;
4005}
4006
Jamie Madillc29968b2016-01-20 11:17:23 -05004007} // namespace gl