blob: 3b084d44231840a8b49c77303bc7343f2c3cca70 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Texture.h"
18#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
22#include "libANGLE/Uniform.h"
23#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES.h"
25#include "libANGLE/validationES3.h"
Corentin Wallez0c7baf12016-12-19 15:43:10 -050026#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
78 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
79 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
95 context->handleError(
96 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
97 return false;
98 }
99
100 if (paths == nullptr)
101 {
102 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
103 return false;
104 }
105
106 if (numPaths < 0)
107 {
108 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
114 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
160 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
188 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
193 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
202 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang97073d12016-04-20 10:42:34 -0700209bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
210{
211 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
212 switch (internalFormatInfo.format)
213 {
214 case GL_ALPHA:
215 case GL_LUMINANCE:
216 case GL_LUMINANCE_ALPHA:
217 case GL_RGB:
218 case GL_RGBA:
219 return true;
220
221 case GL_RED:
222 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
223
224 case GL_BGRA_EXT:
225 return context->getExtensions().textureFormatBGRA8888;
226
227 default:
228 return false;
229 }
230}
231
232bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
233{
234 switch (internalFormat)
235 {
236 case GL_RGB:
237 case GL_RGBA:
238 break;
239
240 case GL_BGRA_EXT:
241 return context->getExtensions().textureFormatBGRA8888;
242
243 default:
244 return false;
245 }
246
247 switch (type)
248 {
249 case GL_UNSIGNED_BYTE:
250 break;
251
252 default:
253 return false;
254 }
255
256 return true;
257}
258
259bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
260{
261 switch (target)
262 {
263 case GL_TEXTURE_2D:
264 return true;
265
266 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
267 // supported
268
269 default:
270 return false;
271 }
272}
273
274bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
275{
276 if (IsValidCopyTextureDestinationTarget(context, target))
277 {
278 return true;
279 }
280
281 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
282 // supported
283
284 return false;
285}
286
Jamie Madillc29968b2016-01-20 11:17:23 -0500287} // anonymous namespace
288
Geoff Langff5b2d52016-09-07 11:32:23 -0400289bool ValidateES2TexImageParameters(Context *context,
290 GLenum target,
291 GLint level,
292 GLenum internalformat,
293 bool isCompressed,
294 bool isSubImage,
295 GLint xoffset,
296 GLint yoffset,
297 GLsizei width,
298 GLsizei height,
299 GLint border,
300 GLenum format,
301 GLenum type,
302 GLsizei imageSize,
303 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304{
Jamie Madill6f38f822014-06-06 17:12:20 -0400305 if (!ValidTexture2DDestinationTarget(context, target))
306 {
Jamie Madill437fa652016-05-03 15:13:24 -0400307 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400308 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400309 }
310
Austin Kinross08528e12015-10-07 16:24:40 -0700311 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 {
Jamie Madill437fa652016-05-03 15:13:24 -0400313 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316
He Yunchaoced53ae2016-11-29 15:00:51 +0800317 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400318 std::numeric_limits<GLsizei>::max() - yoffset < height)
319 {
Jamie Madill437fa652016-05-03 15:13:24 -0400320 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
Geoff Lang005df412013-10-16 14:12:50 -0400324 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Jamie Madill437fa652016-05-03 15:13:24 -0400326 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 }
329
Geoff Langaae65a42014-05-26 12:43:44 -0400330 const gl::Caps &caps = context->getCaps();
331
Geoff Langa9be0dc2014-12-17 12:34:40 -0500332 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
335 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 {
Jamie Madill437fa652016-05-03 15:13:24 -0400337 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500341 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500342 {
343 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 {
Jamie Madill437fa652016-05-03 15:13:24 -0400345 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348
Geoff Langa9be0dc2014-12-17 12:34:40 -0500349 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
350 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
354 }
355 }
356 else
357 {
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400360 }
361
He Yunchaoced53ae2016-11-29 15:00:51 +0800362 gl::Texture *texture =
363 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 if (!texture)
365 {
Jamie Madill437fa652016-05-03 15:13:24 -0400366 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 }
369
Geoff Langa9be0dc2014-12-17 12:34:40 -0500370 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371 {
Geoff Langc51642b2016-11-14 16:18:26 -0500372 GLenum textureFormat = texture->getFormat(target, level).asSized();
373 if (textureFormat == GL_NONE)
374 {
375 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
376 return false;
377 }
378
Geoff Langa9be0dc2014-12-17 12:34:40 -0500379 if (format != GL_NONE)
380 {
Geoff Langc51642b2016-11-14 16:18:26 -0500381 if (gl::GetSizedInternalFormat(format, type) != textureFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500382 {
Jamie Madill437fa652016-05-03 15:13:24 -0400383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500384 return false;
385 }
386 }
387
388 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
389 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
390 {
Jamie Madill437fa652016-05-03 15:13:24 -0400391 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500392 return false;
393 }
394 }
395 else
396 {
Geoff Lang69cce582015-09-17 13:20:36 -0400397 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500398 {
Jamie Madill437fa652016-05-03 15:13:24 -0400399 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500400 return false;
401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 }
403
404 // Verify zero border
405 if (border != 0)
406 {
Jamie Madill437fa652016-05-03 15:13:24 -0400407 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409 }
410
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 if (isCompressed)
412 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400413 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400414 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415 switch (actualInternalFormat)
416 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
419 if (!context->getExtensions().textureCompressionDXT1)
420 {
421 context->handleError(Error(GL_INVALID_ENUM));
422 return false;
423 }
424 break;
425 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
426 if (!context->getExtensions().textureCompressionDXT1)
427 {
428 context->handleError(Error(GL_INVALID_ENUM));
429 return false;
430 }
431 break;
432 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
433 if (!context->getExtensions().textureCompressionDXT5)
434 {
435 context->handleError(Error(GL_INVALID_ENUM));
436 return false;
437 }
438 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800439 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
440 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
441 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
442 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
443 if (!context->getExtensions().textureCompressionS3TCsRGB)
444 {
445 context->handleError(Error(GL_INVALID_ENUM));
446 return false;
447 }
448 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 case GL_ETC1_RGB8_OES:
450 if (!context->getExtensions().compressedETC1RGB8Texture)
451 {
452 context->handleError(Error(GL_INVALID_ENUM));
453 return false;
454 }
455 break;
456 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800457 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
458 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
459 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
460 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800461 if (!context->getExtensions().lossyETCDecode)
462 {
463 context->handleError(Error(
464 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
465 return false;
466 }
467 break;
468 default:
469 context->handleError(
470 Error(GL_INVALID_ENUM,
471 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400472 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400473 }
Geoff Lang44ff5a72017-02-03 15:15:43 -0500474 if (!ValidCompressedImageSize(context, actualInternalFormat, xoffset, yoffset, width,
475 height))
tmartino0ccd5ae2015-10-01 14:33:14 -0400476 {
Jamie Madill437fa652016-05-03 15:13:24 -0400477 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400478 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400479 }
480 }
481 else
482 {
483 // validate <type> by itself (used as secondary key below)
484 switch (type)
485 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800486 case GL_UNSIGNED_BYTE:
487 case GL_UNSIGNED_SHORT_5_6_5:
488 case GL_UNSIGNED_SHORT_4_4_4_4:
489 case GL_UNSIGNED_SHORT_5_5_5_1:
490 case GL_UNSIGNED_SHORT:
491 case GL_UNSIGNED_INT:
492 case GL_UNSIGNED_INT_24_8_OES:
493 case GL_HALF_FLOAT_OES:
494 case GL_FLOAT:
495 break;
496 default:
497 context->handleError(Error(GL_INVALID_ENUM));
498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400499 }
500
501 // validate <format> + <type> combinations
502 // - invalid <format> -> sets INVALID_ENUM
503 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
504 switch (format)
505 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800506 case GL_ALPHA:
507 case GL_LUMINANCE:
508 case GL_LUMINANCE_ALPHA:
509 switch (type)
510 {
511 case GL_UNSIGNED_BYTE:
512 case GL_FLOAT:
513 case GL_HALF_FLOAT_OES:
514 break;
515 default:
516 context->handleError(Error(GL_INVALID_OPERATION));
517 return false;
518 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400519 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800520 case GL_RED:
521 case GL_RG:
522 if (!context->getExtensions().textureRG)
523 {
524 context->handleError(Error(GL_INVALID_ENUM));
525 return false;
526 }
527 switch (type)
528 {
529 case GL_UNSIGNED_BYTE:
530 case GL_FLOAT:
531 case GL_HALF_FLOAT_OES:
532 break;
533 default:
534 context->handleError(Error(GL_INVALID_OPERATION));
535 return false;
536 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400537 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800538 case GL_RGB:
539 switch (type)
540 {
541 case GL_UNSIGNED_BYTE:
542 case GL_UNSIGNED_SHORT_5_6_5:
543 case GL_FLOAT:
544 case GL_HALF_FLOAT_OES:
545 break;
546 default:
547 context->handleError(Error(GL_INVALID_OPERATION));
548 return false;
549 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400550 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800551 case GL_RGBA:
552 switch (type)
553 {
554 case GL_UNSIGNED_BYTE:
555 case GL_UNSIGNED_SHORT_4_4_4_4:
556 case GL_UNSIGNED_SHORT_5_5_5_1:
557 case GL_FLOAT:
558 case GL_HALF_FLOAT_OES:
559 break;
560 default:
561 context->handleError(Error(GL_INVALID_OPERATION));
562 return false;
563 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400564 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800565 case GL_BGRA_EXT:
566 switch (type)
567 {
568 case GL_UNSIGNED_BYTE:
569 break;
570 default:
571 context->handleError(Error(GL_INVALID_OPERATION));
572 return false;
573 }
574 break;
575 case GL_SRGB_EXT:
576 case GL_SRGB_ALPHA_EXT:
577 if (!context->getExtensions().sRGB)
578 {
579 context->handleError(Error(GL_INVALID_ENUM));
580 return false;
581 }
582 switch (type)
583 {
584 case GL_UNSIGNED_BYTE:
585 break;
586 default:
587 context->handleError(Error(GL_INVALID_OPERATION));
588 return false;
589 }
590 break;
591 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
592 // handled below
593 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
594 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
595 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
596 break;
597 case GL_DEPTH_COMPONENT:
598 switch (type)
599 {
600 case GL_UNSIGNED_SHORT:
601 case GL_UNSIGNED_INT:
602 break;
603 default:
604 context->handleError(Error(GL_INVALID_OPERATION));
605 return false;
606 }
607 break;
608 case GL_DEPTH_STENCIL_OES:
609 switch (type)
610 {
611 case GL_UNSIGNED_INT_24_8_OES:
612 break;
613 default:
614 context->handleError(Error(GL_INVALID_OPERATION));
615 return false;
616 }
617 break;
618 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400619 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400620 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400621 }
622
623 switch (format)
624 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800625 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
626 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
627 if (context->getExtensions().textureCompressionDXT1)
628 {
629 context->handleError(Error(GL_INVALID_OPERATION));
630 return false;
631 }
632 else
633 {
634 context->handleError(Error(GL_INVALID_ENUM));
635 return false;
636 }
637 break;
638 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
639 if (context->getExtensions().textureCompressionDXT3)
640 {
641 context->handleError(Error(GL_INVALID_OPERATION));
642 return false;
643 }
644 else
645 {
646 context->handleError(Error(GL_INVALID_ENUM));
647 return false;
648 }
649 break;
650 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
651 if (context->getExtensions().textureCompressionDXT5)
652 {
653 context->handleError(Error(GL_INVALID_OPERATION));
654 return false;
655 }
656 else
657 {
658 context->handleError(Error(GL_INVALID_ENUM));
659 return false;
660 }
661 break;
662 case GL_ETC1_RGB8_OES:
663 if (context->getExtensions().compressedETC1RGB8Texture)
664 {
665 context->handleError(Error(GL_INVALID_OPERATION));
666 return false;
667 }
668 else
669 {
670 context->handleError(Error(GL_INVALID_ENUM));
671 return false;
672 }
673 break;
674 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800675 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
676 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
677 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
678 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800679 if (context->getExtensions().lossyETCDecode)
680 {
681 context->handleError(
682 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -0800683 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +0800684 return false;
685 }
686 else
687 {
688 context->handleError(Error(
689 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
690 return false;
691 }
692 break;
693 case GL_DEPTH_COMPONENT:
694 case GL_DEPTH_STENCIL_OES:
695 if (!context->getExtensions().depthTextures)
696 {
697 context->handleError(Error(GL_INVALID_VALUE));
698 return false;
699 }
700 if (target != GL_TEXTURE_2D)
701 {
702 context->handleError(Error(GL_INVALID_OPERATION));
703 return false;
704 }
705 // OES_depth_texture supports loading depth data and multiple levels,
706 // but ANGLE_depth_texture does not
707 if (pixels != NULL || level != 0)
708 {
709 context->handleError(Error(GL_INVALID_OPERATION));
710 return false;
711 }
712 break;
713 default:
714 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400715 }
716
717 if (type == GL_FLOAT)
718 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400719 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400720 {
Jamie Madill437fa652016-05-03 15:13:24 -0400721 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400722 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 }
724 }
725 else if (type == GL_HALF_FLOAT_OES)
726 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400727 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400728 {
Jamie Madill437fa652016-05-03 15:13:24 -0400729 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731 }
732 }
733 }
734
Geoff Langff5b2d52016-09-07 11:32:23 -0400735 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
736 imageSize))
737 {
738 return false;
739 }
740
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400741 return true;
742}
743
Jamie Madillc29968b2016-01-20 11:17:23 -0500744bool ValidateES2CopyTexImageParameters(ValidationContext *context,
745 GLenum target,
746 GLint level,
747 GLenum internalformat,
748 bool isSubImage,
749 GLint xoffset,
750 GLint yoffset,
751 GLint x,
752 GLint y,
753 GLsizei width,
754 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 GLint border)
756{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500757 if (!ValidTexture2DDestinationTarget(context, target))
758 {
Jamie Madill437fa652016-05-03 15:13:24 -0400759 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500760 return false;
761 }
762
Geoff Langcc507aa2016-12-12 10:09:52 -0500763 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
764 {
765 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
766 return false;
767 }
768
Jamie Madill0c8abca2016-07-22 20:21:26 -0400769 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400770 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400771 xoffset, yoffset, 0, x, y, width, height, border,
772 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400773 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400774 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 }
776
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700777 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400778 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400779 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780
781 // [OpenGL ES 2.0.24] table 3.9
782 if (isSubImage)
783 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400784 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800786 case GL_ALPHA:
787 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
788 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
789 {
790 context->handleError(Error(GL_INVALID_OPERATION));
791 return false;
792 }
793 break;
794 case GL_LUMINANCE:
795 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
796 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
797 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
798 colorbufferFormat != GL_RGBA8_OES)
799 {
800 context->handleError(Error(GL_INVALID_OPERATION));
801 return false;
802 }
803 break;
804 case GL_RED_EXT:
805 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
806 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
807 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
808 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
809 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
810 colorbufferFormat != GL_RGBA32F)
811 {
812 context->handleError(Error(GL_INVALID_OPERATION));
813 return false;
814 }
815 break;
816 case GL_RG_EXT:
817 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
818 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
819 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
820 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
821 colorbufferFormat != GL_RGBA32F)
822 {
823 context->handleError(Error(GL_INVALID_OPERATION));
824 return false;
825 }
826 break;
827 case GL_RGB:
828 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
829 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
830 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
831 colorbufferFormat != GL_RGBA32F)
832 {
833 context->handleError(Error(GL_INVALID_OPERATION));
834 return false;
835 }
836 break;
837 case GL_LUMINANCE_ALPHA:
838 case GL_RGBA:
839 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
840 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
841 {
842 context->handleError(Error(GL_INVALID_OPERATION));
843 return false;
844 }
845 break;
846 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
847 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
848 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
849 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
850 case GL_ETC1_RGB8_OES:
851 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800852 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
853 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
854 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
855 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400856 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400857 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800858 case GL_DEPTH_COMPONENT:
859 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400860 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400861 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800862 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400863 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400864 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500866
Jamie Madill0c8abca2016-07-22 20:21:26 -0400867 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500868 {
Jamie Madill437fa652016-05-03 15:13:24 -0400869 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500870 return false;
871 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400872 }
873 else
874 {
875 switch (internalformat)
876 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800877 case GL_ALPHA:
878 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
879 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
880 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
881 {
882 context->handleError(Error(GL_INVALID_OPERATION));
883 return false;
884 }
885 break;
886 case GL_LUMINANCE:
887 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
888 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
889 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
890 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
891 colorbufferFormat != GL_BGR5_A1_ANGLEX)
892 {
893 context->handleError(Error(GL_INVALID_OPERATION));
894 return false;
895 }
896 break;
897 case GL_RED_EXT:
898 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
899 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
900 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
901 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
902 colorbufferFormat != GL_BGR5_A1_ANGLEX)
903 {
904 context->handleError(Error(GL_INVALID_OPERATION));
905 return false;
906 }
907 break;
908 case GL_RG_EXT:
909 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
910 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
911 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
912 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
913 {
914 context->handleError(Error(GL_INVALID_OPERATION));
915 return false;
916 }
917 break;
918 case GL_RGB:
919 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
920 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
921 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
922 colorbufferFormat != GL_BGR5_A1_ANGLEX)
923 {
924 context->handleError(Error(GL_INVALID_OPERATION));
925 return false;
926 }
927 break;
928 case GL_LUMINANCE_ALPHA:
929 case GL_RGBA:
930 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
931 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
932 colorbufferFormat != GL_BGR5_A1_ANGLEX)
933 {
934 context->handleError(Error(GL_INVALID_OPERATION));
935 return false;
936 }
937 break;
938 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
939 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
940 if (context->getExtensions().textureCompressionDXT1)
941 {
942 context->handleError(Error(GL_INVALID_OPERATION));
943 return false;
944 }
945 else
946 {
947 context->handleError(Error(GL_INVALID_ENUM));
948 return false;
949 }
950 break;
951 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
952 if (context->getExtensions().textureCompressionDXT3)
953 {
954 context->handleError(Error(GL_INVALID_OPERATION));
955 return false;
956 }
957 else
958 {
959 context->handleError(Error(GL_INVALID_ENUM));
960 return false;
961 }
962 break;
963 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
964 if (context->getExtensions().textureCompressionDXT5)
965 {
966 context->handleError(Error(GL_INVALID_OPERATION));
967 return false;
968 }
969 else
970 {
971 context->handleError(Error(GL_INVALID_ENUM));
972 return false;
973 }
974 break;
975 case GL_ETC1_RGB8_OES:
976 if (context->getExtensions().compressedETC1RGB8Texture)
977 {
978 context->handleError(Error(GL_INVALID_OPERATION));
979 return false;
980 }
981 else
982 {
983 context->handleError(Error(GL_INVALID_ENUM));
984 return false;
985 }
986 break;
987 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800988 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
989 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
990 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
991 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 if (context->getExtensions().lossyETCDecode)
993 {
994 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -0800995 "ETC lossy decode formats can't be copied to."));
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 return false;
997 }
998 else
999 {
1000 context->handleError(Error(
1001 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1002 return false;
1003 }
1004 break;
1005 case GL_DEPTH_COMPONENT:
1006 case GL_DEPTH_COMPONENT16:
1007 case GL_DEPTH_COMPONENT32_OES:
1008 case GL_DEPTH_STENCIL_OES:
1009 case GL_DEPTH24_STENCIL8_OES:
1010 if (context->getExtensions().depthTextures)
1011 {
1012 context->handleError(Error(GL_INVALID_OPERATION));
1013 return false;
1014 }
1015 else
1016 {
1017 context->handleError(Error(GL_INVALID_ENUM));
1018 return false;
1019 }
1020 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001021 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024 }
1025
Geoff Lang784a8fd2013-09-24 12:33:16 -04001026 // If width or height is zero, it is a no-op. Return false without setting an error.
1027 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028}
1029
He Yunchaoced53ae2016-11-29 15:00:51 +08001030bool ValidateES2TexStorageParameters(Context *context,
1031 GLenum target,
1032 GLsizei levels,
1033 GLenum internalformat,
1034 GLsizei width,
1035 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036{
1037 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1038 {
Jamie Madill437fa652016-05-03 15:13:24 -04001039 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 }
1042
1043 if (width < 1 || height < 1 || levels < 1)
1044 {
Jamie Madill437fa652016-05-03 15:13:24 -04001045 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001046 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 }
1048
1049 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001052 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 }
1054
1055 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1056 {
Jamie Madill437fa652016-05-03 15:13:24 -04001057 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001058 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 }
1060
Geoff Lang5d601382014-07-22 15:14:06 -04001061 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1062 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 {
Jamie Madill437fa652016-05-03 15:13:24 -04001064 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001065 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001066 }
1067
Geoff Langaae65a42014-05-26 12:43:44 -04001068 const gl::Caps &caps = context->getCaps();
1069
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070 switch (target)
1071 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_TEXTURE_2D:
1073 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1074 static_cast<GLuint>(height) > caps.max2DTextureSize)
1075 {
1076 context->handleError(Error(GL_INVALID_VALUE));
1077 return false;
1078 }
1079 break;
1080 case GL_TEXTURE_CUBE_MAP:
1081 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1082 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1083 {
1084 context->handleError(Error(GL_INVALID_VALUE));
1085 return false;
1086 }
1087 break;
1088 default:
1089 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092
Geoff Langc0b9ef42014-07-02 10:02:37 -04001093 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 {
1095 if (!gl::isPow2(width) || !gl::isPow2(height))
1096 {
Jamie Madill437fa652016-05-03 15:13:24 -04001097 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001098 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 }
1100 }
1101
1102 switch (internalformat)
1103 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001104 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1105 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1106 if (!context->getExtensions().textureCompressionDXT1)
1107 {
1108 context->handleError(Error(GL_INVALID_ENUM));
1109 return false;
1110 }
1111 break;
1112 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1113 if (!context->getExtensions().textureCompressionDXT3)
1114 {
1115 context->handleError(Error(GL_INVALID_ENUM));
1116 return false;
1117 }
1118 break;
1119 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1120 if (!context->getExtensions().textureCompressionDXT5)
1121 {
1122 context->handleError(Error(GL_INVALID_ENUM));
1123 return false;
1124 }
1125 break;
1126 case GL_ETC1_RGB8_OES:
1127 if (!context->getExtensions().compressedETC1RGB8Texture)
1128 {
1129 context->handleError(Error(GL_INVALID_ENUM));
1130 return false;
1131 }
1132 break;
1133 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001134 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1135 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1136 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1137 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001138 if (!context->getExtensions().lossyETCDecode)
1139 {
1140 context->handleError(
1141 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1142 return false;
1143 }
1144 break;
1145 case GL_RGBA32F_EXT:
1146 case GL_RGB32F_EXT:
1147 case GL_ALPHA32F_EXT:
1148 case GL_LUMINANCE32F_EXT:
1149 case GL_LUMINANCE_ALPHA32F_EXT:
1150 if (!context->getExtensions().textureFloat)
1151 {
1152 context->handleError(Error(GL_INVALID_ENUM));
1153 return false;
1154 }
1155 break;
1156 case GL_RGBA16F_EXT:
1157 case GL_RGB16F_EXT:
1158 case GL_ALPHA16F_EXT:
1159 case GL_LUMINANCE16F_EXT:
1160 case GL_LUMINANCE_ALPHA16F_EXT:
1161 if (!context->getExtensions().textureHalfFloat)
1162 {
1163 context->handleError(Error(GL_INVALID_ENUM));
1164 return false;
1165 }
1166 break;
1167 case GL_R8_EXT:
1168 case GL_RG8_EXT:
1169 case GL_R16F_EXT:
1170 case GL_RG16F_EXT:
1171 case GL_R32F_EXT:
1172 case GL_RG32F_EXT:
1173 if (!context->getExtensions().textureRG)
1174 {
1175 context->handleError(Error(GL_INVALID_ENUM));
1176 return false;
1177 }
1178 break;
1179 case GL_DEPTH_COMPONENT16:
1180 case GL_DEPTH_COMPONENT32_OES:
1181 case GL_DEPTH24_STENCIL8_OES:
1182 if (!context->getExtensions().depthTextures)
1183 {
1184 context->handleError(Error(GL_INVALID_ENUM));
1185 return false;
1186 }
1187 if (target != GL_TEXTURE_2D)
1188 {
1189 context->handleError(Error(GL_INVALID_OPERATION));
1190 return false;
1191 }
1192 // ANGLE_depth_texture only supports 1-level textures
1193 if (levels != 1)
1194 {
1195 context->handleError(Error(GL_INVALID_OPERATION));
1196 return false;
1197 }
1198 break;
1199 default:
1200 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201 }
1202
Geoff Lang691e58c2014-12-19 17:03:25 -05001203 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001204 if (!texture || texture->id() == 0)
1205 {
Jamie Madill437fa652016-05-03 15:13:24 -04001206 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001207 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001208 }
1209
Geoff Lang69cce582015-09-17 13:20:36 -04001210 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 {
Jamie Madill437fa652016-05-03 15:13:24 -04001212 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001213 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001214 }
1215
1216 return true;
1217}
1218
He Yunchaoced53ae2016-11-29 15:00:51 +08001219bool ValidateDiscardFramebufferEXT(Context *context,
1220 GLenum target,
1221 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001222 const GLenum *attachments)
1223{
Jamie Madillc29968b2016-01-20 11:17:23 -05001224 if (!context->getExtensions().discardFramebuffer)
1225 {
Jamie Madill437fa652016-05-03 15:13:24 -04001226 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001227 return false;
1228 }
1229
Austin Kinross08332632015-05-05 13:35:47 -07001230 bool defaultFramebuffer = false;
1231
1232 switch (target)
1233 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 case GL_FRAMEBUFFER:
1235 defaultFramebuffer =
1236 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1237 break;
1238 default:
1239 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1240 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001241 }
1242
He Yunchaoced53ae2016-11-29 15:00:51 +08001243 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1244 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001245}
1246
Austin Kinrossbc781f32015-10-26 09:27:38 -07001247bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1248{
1249 if (!context->getExtensions().vertexArrayObject)
1250 {
Jamie Madill437fa652016-05-03 15:13:24 -04001251 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001252 return false;
1253 }
1254
1255 return ValidateBindVertexArrayBase(context, array);
1256}
1257
1258bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1259{
1260 if (!context->getExtensions().vertexArrayObject)
1261 {
Jamie Madill437fa652016-05-03 15:13:24 -04001262 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001263 return false;
1264 }
1265
Olli Etuaho41997e72016-03-10 13:38:39 +02001266 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001267}
1268
1269bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1270{
1271 if (!context->getExtensions().vertexArrayObject)
1272 {
Jamie Madill437fa652016-05-03 15:13:24 -04001273 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001274 return false;
1275 }
1276
Olli Etuaho41997e72016-03-10 13:38:39 +02001277 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001278}
1279
1280bool ValidateIsVertexArrayOES(Context *context)
1281{
1282 if (!context->getExtensions().vertexArrayObject)
1283 {
Jamie Madill437fa652016-05-03 15:13:24 -04001284 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001285 return false;
1286 }
1287
1288 return true;
1289}
Geoff Langc5629752015-12-07 16:29:04 -05001290
1291bool ValidateProgramBinaryOES(Context *context,
1292 GLuint program,
1293 GLenum binaryFormat,
1294 const void *binary,
1295 GLint length)
1296{
1297 if (!context->getExtensions().getProgramBinary)
1298 {
Jamie Madill437fa652016-05-03 15:13:24 -04001299 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001300 return false;
1301 }
1302
1303 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1304}
1305
1306bool ValidateGetProgramBinaryOES(Context *context,
1307 GLuint program,
1308 GLsizei bufSize,
1309 GLsizei *length,
1310 GLenum *binaryFormat,
1311 void *binary)
1312{
1313 if (!context->getExtensions().getProgramBinary)
1314 {
Jamie Madill437fa652016-05-03 15:13:24 -04001315 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001316 return false;
1317 }
1318
1319 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1320}
Geoff Lange102fee2015-12-10 11:23:30 -05001321
Geoff Lang70d0f492015-12-10 17:45:46 -05001322static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1323{
1324 switch (source)
1325 {
1326 case GL_DEBUG_SOURCE_API:
1327 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1328 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1329 case GL_DEBUG_SOURCE_OTHER:
1330 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1331 return !mustBeThirdPartyOrApplication;
1332
1333 case GL_DEBUG_SOURCE_THIRD_PARTY:
1334 case GL_DEBUG_SOURCE_APPLICATION:
1335 return true;
1336
1337 default:
1338 return false;
1339 }
1340}
1341
1342static bool ValidDebugType(GLenum type)
1343{
1344 switch (type)
1345 {
1346 case GL_DEBUG_TYPE_ERROR:
1347 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1348 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1349 case GL_DEBUG_TYPE_PERFORMANCE:
1350 case GL_DEBUG_TYPE_PORTABILITY:
1351 case GL_DEBUG_TYPE_OTHER:
1352 case GL_DEBUG_TYPE_MARKER:
1353 case GL_DEBUG_TYPE_PUSH_GROUP:
1354 case GL_DEBUG_TYPE_POP_GROUP:
1355 return true;
1356
1357 default:
1358 return false;
1359 }
1360}
1361
1362static bool ValidDebugSeverity(GLenum severity)
1363{
1364 switch (severity)
1365 {
1366 case GL_DEBUG_SEVERITY_HIGH:
1367 case GL_DEBUG_SEVERITY_MEDIUM:
1368 case GL_DEBUG_SEVERITY_LOW:
1369 case GL_DEBUG_SEVERITY_NOTIFICATION:
1370 return true;
1371
1372 default:
1373 return false;
1374 }
1375}
1376
Geoff Lange102fee2015-12-10 11:23:30 -05001377bool ValidateDebugMessageControlKHR(Context *context,
1378 GLenum source,
1379 GLenum type,
1380 GLenum severity,
1381 GLsizei count,
1382 const GLuint *ids,
1383 GLboolean enabled)
1384{
1385 if (!context->getExtensions().debug)
1386 {
Jamie Madill437fa652016-05-03 15:13:24 -04001387 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001388 return false;
1389 }
1390
Geoff Lang70d0f492015-12-10 17:45:46 -05001391 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001394 return false;
1395 }
1396
1397 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001400 return false;
1401 }
1402
1403 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1404 {
Jamie Madill437fa652016-05-03 15:13:24 -04001405 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001406 return false;
1407 }
1408
1409 if (count > 0)
1410 {
1411 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001414 GL_INVALID_OPERATION,
1415 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1416 return false;
1417 }
1418
1419 if (severity != GL_DONT_CARE)
1420 {
Jamie Madill437fa652016-05-03 15:13:24 -04001421 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001422 Error(GL_INVALID_OPERATION,
1423 "If count is greater than zero, severity must be GL_DONT_CARE."));
1424 return false;
1425 }
1426 }
1427
Geoff Lange102fee2015-12-10 11:23:30 -05001428 return true;
1429}
1430
1431bool ValidateDebugMessageInsertKHR(Context *context,
1432 GLenum source,
1433 GLenum type,
1434 GLuint id,
1435 GLenum severity,
1436 GLsizei length,
1437 const GLchar *buf)
1438{
1439 if (!context->getExtensions().debug)
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001442 return false;
1443 }
1444
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001445 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001446 {
1447 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1448 // not generate an error.
1449 return false;
1450 }
1451
1452 if (!ValidDebugSeverity(severity))
1453 {
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001455 return false;
1456 }
1457
1458 if (!ValidDebugType(type))
1459 {
Jamie Madill437fa652016-05-03 15:13:24 -04001460 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001461 return false;
1462 }
1463
1464 if (!ValidDebugSource(source, true))
1465 {
Jamie Madill437fa652016-05-03 15:13:24 -04001466 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001467 return false;
1468 }
1469
1470 size_t messageLength = (length < 0) ? strlen(buf) : length;
1471 if (messageLength > context->getExtensions().maxDebugMessageLength)
1472 {
Jamie Madill437fa652016-05-03 15:13:24 -04001473 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001474 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1475 return false;
1476 }
1477
Geoff Lange102fee2015-12-10 11:23:30 -05001478 return true;
1479}
1480
1481bool ValidateDebugMessageCallbackKHR(Context *context,
1482 GLDEBUGPROCKHR callback,
1483 const void *userParam)
1484{
1485 if (!context->getExtensions().debug)
1486 {
Jamie Madill437fa652016-05-03 15:13:24 -04001487 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001488 return false;
1489 }
1490
Geoff Lange102fee2015-12-10 11:23:30 -05001491 return true;
1492}
1493
1494bool ValidateGetDebugMessageLogKHR(Context *context,
1495 GLuint count,
1496 GLsizei bufSize,
1497 GLenum *sources,
1498 GLenum *types,
1499 GLuint *ids,
1500 GLenum *severities,
1501 GLsizei *lengths,
1502 GLchar *messageLog)
1503{
1504 if (!context->getExtensions().debug)
1505 {
Jamie Madill437fa652016-05-03 15:13:24 -04001506 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001507 return false;
1508 }
1509
Geoff Lang70d0f492015-12-10 17:45:46 -05001510 if (bufSize < 0 && messageLog != nullptr)
1511 {
Jamie Madill437fa652016-05-03 15:13:24 -04001512 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001513 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1514 return false;
1515 }
1516
Geoff Lange102fee2015-12-10 11:23:30 -05001517 return true;
1518}
1519
1520bool ValidatePushDebugGroupKHR(Context *context,
1521 GLenum source,
1522 GLuint id,
1523 GLsizei length,
1524 const GLchar *message)
1525{
1526 if (!context->getExtensions().debug)
1527 {
Jamie Madill437fa652016-05-03 15:13:24 -04001528 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001529 return false;
1530 }
1531
Geoff Lang70d0f492015-12-10 17:45:46 -05001532 if (!ValidDebugSource(source, true))
1533 {
Jamie Madill437fa652016-05-03 15:13:24 -04001534 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001535 return false;
1536 }
1537
1538 size_t messageLength = (length < 0) ? strlen(message) : length;
1539 if (messageLength > context->getExtensions().maxDebugMessageLength)
1540 {
Jamie Madill437fa652016-05-03 15:13:24 -04001541 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001542 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1543 return false;
1544 }
1545
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001546 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001547 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1548 {
Jamie Madill437fa652016-05-03 15:13:24 -04001549 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001550 Error(GL_STACK_OVERFLOW,
1551 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1552 return false;
1553 }
1554
Geoff Lange102fee2015-12-10 11:23:30 -05001555 return true;
1556}
1557
1558bool ValidatePopDebugGroupKHR(Context *context)
1559{
1560 if (!context->getExtensions().debug)
1561 {
Jamie Madill437fa652016-05-03 15:13:24 -04001562 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001563 return false;
1564 }
1565
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001566 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001567 if (currentStackSize <= 1)
1568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001570 return false;
1571 }
1572
1573 return true;
1574}
1575
1576static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1577{
1578 switch (identifier)
1579 {
1580 case GL_BUFFER:
1581 if (context->getBuffer(name) == nullptr)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 return false;
1585 }
1586 return true;
1587
1588 case GL_SHADER:
1589 if (context->getShader(name) == nullptr)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001592 return false;
1593 }
1594 return true;
1595
1596 case GL_PROGRAM:
1597 if (context->getProgram(name) == nullptr)
1598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001600 return false;
1601 }
1602 return true;
1603
1604 case GL_VERTEX_ARRAY:
1605 if (context->getVertexArray(name) == nullptr)
1606 {
Jamie Madill437fa652016-05-03 15:13:24 -04001607 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001608 return false;
1609 }
1610 return true;
1611
1612 case GL_QUERY:
1613 if (context->getQuery(name) == nullptr)
1614 {
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001616 return false;
1617 }
1618 return true;
1619
1620 case GL_TRANSFORM_FEEDBACK:
1621 if (context->getTransformFeedback(name) == nullptr)
1622 {
Jamie Madill437fa652016-05-03 15:13:24 -04001623 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001624 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1625 return false;
1626 }
1627 return true;
1628
1629 case GL_SAMPLER:
1630 if (context->getSampler(name) == nullptr)
1631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001633 return false;
1634 }
1635 return true;
1636
1637 case GL_TEXTURE:
1638 if (context->getTexture(name) == nullptr)
1639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001641 return false;
1642 }
1643 return true;
1644
1645 case GL_RENDERBUFFER:
1646 if (context->getRenderbuffer(name) == nullptr)
1647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 return false;
1650 }
1651 return true;
1652
1653 case GL_FRAMEBUFFER:
1654 if (context->getFramebuffer(name) == nullptr)
1655 {
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001657 return false;
1658 }
1659 return true;
1660
1661 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001663 return false;
1664 }
Geoff Lange102fee2015-12-10 11:23:30 -05001665}
1666
Martin Radev9d901792016-07-15 15:58:58 +03001667static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1668{
1669 size_t labelLength = 0;
1670
1671 if (length < 0)
1672 {
1673 if (label != nullptr)
1674 {
1675 labelLength = strlen(label);
1676 }
1677 }
1678 else
1679 {
1680 labelLength = static_cast<size_t>(length);
1681 }
1682
1683 if (labelLength > context->getExtensions().maxLabelLength)
1684 {
1685 context->handleError(
1686 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1687 return false;
1688 }
1689
1690 return true;
1691}
1692
Geoff Lange102fee2015-12-10 11:23:30 -05001693bool ValidateObjectLabelKHR(Context *context,
1694 GLenum identifier,
1695 GLuint name,
1696 GLsizei length,
1697 const GLchar *label)
1698{
1699 if (!context->getExtensions().debug)
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001702 return false;
1703 }
1704
Geoff Lang70d0f492015-12-10 17:45:46 -05001705 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1706 {
1707 return false;
1708 }
1709
Martin Radev9d901792016-07-15 15:58:58 +03001710 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001711 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001712 return false;
1713 }
1714
Geoff Lange102fee2015-12-10 11:23:30 -05001715 return true;
1716}
1717
1718bool ValidateGetObjectLabelKHR(Context *context,
1719 GLenum identifier,
1720 GLuint name,
1721 GLsizei bufSize,
1722 GLsizei *length,
1723 GLchar *label)
1724{
1725 if (!context->getExtensions().debug)
1726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001728 return false;
1729 }
1730
Geoff Lang70d0f492015-12-10 17:45:46 -05001731 if (bufSize < 0)
1732 {
Jamie Madill437fa652016-05-03 15:13:24 -04001733 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001734 return false;
1735 }
1736
1737 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1738 {
1739 return false;
1740 }
1741
Martin Radev9d901792016-07-15 15:58:58 +03001742 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001743}
1744
1745static bool ValidateObjectPtrName(Context *context, const void *ptr)
1746{
1747 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1748 {
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001750 return false;
1751 }
1752
Geoff Lange102fee2015-12-10 11:23:30 -05001753 return true;
1754}
1755
1756bool ValidateObjectPtrLabelKHR(Context *context,
1757 const void *ptr,
1758 GLsizei length,
1759 const GLchar *label)
1760{
1761 if (!context->getExtensions().debug)
1762 {
Jamie Madill437fa652016-05-03 15:13:24 -04001763 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001764 return false;
1765 }
1766
Geoff Lang70d0f492015-12-10 17:45:46 -05001767 if (!ValidateObjectPtrName(context, ptr))
1768 {
1769 return false;
1770 }
1771
Martin Radev9d901792016-07-15 15:58:58 +03001772 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001773 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001774 return false;
1775 }
1776
Geoff Lange102fee2015-12-10 11:23:30 -05001777 return true;
1778}
1779
1780bool ValidateGetObjectPtrLabelKHR(Context *context,
1781 const void *ptr,
1782 GLsizei bufSize,
1783 GLsizei *length,
1784 GLchar *label)
1785{
1786 if (!context->getExtensions().debug)
1787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001789 return false;
1790 }
1791
Geoff Lang70d0f492015-12-10 17:45:46 -05001792 if (bufSize < 0)
1793 {
Jamie Madill437fa652016-05-03 15:13:24 -04001794 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001795 return false;
1796 }
1797
1798 if (!ValidateObjectPtrName(context, ptr))
1799 {
1800 return false;
1801 }
1802
Martin Radev9d901792016-07-15 15:58:58 +03001803 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001804}
1805
1806bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1807{
1808 if (!context->getExtensions().debug)
1809 {
Jamie Madill437fa652016-05-03 15:13:24 -04001810 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001811 return false;
1812 }
1813
Geoff Lang70d0f492015-12-10 17:45:46 -05001814 // TODO: represent this in Context::getQueryParameterInfo.
1815 switch (pname)
1816 {
1817 case GL_DEBUG_CALLBACK_FUNCTION:
1818 case GL_DEBUG_CALLBACK_USER_PARAM:
1819 break;
1820
1821 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001823 return false;
1824 }
1825
Geoff Lange102fee2015-12-10 11:23:30 -05001826 return true;
1827}
Jamie Madillc29968b2016-01-20 11:17:23 -05001828
1829bool ValidateBlitFramebufferANGLE(Context *context,
1830 GLint srcX0,
1831 GLint srcY0,
1832 GLint srcX1,
1833 GLint srcY1,
1834 GLint dstX0,
1835 GLint dstY0,
1836 GLint dstX1,
1837 GLint dstY1,
1838 GLbitfield mask,
1839 GLenum filter)
1840{
1841 if (!context->getExtensions().framebufferBlit)
1842 {
Jamie Madill437fa652016-05-03 15:13:24 -04001843 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001844 return false;
1845 }
1846
1847 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1848 {
1849 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001850 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 GL_INVALID_OPERATION,
1852 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1853 return false;
1854 }
1855
1856 if (filter == GL_LINEAR)
1857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001859 return false;
1860 }
1861
Jamie Madill51f40ec2016-06-15 14:06:00 -04001862 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1863 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001864
1865 if (mask & GL_COLOR_BUFFER_BIT)
1866 {
1867 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1868 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1869
1870 if (readColorAttachment && drawColorAttachment)
1871 {
1872 if (!(readColorAttachment->type() == GL_TEXTURE &&
1873 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1874 readColorAttachment->type() != GL_RENDERBUFFER &&
1875 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1876 {
Jamie Madill437fa652016-05-03 15:13:24 -04001877 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 return false;
1879 }
1880
Geoff Langa15472a2015-08-11 11:48:03 -04001881 for (size_t drawbufferIdx = 0;
1882 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001883 {
Geoff Langa15472a2015-08-11 11:48:03 -04001884 const FramebufferAttachment *attachment =
1885 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1886 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001887 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 if (!(attachment->type() == GL_TEXTURE &&
1889 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1890 attachment->type() != GL_RENDERBUFFER &&
1891 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1892 {
Jamie Madill437fa652016-05-03 15:13:24 -04001893 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001894 return false;
1895 }
1896
1897 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001898 if (!Format::SameSized(attachment->getFormat(),
1899 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001900 {
Jamie Madill437fa652016-05-03 15:13:24 -04001901 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001902 return false;
1903 }
1904 }
1905 }
1906
Jamie Madill51f40ec2016-06-15 14:06:00 -04001907 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1909 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
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 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1918 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1919 for (size_t i = 0; i < 2; i++)
1920 {
1921 if (mask & masks[i])
1922 {
1923 const FramebufferAttachment *readBuffer =
1924 readFramebuffer->getAttachment(attachments[i]);
1925 const FramebufferAttachment *drawBuffer =
1926 drawFramebuffer->getAttachment(attachments[i]);
1927
1928 if (readBuffer && drawBuffer)
1929 {
1930 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1931 dstX0, dstY0, dstX1, dstY1))
1932 {
1933 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05001934 context->handleError(Error(GL_INVALID_OPERATION,
1935 "Only whole-buffer depth and stencil blits are "
1936 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001937 return false;
1938 }
1939
1940 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1941 {
Jamie Madill437fa652016-05-03 15:13:24 -04001942 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001943 return false;
1944 }
1945 }
1946 }
1947 }
1948
1949 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1950 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001951}
Jamie Madillc29968b2016-01-20 11:17:23 -05001952
1953bool ValidateClear(ValidationContext *context, GLbitfield mask)
1954{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001955 auto fbo = context->getGLState().getDrawFramebuffer();
1956 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001957 {
Jamie Madill437fa652016-05-03 15:13:24 -04001958 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001959 return false;
1960 }
1961
1962 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1963 {
Jamie Madill437fa652016-05-03 15:13:24 -04001964 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001965 return false;
1966 }
1967
Geoff Lang76e65652017-03-27 14:58:02 -04001968 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
1969 {
1970 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1971 GL_SIGNED_NORMALIZED};
1972
1973 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
1974 drawBufferIdx++)
1975 {
1976 if (!ValidateWebGLFramebufferAttachmentClearType(
1977 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
1978 {
1979 return false;
1980 }
1981 }
1982 }
1983
Jamie Madillc29968b2016-01-20 11:17:23 -05001984 return true;
1985}
1986
1987bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1988{
1989 if (!context->getExtensions().drawBuffers)
1990 {
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001992 return false;
1993 }
1994
1995 return ValidateDrawBuffersBase(context, n, bufs);
1996}
1997
Jamie Madill73a84962016-02-12 09:27:23 -05001998bool ValidateTexImage2D(Context *context,
1999 GLenum target,
2000 GLint level,
2001 GLint internalformat,
2002 GLsizei width,
2003 GLsizei height,
2004 GLint border,
2005 GLenum format,
2006 GLenum type,
2007 const GLvoid *pixels)
2008{
Martin Radev1be913c2016-07-11 17:59:16 +03002009 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002010 {
2011 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002012 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002013 }
2014
Martin Radev1be913c2016-07-11 17:59:16 +03002015 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002016 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002017 0, 0, width, height, 1, border, format, type, -1,
2018 pixels);
2019}
2020
2021bool ValidateTexImage2DRobust(Context *context,
2022 GLenum target,
2023 GLint level,
2024 GLint internalformat,
2025 GLsizei width,
2026 GLsizei height,
2027 GLint border,
2028 GLenum format,
2029 GLenum type,
2030 GLsizei bufSize,
2031 const GLvoid *pixels)
2032{
2033 if (!ValidateRobustEntryPoint(context, bufSize))
2034 {
2035 return false;
2036 }
2037
2038 if (context->getClientMajorVersion() < 3)
2039 {
2040 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2041 0, 0, width, height, border, format, type, bufSize,
2042 pixels);
2043 }
2044
2045 ASSERT(context->getClientMajorVersion() >= 3);
2046 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2047 0, 0, width, height, 1, border, format, type, bufSize,
2048 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002049}
2050
2051bool ValidateTexSubImage2D(Context *context,
2052 GLenum target,
2053 GLint level,
2054 GLint xoffset,
2055 GLint yoffset,
2056 GLsizei width,
2057 GLsizei height,
2058 GLenum format,
2059 GLenum type,
2060 const GLvoid *pixels)
2061{
2062
Martin Radev1be913c2016-07-11 17:59:16 +03002063 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002064 {
2065 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002066 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002067 }
2068
Martin Radev1be913c2016-07-11 17:59:16 +03002069 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002070 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002071 yoffset, 0, width, height, 1, 0, format, type, -1,
2072 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002073}
2074
Geoff Langc52f6f12016-10-14 10:18:00 -04002075bool ValidateTexSubImage2DRobustANGLE(Context *context,
2076 GLenum target,
2077 GLint level,
2078 GLint xoffset,
2079 GLint yoffset,
2080 GLsizei width,
2081 GLsizei height,
2082 GLenum format,
2083 GLenum type,
2084 GLsizei bufSize,
2085 const GLvoid *pixels)
2086{
2087 if (!ValidateRobustEntryPoint(context, bufSize))
2088 {
2089 return false;
2090 }
2091
2092 if (context->getClientMajorVersion() < 3)
2093 {
2094 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2095 yoffset, width, height, 0, format, type, bufSize,
2096 pixels);
2097 }
2098
2099 ASSERT(context->getClientMajorVersion() >= 3);
2100 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2101 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2102 pixels);
2103}
2104
Jamie Madill73a84962016-02-12 09:27:23 -05002105bool ValidateCompressedTexImage2D(Context *context,
2106 GLenum target,
2107 GLint level,
2108 GLenum internalformat,
2109 GLsizei width,
2110 GLsizei height,
2111 GLint border,
2112 GLsizei imageSize,
2113 const GLvoid *data)
2114{
Martin Radev1be913c2016-07-11 17:59:16 +03002115 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002116 {
2117 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002118 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002119 {
2120 return false;
2121 }
2122 }
2123 else
2124 {
Martin Radev1be913c2016-07-11 17:59:16 +03002125 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002126 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002127 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002128 data))
2129 {
2130 return false;
2131 }
2132 }
2133
2134 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002135 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002136 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002137 if (blockSizeOrErr.isError())
2138 {
2139 context->handleError(blockSizeOrErr.getError());
2140 return false;
2141 }
2142
2143 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002144 {
Jamie Madill437fa652016-05-03 15:13:24 -04002145 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002146 return false;
2147 }
2148
2149 return true;
2150}
2151
2152bool ValidateCompressedTexSubImage2D(Context *context,
2153 GLenum target,
2154 GLint level,
2155 GLint xoffset,
2156 GLint yoffset,
2157 GLsizei width,
2158 GLsizei height,
2159 GLenum format,
2160 GLsizei imageSize,
2161 const GLvoid *data)
2162{
Martin Radev1be913c2016-07-11 17:59:16 +03002163 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002164 {
2165 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002166 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002167 {
2168 return false;
2169 }
2170 }
2171 else
2172 {
Martin Radev1be913c2016-07-11 17:59:16 +03002173 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002174 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002175 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002176 data))
2177 {
2178 return false;
2179 }
2180 }
2181
2182 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002183 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002184 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002185 if (blockSizeOrErr.isError())
2186 {
2187 context->handleError(blockSizeOrErr.getError());
2188 return false;
2189 }
2190
2191 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002194 return false;
2195 }
2196
2197 return true;
2198}
2199
Olli Etuaho4f667482016-03-30 15:56:35 +03002200bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2201{
Geoff Lang496c02d2016-10-20 11:38:11 -07002202 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002203}
2204
2205bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2206{
2207 if (!context->getExtensions().mapBuffer)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002210 return false;
2211 }
2212
2213 if (!ValidBufferTarget(context, target))
2214 {
Jamie Madill437fa652016-05-03 15:13:24 -04002215 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002216 return false;
2217 }
2218
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002219 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002220
2221 if (buffer == nullptr)
2222 {
Jamie Madill437fa652016-05-03 15:13:24 -04002223 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002224 return false;
2225 }
2226
2227 if (access != GL_WRITE_ONLY_OES)
2228 {
Jamie Madill437fa652016-05-03 15:13:24 -04002229 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002230 return false;
2231 }
2232
2233 if (buffer->isMapped())
2234 {
Jamie Madill437fa652016-05-03 15:13:24 -04002235 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002236 return false;
2237 }
2238
2239 return true;
2240}
2241
2242bool ValidateUnmapBufferOES(Context *context, GLenum target)
2243{
2244 if (!context->getExtensions().mapBuffer)
2245 {
Jamie Madill437fa652016-05-03 15:13:24 -04002246 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002247 return false;
2248 }
2249
2250 return ValidateUnmapBufferBase(context, target);
2251}
2252
2253bool ValidateMapBufferRangeEXT(Context *context,
2254 GLenum target,
2255 GLintptr offset,
2256 GLsizeiptr length,
2257 GLbitfield access)
2258{
2259 if (!context->getExtensions().mapBufferRange)
2260 {
Jamie Madill437fa652016-05-03 15:13:24 -04002261 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002262 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2263 return false;
2264 }
2265
2266 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2267}
2268
2269bool ValidateFlushMappedBufferRangeEXT(Context *context,
2270 GLenum target,
2271 GLintptr offset,
2272 GLsizeiptr length)
2273{
2274 if (!context->getExtensions().mapBufferRange)
2275 {
Jamie Madill437fa652016-05-03 15:13:24 -04002276 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002277 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2278 return false;
2279 }
2280
2281 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2282}
2283
Ian Ewell54f87462016-03-10 13:47:21 -05002284bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2285{
2286 Texture *textureObject = context->getTexture(texture);
2287 if (textureObject && textureObject->getTarget() != target && texture != 0)
2288 {
Jamie Madill437fa652016-05-03 15:13:24 -04002289 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002290 return false;
2291 }
2292
Geoff Langf41a7152016-09-19 15:11:17 -04002293 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2294 !context->isTextureGenerated(texture))
2295 {
2296 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2297 return false;
2298 }
2299
Ian Ewell54f87462016-03-10 13:47:21 -05002300 switch (target)
2301 {
2302 case GL_TEXTURE_2D:
2303 case GL_TEXTURE_CUBE_MAP:
2304 break;
2305
2306 case GL_TEXTURE_3D:
2307 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002308 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002309 {
Jamie Madill437fa652016-05-03 15:13:24 -04002310 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002311 return false;
2312 }
2313 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002314
2315 case GL_TEXTURE_2D_MULTISAMPLE:
2316 if (context->getClientVersion() < Version(3, 1))
2317 {
2318 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2319 return false;
2320 }
Geoff Lang3b573612016-10-31 14:08:10 -04002321 break;
2322
Ian Ewell54f87462016-03-10 13:47:21 -05002323 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002324 if (!context->getExtensions().eglImageExternal &&
2325 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002326 {
Jamie Madill437fa652016-05-03 15:13:24 -04002327 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002328 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2329 return false;
2330 }
2331 break;
2332 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002333 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002334 return false;
2335 }
2336
2337 return true;
2338}
2339
Geoff Langd8605522016-04-13 10:19:12 -04002340bool ValidateBindUniformLocationCHROMIUM(Context *context,
2341 GLuint program,
2342 GLint location,
2343 const GLchar *name)
2344{
2345 if (!context->getExtensions().bindUniformLocation)
2346 {
Jamie Madill437fa652016-05-03 15:13:24 -04002347 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002348 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2349 return false;
2350 }
2351
2352 Program *programObject = GetValidProgram(context, program);
2353 if (!programObject)
2354 {
2355 return false;
2356 }
2357
2358 if (location < 0)
2359 {
Jamie Madill437fa652016-05-03 15:13:24 -04002360 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002361 return false;
2362 }
2363
2364 const Caps &caps = context->getCaps();
2365 if (static_cast<size_t>(location) >=
2366 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2367 {
Jamie Madill437fa652016-05-03 15:13:24 -04002368 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002369 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2370 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2371 return false;
2372 }
2373
2374 if (strncmp(name, "gl_", 3) == 0)
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002377 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2378 return false;
2379 }
2380
2381 return true;
2382}
2383
Jamie Madille2e406c2016-06-02 13:04:10 -04002384bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002385{
2386 if (!context->getExtensions().framebufferMixedSamples)
2387 {
2388 context->handleError(
2389 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2390 return false;
2391 }
2392 switch (components)
2393 {
2394 case GL_RGB:
2395 case GL_RGBA:
2396 case GL_ALPHA:
2397 case GL_NONE:
2398 break;
2399 default:
2400 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002401 Error(GL_INVALID_ENUM,
2402 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002403 return false;
2404 }
2405
2406 return true;
2407}
2408
Sami Väisänene45e53b2016-05-25 10:36:04 +03002409// CHROMIUM_path_rendering
2410
2411bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2412{
2413 if (!context->getExtensions().pathRendering)
2414 {
2415 context->handleError(
2416 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2417 return false;
2418 }
2419 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2420 {
2421 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2422 return false;
2423 }
2424 if (matrix == nullptr)
2425 {
2426 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2427 return false;
2428 }
2429 return true;
2430}
2431
2432bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2433{
2434 if (!context->getExtensions().pathRendering)
2435 {
2436 context->handleError(
2437 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2438 return false;
2439 }
2440 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2441 {
2442 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2443 return false;
2444 }
2445 return true;
2446}
2447
2448bool ValidateGenPaths(Context *context, GLsizei range)
2449{
2450 if (!context->getExtensions().pathRendering)
2451 {
2452 context->handleError(
2453 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2454 return false;
2455 }
2456
2457 // range = 0 is undefined in NV_path_rendering.
2458 // we add stricter semantic check here and require a non zero positive range.
2459 if (range <= 0)
2460 {
2461 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2462 return false;
2463 }
2464
2465 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2466 {
2467 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2468 return false;
2469 }
2470
2471 return true;
2472}
2473
2474bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2475{
2476 if (!context->getExtensions().pathRendering)
2477 {
2478 context->handleError(
2479 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2480 return false;
2481 }
2482
2483 // range = 0 is undefined in NV_path_rendering.
2484 // we add stricter semantic check here and require a non zero positive range.
2485 if (range <= 0)
2486 {
2487 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2488 return false;
2489 }
2490
2491 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2492 checkedRange += range;
2493
2494 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2495 {
2496 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2497 return false;
2498 }
2499 return true;
2500}
2501
2502bool ValidatePathCommands(Context *context,
2503 GLuint path,
2504 GLsizei numCommands,
2505 const GLubyte *commands,
2506 GLsizei numCoords,
2507 GLenum coordType,
2508 const void *coords)
2509{
2510 if (!context->getExtensions().pathRendering)
2511 {
2512 context->handleError(
2513 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2514 return false;
2515 }
2516 if (!context->hasPath(path))
2517 {
2518 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2519 return false;
2520 }
2521
2522 if (numCommands < 0)
2523 {
2524 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2525 return false;
2526 }
2527 else if (numCommands > 0)
2528 {
2529 if (!commands)
2530 {
2531 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2532 return false;
2533 }
2534 }
2535
2536 if (numCoords < 0)
2537 {
2538 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2539 return false;
2540 }
2541 else if (numCoords > 0)
2542 {
2543 if (!coords)
2544 {
2545 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2546 return false;
2547 }
2548 }
2549
2550 std::uint32_t coordTypeSize = 0;
2551 switch (coordType)
2552 {
2553 case GL_BYTE:
2554 coordTypeSize = sizeof(GLbyte);
2555 break;
2556
2557 case GL_UNSIGNED_BYTE:
2558 coordTypeSize = sizeof(GLubyte);
2559 break;
2560
2561 case GL_SHORT:
2562 coordTypeSize = sizeof(GLshort);
2563 break;
2564
2565 case GL_UNSIGNED_SHORT:
2566 coordTypeSize = sizeof(GLushort);
2567 break;
2568
2569 case GL_FLOAT:
2570 coordTypeSize = sizeof(GLfloat);
2571 break;
2572
2573 default:
2574 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2575 return false;
2576 }
2577
2578 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2579 checkedSize += (coordTypeSize * numCoords);
2580 if (!checkedSize.IsValid())
2581 {
2582 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2583 return false;
2584 }
2585
2586 // early return skips command data validation when it doesn't exist.
2587 if (!commands)
2588 return true;
2589
2590 GLsizei expectedNumCoords = 0;
2591 for (GLsizei i = 0; i < numCommands; ++i)
2592 {
2593 switch (commands[i])
2594 {
2595 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2596 break;
2597 case GL_MOVE_TO_CHROMIUM:
2598 case GL_LINE_TO_CHROMIUM:
2599 expectedNumCoords += 2;
2600 break;
2601 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2602 expectedNumCoords += 4;
2603 break;
2604 case GL_CUBIC_CURVE_TO_CHROMIUM:
2605 expectedNumCoords += 6;
2606 break;
2607 case GL_CONIC_CURVE_TO_CHROMIUM:
2608 expectedNumCoords += 5;
2609 break;
2610 default:
2611 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2612 return false;
2613 }
2614 }
2615 if (expectedNumCoords != numCoords)
2616 {
2617 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2618 return false;
2619 }
2620
2621 return true;
2622}
2623
2624bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2625{
2626 if (!context->getExtensions().pathRendering)
2627 {
2628 context->handleError(
2629 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2630 return false;
2631 }
2632 if (!context->hasPath(path))
2633 {
2634 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2635 return false;
2636 }
2637
2638 switch (pname)
2639 {
2640 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2641 if (value < 0.0f)
2642 {
2643 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2644 return false;
2645 }
2646 break;
2647 case GL_PATH_END_CAPS_CHROMIUM:
2648 switch (static_cast<GLenum>(value))
2649 {
2650 case GL_FLAT_CHROMIUM:
2651 case GL_SQUARE_CHROMIUM:
2652 case GL_ROUND_CHROMIUM:
2653 break;
2654 default:
2655 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2656 return false;
2657 }
2658 break;
2659 case GL_PATH_JOIN_STYLE_CHROMIUM:
2660 switch (static_cast<GLenum>(value))
2661 {
2662 case GL_MITER_REVERT_CHROMIUM:
2663 case GL_BEVEL_CHROMIUM:
2664 case GL_ROUND_CHROMIUM:
2665 break;
2666 default:
2667 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2668 return false;
2669 }
2670 case GL_PATH_MITER_LIMIT_CHROMIUM:
2671 if (value < 0.0f)
2672 {
2673 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2674 return false;
2675 }
2676 break;
2677
2678 case GL_PATH_STROKE_BOUND_CHROMIUM:
2679 // no errors, only clamping.
2680 break;
2681
2682 default:
2683 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2684 return false;
2685 }
2686 return true;
2687}
2688
2689bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2690{
2691 if (!context->getExtensions().pathRendering)
2692 {
2693 context->handleError(
2694 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2695 return false;
2696 }
2697
2698 if (!context->hasPath(path))
2699 {
2700 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2701 return false;
2702 }
2703 if (!value)
2704 {
2705 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2706 return false;
2707 }
2708
2709 switch (pname)
2710 {
2711 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2712 case GL_PATH_END_CAPS_CHROMIUM:
2713 case GL_PATH_JOIN_STYLE_CHROMIUM:
2714 case GL_PATH_MITER_LIMIT_CHROMIUM:
2715 case GL_PATH_STROKE_BOUND_CHROMIUM:
2716 break;
2717
2718 default:
2719 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2720 return false;
2721 }
2722
2723 return true;
2724}
2725
2726bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2727{
2728 if (!context->getExtensions().pathRendering)
2729 {
2730 context->handleError(
2731 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2732 return false;
2733 }
2734
2735 switch (func)
2736 {
2737 case GL_NEVER:
2738 case GL_ALWAYS:
2739 case GL_LESS:
2740 case GL_LEQUAL:
2741 case GL_EQUAL:
2742 case GL_GEQUAL:
2743 case GL_GREATER:
2744 case GL_NOTEQUAL:
2745 break;
2746 default:
2747 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2748 return false;
2749 }
2750
2751 return true;
2752}
2753
2754// Note that the spec specifies that for the path drawing commands
2755// if the path object is not an existing path object the command
2756// does nothing and no error is generated.
2757// However if the path object exists but has not been specified any
2758// commands then an error is generated.
2759
2760bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2761{
2762 if (!context->getExtensions().pathRendering)
2763 {
2764 context->handleError(
2765 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2766 return false;
2767 }
2768 if (context->hasPath(path) && !context->hasPathData(path))
2769 {
2770 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2771 return false;
2772 }
2773
2774 switch (fillMode)
2775 {
2776 case GL_COUNT_UP_CHROMIUM:
2777 case GL_COUNT_DOWN_CHROMIUM:
2778 break;
2779 default:
2780 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2781 return false;
2782 }
2783
2784 if (!isPow2(mask + 1))
2785 {
2786 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2787 return false;
2788 }
2789
2790 return true;
2791}
2792
2793bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2794{
2795 if (!context->getExtensions().pathRendering)
2796 {
2797 context->handleError(
2798 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2799 return false;
2800 }
2801 if (context->hasPath(path) && !context->hasPathData(path))
2802 {
2803 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2804 return false;
2805 }
2806
2807 return true;
2808}
2809
2810bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2811{
2812 if (!context->getExtensions().pathRendering)
2813 {
2814 context->handleError(
2815 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2816 return false;
2817 }
2818 if (context->hasPath(path) && !context->hasPathData(path))
2819 {
2820 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2821 return false;
2822 }
2823
2824 switch (coverMode)
2825 {
2826 case GL_CONVEX_HULL_CHROMIUM:
2827 case GL_BOUNDING_BOX_CHROMIUM:
2828 break;
2829 default:
2830 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2831 return false;
2832 }
2833 return true;
2834}
2835
2836bool ValidateStencilThenCoverFillPath(Context *context,
2837 GLuint path,
2838 GLenum fillMode,
2839 GLuint mask,
2840 GLenum coverMode)
2841{
2842 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2843 ValidateCoverPath(context, path, coverMode);
2844}
2845
2846bool ValidateStencilThenCoverStrokePath(Context *context,
2847 GLuint path,
2848 GLint reference,
2849 GLuint mask,
2850 GLenum coverMode)
2851{
2852 return ValidateStencilStrokePath(context, path, reference, mask) &&
2853 ValidateCoverPath(context, path, coverMode);
2854}
2855
2856bool ValidateIsPath(Context *context)
2857{
2858 if (!context->getExtensions().pathRendering)
2859 {
2860 context->handleError(
2861 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2862 return false;
2863 }
2864 return true;
2865}
2866
Sami Väisänend59ca052016-06-21 16:10:00 +03002867bool ValidateCoverFillPathInstanced(Context *context,
2868 GLsizei numPaths,
2869 GLenum pathNameType,
2870 const void *paths,
2871 GLuint pathBase,
2872 GLenum coverMode,
2873 GLenum transformType,
2874 const GLfloat *transformValues)
2875{
2876 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2877 transformType, transformValues))
2878 return false;
2879
2880 switch (coverMode)
2881 {
2882 case GL_CONVEX_HULL_CHROMIUM:
2883 case GL_BOUNDING_BOX_CHROMIUM:
2884 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2885 break;
2886 default:
2887 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2888 return false;
2889 }
2890
2891 return true;
2892}
2893
2894bool ValidateCoverStrokePathInstanced(Context *context,
2895 GLsizei numPaths,
2896 GLenum pathNameType,
2897 const void *paths,
2898 GLuint pathBase,
2899 GLenum coverMode,
2900 GLenum transformType,
2901 const GLfloat *transformValues)
2902{
2903 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2904 transformType, transformValues))
2905 return false;
2906
2907 switch (coverMode)
2908 {
2909 case GL_CONVEX_HULL_CHROMIUM:
2910 case GL_BOUNDING_BOX_CHROMIUM:
2911 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2912 break;
2913 default:
2914 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2915 return false;
2916 }
2917
2918 return true;
2919}
2920
2921bool ValidateStencilFillPathInstanced(Context *context,
2922 GLsizei numPaths,
2923 GLenum pathNameType,
2924 const void *paths,
2925 GLuint pathBase,
2926 GLenum fillMode,
2927 GLuint mask,
2928 GLenum transformType,
2929 const GLfloat *transformValues)
2930{
2931
2932 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2933 transformType, transformValues))
2934 return false;
2935
2936 switch (fillMode)
2937 {
2938 case GL_COUNT_UP_CHROMIUM:
2939 case GL_COUNT_DOWN_CHROMIUM:
2940 break;
2941 default:
2942 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2943 return false;
2944 }
2945 if (!isPow2(mask + 1))
2946 {
2947 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2948 return false;
2949 }
2950 return true;
2951}
2952
2953bool ValidateStencilStrokePathInstanced(Context *context,
2954 GLsizei numPaths,
2955 GLenum pathNameType,
2956 const void *paths,
2957 GLuint pathBase,
2958 GLint reference,
2959 GLuint mask,
2960 GLenum transformType,
2961 const GLfloat *transformValues)
2962{
2963 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2964 transformType, transformValues))
2965 return false;
2966
2967 // no more validation here.
2968
2969 return true;
2970}
2971
2972bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2973 GLsizei numPaths,
2974 GLenum pathNameType,
2975 const void *paths,
2976 GLuint pathBase,
2977 GLenum fillMode,
2978 GLuint mask,
2979 GLenum coverMode,
2980 GLenum transformType,
2981 const GLfloat *transformValues)
2982{
2983 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2984 transformType, transformValues))
2985 return false;
2986
2987 switch (coverMode)
2988 {
2989 case GL_CONVEX_HULL_CHROMIUM:
2990 case GL_BOUNDING_BOX_CHROMIUM:
2991 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2992 break;
2993 default:
2994 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2995 return false;
2996 }
2997
2998 switch (fillMode)
2999 {
3000 case GL_COUNT_UP_CHROMIUM:
3001 case GL_COUNT_DOWN_CHROMIUM:
3002 break;
3003 default:
3004 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3005 return false;
3006 }
3007 if (!isPow2(mask + 1))
3008 {
3009 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3010 return false;
3011 }
3012
3013 return true;
3014}
3015
3016bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3017 GLsizei numPaths,
3018 GLenum pathNameType,
3019 const void *paths,
3020 GLuint pathBase,
3021 GLint reference,
3022 GLuint mask,
3023 GLenum coverMode,
3024 GLenum transformType,
3025 const GLfloat *transformValues)
3026{
3027 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3028 transformType, transformValues))
3029 return false;
3030
3031 switch (coverMode)
3032 {
3033 case GL_CONVEX_HULL_CHROMIUM:
3034 case GL_BOUNDING_BOX_CHROMIUM:
3035 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3036 break;
3037 default:
3038 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3039 return false;
3040 }
3041
3042 return true;
3043}
3044
Sami Väisänen46eaa942016-06-29 10:26:37 +03003045bool ValidateBindFragmentInputLocation(Context *context,
3046 GLuint program,
3047 GLint location,
3048 const GLchar *name)
3049{
3050 if (!context->getExtensions().pathRendering)
3051 {
3052 context->handleError(
3053 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3054 return false;
3055 }
3056
3057 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3058 if (location >= MaxLocation)
3059 {
3060 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3061 return false;
3062 }
3063
3064 const auto *programObject = context->getProgram(program);
3065 if (!programObject)
3066 {
3067 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3068 return false;
3069 }
3070
3071 if (!name)
3072 {
3073 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3074 return false;
3075 }
3076
3077 if (angle::BeginsWith(name, "gl_"))
3078 {
3079 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3080 return false;
3081 }
3082
3083 return true;
3084}
3085
3086bool ValidateProgramPathFragmentInputGen(Context *context,
3087 GLuint program,
3088 GLint location,
3089 GLenum genMode,
3090 GLint components,
3091 const GLfloat *coeffs)
3092{
3093 if (!context->getExtensions().pathRendering)
3094 {
3095 context->handleError(
3096 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3097 return false;
3098 }
3099
3100 const auto *programObject = context->getProgram(program);
3101 if (!programObject || programObject->isFlaggedForDeletion())
3102 {
3103 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3104 return false;
3105 }
3106
3107 if (!programObject->isLinked())
3108 {
3109 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3110 return false;
3111 }
3112
3113 switch (genMode)
3114 {
3115 case GL_NONE:
3116 if (components != 0)
3117 {
3118 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3119 return false;
3120 }
3121 break;
3122
3123 case GL_OBJECT_LINEAR_CHROMIUM:
3124 case GL_EYE_LINEAR_CHROMIUM:
3125 case GL_CONSTANT_CHROMIUM:
3126 if (components < 1 || components > 4)
3127 {
3128 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3129 return false;
3130 }
3131 if (!coeffs)
3132 {
3133 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3134 return false;
3135 }
3136 break;
3137
3138 default:
3139 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3140 return false;
3141 }
3142
3143 // If the location is -1 then the command is silently ignored
3144 // and no further validation is needed.
3145 if (location == -1)
3146 return true;
3147
3148 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3149
3150 if (!binding.valid)
3151 {
3152 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3153 return false;
3154 }
3155
3156 if (binding.type != GL_NONE)
3157 {
3158 GLint expectedComponents = 0;
3159 switch (binding.type)
3160 {
3161 case GL_FLOAT:
3162 expectedComponents = 1;
3163 break;
3164 case GL_FLOAT_VEC2:
3165 expectedComponents = 2;
3166 break;
3167 case GL_FLOAT_VEC3:
3168 expectedComponents = 3;
3169 break;
3170 case GL_FLOAT_VEC4:
3171 expectedComponents = 4;
3172 break;
3173 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003174 context->handleError(
3175 Error(GL_INVALID_OPERATION,
3176 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003177 return false;
3178 }
3179 if (expectedComponents != components && genMode != GL_NONE)
3180 {
3181 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3182 return false;
3183 }
3184 }
3185 return true;
3186}
3187
Geoff Lang97073d12016-04-20 10:42:34 -07003188bool ValidateCopyTextureCHROMIUM(Context *context,
3189 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003190 GLint sourceLevel,
3191 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003192 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003193 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003194 GLint internalFormat,
3195 GLenum destType,
3196 GLboolean unpackFlipY,
3197 GLboolean unpackPremultiplyAlpha,
3198 GLboolean unpackUnmultiplyAlpha)
3199{
3200 if (!context->getExtensions().copyTexture)
3201 {
3202 context->handleError(
3203 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3204 return false;
3205 }
3206
3207 const gl::Texture *source = context->getTexture(sourceId);
3208 if (source == nullptr)
3209 {
3210 context->handleError(
3211 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3212 return false;
3213 }
3214
3215 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3216 {
3217 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3218 return false;
3219 }
3220
3221 GLenum sourceTarget = source->getTarget();
3222 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3223 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3224 {
3225 context->handleError(
3226 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3227 return false;
3228 }
3229
3230 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3231 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3232 {
3233 context->handleError(
3234 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3235 return false;
3236 }
3237
3238 const gl::Texture *dest = context->getTexture(destId);
3239 if (dest == nullptr)
3240 {
3241 context->handleError(
3242 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3243 return false;
3244 }
3245
3246 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3247 {
3248 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3249 return false;
3250 }
3251
3252 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3253 {
3254 context->handleError(
3255 Error(GL_INVALID_OPERATION,
3256 "Destination internal format and type combination is not valid."));
3257 return false;
3258 }
3259
3260 if (dest->getImmutableFormat())
3261 {
3262 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3263 return false;
3264 }
3265
3266 return true;
3267}
3268
3269bool ValidateCopySubTextureCHROMIUM(Context *context,
3270 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003271 GLint sourceLevel,
3272 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003273 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003274 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003275 GLint xoffset,
3276 GLint yoffset,
3277 GLint x,
3278 GLint y,
3279 GLsizei width,
3280 GLsizei height,
3281 GLboolean unpackFlipY,
3282 GLboolean unpackPremultiplyAlpha,
3283 GLboolean unpackUnmultiplyAlpha)
3284{
3285 if (!context->getExtensions().copyTexture)
3286 {
3287 context->handleError(
3288 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3289 return false;
3290 }
3291
3292 const gl::Texture *source = context->getTexture(sourceId);
3293 if (source == nullptr)
3294 {
3295 context->handleError(
3296 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3297 return false;
3298 }
3299
3300 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3301 {
3302 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3303 return false;
3304 }
3305
3306 GLenum sourceTarget = source->getTarget();
3307 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3308 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3309 {
3310 context->handleError(
3311 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3312 return false;
3313 }
3314
3315 if (x < 0 || y < 0)
3316 {
3317 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3318 return false;
3319 }
3320
3321 if (width < 0 || height < 0)
3322 {
3323 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3324 return false;
3325 }
3326
3327 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3328 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3329 {
3330 context->handleError(
3331 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3332 return false;
3333 }
3334
3335 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3336 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3337 {
3338 context->handleError(
3339 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3340 return false;
3341 }
3342
3343 const gl::Texture *dest = context->getTexture(destId);
3344 if (dest == nullptr)
3345 {
3346 context->handleError(
3347 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3348 return false;
3349 }
3350
3351 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3352 {
3353 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3354 return false;
3355 }
3356
Geoff Lang97073d12016-04-20 10:42:34 -07003357 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3358 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3359 {
3360 context->handleError(
3361 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3362 return false;
3363 }
3364
3365 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3366 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3367 {
3368 context->handleError(
3369 Error(GL_INVALID_OPERATION,
3370 "Destination internal format and type combination is not valid."));
3371 return false;
3372 }
3373
3374 if (xoffset < 0 || yoffset < 0)
3375 {
3376 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3377 return false;
3378 }
3379
3380 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3381 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3382 {
3383 context->handleError(
3384 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3385 return false;
3386 }
3387
3388 return true;
3389}
3390
Geoff Lang47110bf2016-04-20 11:13:22 -07003391bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3392{
3393 if (!context->getExtensions().copyCompressedTexture)
3394 {
3395 context->handleError(Error(GL_INVALID_OPERATION,
3396 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3397 return false;
3398 }
3399
3400 const gl::Texture *source = context->getTexture(sourceId);
3401 if (source == nullptr)
3402 {
3403 context->handleError(
3404 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3405 return false;
3406 }
3407
3408 if (source->getTarget() != GL_TEXTURE_2D)
3409 {
3410 context->handleError(
3411 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3412 return false;
3413 }
3414
3415 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3416 {
3417 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3418 return false;
3419 }
3420
3421 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3422 if (!sourceFormat.info->compressed)
3423 {
3424 context->handleError(
3425 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3426 return false;
3427 }
3428
3429 const gl::Texture *dest = context->getTexture(destId);
3430 if (dest == nullptr)
3431 {
3432 context->handleError(
3433 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3434 return false;
3435 }
3436
3437 if (dest->getTarget() != GL_TEXTURE_2D)
3438 {
3439 context->handleError(
3440 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3441 return false;
3442 }
3443
3444 if (dest->getImmutableFormat())
3445 {
3446 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3447 return false;
3448 }
3449
3450 return true;
3451}
3452
Martin Radev4c4c8e72016-08-04 12:25:34 +03003453bool ValidateCreateShader(Context *context, GLenum type)
3454{
3455 switch (type)
3456 {
3457 case GL_VERTEX_SHADER:
3458 case GL_FRAGMENT_SHADER:
3459 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003460
Martin Radev4c4c8e72016-08-04 12:25:34 +03003461 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003462 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003463 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003464 context->handleError(
3465 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3466 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003467 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003468 break;
3469
Martin Radev4c4c8e72016-08-04 12:25:34 +03003470 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003471 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003472 return false;
3473 }
Jamie Madill29639852016-09-02 15:00:09 -04003474
3475 return true;
3476}
3477
3478bool ValidateBufferData(ValidationContext *context,
3479 GLenum target,
3480 GLsizeiptr size,
3481 const GLvoid *data,
3482 GLenum usage)
3483{
3484 if (size < 0)
3485 {
3486 context->handleError(Error(GL_INVALID_VALUE));
3487 return false;
3488 }
3489
3490 switch (usage)
3491 {
3492 case GL_STREAM_DRAW:
3493 case GL_STATIC_DRAW:
3494 case GL_DYNAMIC_DRAW:
3495 break;
3496
3497 case GL_STREAM_READ:
3498 case GL_STREAM_COPY:
3499 case GL_STATIC_READ:
3500 case GL_STATIC_COPY:
3501 case GL_DYNAMIC_READ:
3502 case GL_DYNAMIC_COPY:
3503 if (context->getClientMajorVersion() < 3)
3504 {
3505 context->handleError(Error(GL_INVALID_ENUM));
3506 return false;
3507 }
3508 break;
3509
3510 default:
3511 context->handleError(Error(GL_INVALID_ENUM));
3512 return false;
3513 }
3514
3515 if (!ValidBufferTarget(context, target))
3516 {
3517 context->handleError(Error(GL_INVALID_ENUM));
3518 return false;
3519 }
3520
3521 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3522
3523 if (!buffer)
3524 {
3525 context->handleError(Error(GL_INVALID_OPERATION));
3526 return false;
3527 }
3528
3529 return true;
3530}
3531
3532bool ValidateBufferSubData(ValidationContext *context,
3533 GLenum target,
3534 GLintptr offset,
3535 GLsizeiptr size,
3536 const GLvoid *data)
3537{
3538 if (size < 0 || offset < 0)
3539 {
3540 context->handleError(Error(GL_INVALID_VALUE));
3541 return false;
3542 }
3543
3544 if (!ValidBufferTarget(context, target))
3545 {
3546 context->handleError(Error(GL_INVALID_ENUM));
3547 return false;
3548 }
3549
3550 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3551
3552 if (!buffer)
3553 {
3554 context->handleError(Error(GL_INVALID_OPERATION));
3555 return false;
3556 }
3557
3558 if (buffer->isMapped())
3559 {
3560 context->handleError(Error(GL_INVALID_OPERATION));
3561 return false;
3562 }
3563
3564 // Check for possible overflow of size + offset
3565 angle::CheckedNumeric<size_t> checkedSize(size);
3566 checkedSize += offset;
3567 if (!checkedSize.IsValid())
3568 {
3569 context->handleError(Error(GL_OUT_OF_MEMORY));
3570 return false;
3571 }
3572
3573 if (size + offset > buffer->getSize())
3574 {
3575 context->handleError(Error(GL_INVALID_VALUE));
3576 return false;
3577 }
3578
Martin Radev4c4c8e72016-08-04 12:25:34 +03003579 return true;
3580}
3581
Geoff Langc339c4e2016-11-29 10:37:36 -05003582bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003583{
Geoff Langc339c4e2016-11-29 10:37:36 -05003584 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003585 {
3586 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003587 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003588 return false;
3589 }
3590
3591 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3592 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003593 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003594 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003595 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003596 return false;
3597 }
3598
3599 return true;
3600}
3601
Jamie Madillef300b12016-10-07 15:12:09 -04003602bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3603{
3604 if (texture < GL_TEXTURE0 ||
3605 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3606 {
3607 context->handleError(Error(GL_INVALID_ENUM));
3608 return false;
3609 }
3610
3611 return true;
3612}
3613
3614bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3615{
3616 Program *programObject = GetValidProgram(context, program);
3617 if (!programObject)
3618 {
3619 return false;
3620 }
3621
3622 Shader *shaderObject = GetValidShader(context, shader);
3623 if (!shaderObject)
3624 {
3625 return false;
3626 }
3627
3628 switch (shaderObject->getType())
3629 {
3630 case GL_VERTEX_SHADER:
3631 {
3632 if (programObject->getAttachedVertexShader())
3633 {
3634 context->handleError(Error(GL_INVALID_OPERATION));
3635 return false;
3636 }
3637 break;
3638 }
3639 case GL_FRAGMENT_SHADER:
3640 {
3641 if (programObject->getAttachedFragmentShader())
3642 {
3643 context->handleError(Error(GL_INVALID_OPERATION));
3644 return false;
3645 }
3646 break;
3647 }
3648 case GL_COMPUTE_SHADER:
3649 {
3650 if (programObject->getAttachedComputeShader())
3651 {
3652 context->handleError(Error(GL_INVALID_OPERATION));
3653 return false;
3654 }
3655 break;
3656 }
3657 default:
3658 UNREACHABLE();
3659 break;
3660 }
3661
3662 return true;
3663}
3664
Jamie Madill01a80ee2016-11-07 12:06:18 -05003665bool ValidateBindAttribLocation(ValidationContext *context,
3666 GLuint program,
3667 GLuint index,
3668 const GLchar *name)
3669{
3670 if (index >= MAX_VERTEX_ATTRIBS)
3671 {
3672 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3673 return false;
3674 }
3675
3676 if (strncmp(name, "gl_", 3) == 0)
3677 {
3678 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3679 return false;
3680 }
3681
3682 return GetValidProgram(context, program) != nullptr;
3683}
3684
3685bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3686{
3687 if (!ValidBufferTarget(context, target))
3688 {
3689 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3690 return false;
3691 }
3692
3693 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3694 !context->isBufferGenerated(buffer))
3695 {
3696 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3697 return false;
3698 }
3699
3700 return true;
3701}
3702
3703bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3704{
3705 if (!ValidFramebufferTarget(target))
3706 {
3707 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3708 return false;
3709 }
3710
3711 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3712 !context->isFramebufferGenerated(framebuffer))
3713 {
3714 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3715 return false;
3716 }
3717
3718 return true;
3719}
3720
3721bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3722{
3723 if (target != GL_RENDERBUFFER)
3724 {
3725 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3726 return false;
3727 }
3728
3729 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3730 !context->isRenderbufferGenerated(renderbuffer))
3731 {
3732 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3733 return false;
3734 }
3735
3736 return true;
3737}
3738
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003739static bool ValidBlendEquationMode(GLenum mode)
3740{
3741 switch (mode)
3742 {
3743 case GL_FUNC_ADD:
3744 case GL_FUNC_SUBTRACT:
3745 case GL_FUNC_REVERSE_SUBTRACT:
3746 case GL_MIN:
3747 case GL_MAX:
3748 return true;
3749
3750 default:
3751 return false;
3752 }
3753}
3754
3755bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3756{
3757 if (!ValidBlendEquationMode(mode))
3758 {
3759 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3760 return false;
3761 }
3762
3763 return true;
3764}
3765
3766bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3767{
3768 if (!ValidBlendEquationMode(modeRGB))
3769 {
3770 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3771 return false;
3772 }
3773
3774 if (!ValidBlendEquationMode(modeAlpha))
3775 {
3776 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3777 return false;
3778 }
3779
3780 return true;
3781}
3782
3783bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3784{
3785 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3786}
3787
3788static bool ValidSrcBlendFunc(GLenum srcBlend)
3789{
3790 switch (srcBlend)
3791 {
3792 case GL_ZERO:
3793 case GL_ONE:
3794 case GL_SRC_COLOR:
3795 case GL_ONE_MINUS_SRC_COLOR:
3796 case GL_DST_COLOR:
3797 case GL_ONE_MINUS_DST_COLOR:
3798 case GL_SRC_ALPHA:
3799 case GL_ONE_MINUS_SRC_ALPHA:
3800 case GL_DST_ALPHA:
3801 case GL_ONE_MINUS_DST_ALPHA:
3802 case GL_CONSTANT_COLOR:
3803 case GL_ONE_MINUS_CONSTANT_COLOR:
3804 case GL_CONSTANT_ALPHA:
3805 case GL_ONE_MINUS_CONSTANT_ALPHA:
3806 case GL_SRC_ALPHA_SATURATE:
3807 return true;
3808
3809 default:
3810 return false;
3811 }
3812}
3813
3814static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3815{
3816 switch (dstBlend)
3817 {
3818 case GL_ZERO:
3819 case GL_ONE:
3820 case GL_SRC_COLOR:
3821 case GL_ONE_MINUS_SRC_COLOR:
3822 case GL_DST_COLOR:
3823 case GL_ONE_MINUS_DST_COLOR:
3824 case GL_SRC_ALPHA:
3825 case GL_ONE_MINUS_SRC_ALPHA:
3826 case GL_DST_ALPHA:
3827 case GL_ONE_MINUS_DST_ALPHA:
3828 case GL_CONSTANT_COLOR:
3829 case GL_ONE_MINUS_CONSTANT_COLOR:
3830 case GL_CONSTANT_ALPHA:
3831 case GL_ONE_MINUS_CONSTANT_ALPHA:
3832 return true;
3833
3834 case GL_SRC_ALPHA_SATURATE:
3835 return (contextMajorVersion >= 3);
3836
3837 default:
3838 return false;
3839 }
3840}
3841
3842bool ValidateBlendFuncSeparate(ValidationContext *context,
3843 GLenum srcRGB,
3844 GLenum dstRGB,
3845 GLenum srcAlpha,
3846 GLenum dstAlpha)
3847{
3848 if (!ValidSrcBlendFunc(srcRGB))
3849 {
3850 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3851 return false;
3852 }
3853
3854 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3855 {
3856 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3857 return false;
3858 }
3859
3860 if (!ValidSrcBlendFunc(srcAlpha))
3861 {
3862 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3863 return false;
3864 }
3865
3866 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3867 {
3868 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3869 return false;
3870 }
3871
Frank Henigman146e8a12017-03-02 23:22:37 -05003872 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3873 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003874 {
3875 bool constantColorUsed =
3876 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3877 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3878
3879 bool constantAlphaUsed =
3880 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3881 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3882
3883 if (constantColorUsed && constantAlphaUsed)
3884 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003885 const char *msg;
3886 if (context->getExtensions().webglCompatibility)
3887 {
3888 msg =
3889 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3890 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3891 }
3892 else
3893 {
3894 msg =
3895 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3896 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3897 "implementation.";
3898 ERR() << msg;
3899 }
3900 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003901 return false;
3902 }
3903 }
3904
3905 return true;
3906}
3907
Geoff Langc339c4e2016-11-29 10:37:36 -05003908bool ValidateGetString(Context *context, GLenum name)
3909{
3910 switch (name)
3911 {
3912 case GL_VENDOR:
3913 case GL_RENDERER:
3914 case GL_VERSION:
3915 case GL_SHADING_LANGUAGE_VERSION:
3916 case GL_EXTENSIONS:
3917 break;
3918
3919 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3920 if (!context->getExtensions().requestExtension)
3921 {
3922 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3923 return false;
3924 }
3925 break;
3926
3927 default:
3928 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3929 return false;
3930 }
3931
3932 return true;
3933}
3934
Geoff Lang47c48082016-12-07 15:38:13 -05003935bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3936{
3937 if (width <= 0.0f || isNaN(width))
3938 {
3939 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3940 return false;
3941 }
3942
3943 return true;
3944}
3945
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003946bool ValidateVertexAttribPointer(ValidationContext *context,
3947 GLuint index,
3948 GLint size,
3949 GLenum type,
3950 GLboolean normalized,
3951 GLsizei stride,
3952 const GLvoid *ptr)
3953{
Shao80957d92017-02-20 21:25:59 +08003954 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003955 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003956 return false;
3957 }
3958
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003959 if (stride < 0)
3960 {
Shao80957d92017-02-20 21:25:59 +08003961 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003962 return false;
3963 }
3964
Shao80957d92017-02-20 21:25:59 +08003965 const Caps &caps = context->getCaps();
3966 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003967 {
Shao80957d92017-02-20 21:25:59 +08003968 if (stride > caps.maxVertexAttribStride)
3969 {
3970 context->handleError(
3971 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
3972 return false;
3973 }
3974
3975 if (index >= caps.maxVertexAttribBindings)
3976 {
3977 context->handleError(
3978 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
3979 return false;
3980 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003981 }
3982
3983 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3984 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3985 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3986 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003987 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3988 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08003989 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003990 {
3991 context->handleError(
3992 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08003993 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003994 return false;
3995 }
3996
3997 if (context->getExtensions().webglCompatibility)
3998 {
3999 // WebGL 1.0 [Section 6.14] Fixed point support
4000 // The WebGL API does not support the GL_FIXED data type.
4001 if (type == GL_FIXED)
4002 {
4003 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4004 return false;
4005 }
4006
Geoff Lang2d62ab72017-03-23 16:54:40 -04004007 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004008 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004009 return false;
4010 }
4011 }
4012
4013 return true;
4014}
4015
Frank Henigman6137ddc2017-02-10 18:55:07 -05004016bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
4017{
4018 if (context->getExtensions().webglCompatibility && zNear > zFar)
4019 {
4020 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4021 return false;
4022 }
4023
4024 return true;
4025}
4026
Jamie Madille8fb6402017-02-14 17:56:40 -05004027bool ValidateRenderbufferStorage(ValidationContext *context,
4028 GLenum target,
4029 GLenum internalformat,
4030 GLsizei width,
4031 GLsizei height)
4032{
4033 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4034 height);
4035}
4036
4037bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4038 GLenum target,
4039 GLsizei samples,
4040 GLenum internalformat,
4041 GLsizei width,
4042 GLsizei height)
4043{
4044 if (!context->getExtensions().framebufferMultisample)
4045 {
4046 context->handleError(
4047 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4048 return false;
4049 }
4050
4051 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4052 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4053 // generated.
4054 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4055 {
4056 context->handleError(Error(GL_INVALID_VALUE));
4057 return false;
4058 }
4059
4060 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4061 // the specified storage. This is different than ES 3.0 in which a sample number higher
4062 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4063 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4064 if (context->getClientMajorVersion() >= 3)
4065 {
4066 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4067 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4068 {
4069 context->handleError(Error(GL_OUT_OF_MEMORY));
4070 return false;
4071 }
4072 }
4073
4074 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4075 width, height);
4076}
4077
Jamie Madillc29968b2016-01-20 11:17:23 -05004078} // namespace gl