blob: 900d3419d81f58a2416ae8ce085d9f30a8cb936e [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
1968 return true;
1969}
1970
1971bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1972{
1973 if (!context->getExtensions().drawBuffers)
1974 {
Jamie Madill437fa652016-05-03 15:13:24 -04001975 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001976 return false;
1977 }
1978
1979 return ValidateDrawBuffersBase(context, n, bufs);
1980}
1981
Jamie Madill73a84962016-02-12 09:27:23 -05001982bool ValidateTexImage2D(Context *context,
1983 GLenum target,
1984 GLint level,
1985 GLint internalformat,
1986 GLsizei width,
1987 GLsizei height,
1988 GLint border,
1989 GLenum format,
1990 GLenum type,
1991 const GLvoid *pixels)
1992{
Martin Radev1be913c2016-07-11 17:59:16 +03001993 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001994 {
1995 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001996 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001997 }
1998
Martin Radev1be913c2016-07-11 17:59:16 +03001999 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002000 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002001 0, 0, width, height, 1, border, format, type, -1,
2002 pixels);
2003}
2004
2005bool ValidateTexImage2DRobust(Context *context,
2006 GLenum target,
2007 GLint level,
2008 GLint internalformat,
2009 GLsizei width,
2010 GLsizei height,
2011 GLint border,
2012 GLenum format,
2013 GLenum type,
2014 GLsizei bufSize,
2015 const GLvoid *pixels)
2016{
2017 if (!ValidateRobustEntryPoint(context, bufSize))
2018 {
2019 return false;
2020 }
2021
2022 if (context->getClientMajorVersion() < 3)
2023 {
2024 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2025 0, 0, width, height, border, format, type, bufSize,
2026 pixels);
2027 }
2028
2029 ASSERT(context->getClientMajorVersion() >= 3);
2030 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2031 0, 0, width, height, 1, border, format, type, bufSize,
2032 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002033}
2034
2035bool ValidateTexSubImage2D(Context *context,
2036 GLenum target,
2037 GLint level,
2038 GLint xoffset,
2039 GLint yoffset,
2040 GLsizei width,
2041 GLsizei height,
2042 GLenum format,
2043 GLenum type,
2044 const GLvoid *pixels)
2045{
2046
Martin Radev1be913c2016-07-11 17:59:16 +03002047 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002048 {
2049 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002050 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002051 }
2052
Martin Radev1be913c2016-07-11 17:59:16 +03002053 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002054 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002055 yoffset, 0, width, height, 1, 0, format, type, -1,
2056 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002057}
2058
Geoff Langc52f6f12016-10-14 10:18:00 -04002059bool ValidateTexSubImage2DRobustANGLE(Context *context,
2060 GLenum target,
2061 GLint level,
2062 GLint xoffset,
2063 GLint yoffset,
2064 GLsizei width,
2065 GLsizei height,
2066 GLenum format,
2067 GLenum type,
2068 GLsizei bufSize,
2069 const GLvoid *pixels)
2070{
2071 if (!ValidateRobustEntryPoint(context, bufSize))
2072 {
2073 return false;
2074 }
2075
2076 if (context->getClientMajorVersion() < 3)
2077 {
2078 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2079 yoffset, width, height, 0, format, type, bufSize,
2080 pixels);
2081 }
2082
2083 ASSERT(context->getClientMajorVersion() >= 3);
2084 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2085 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2086 pixels);
2087}
2088
Jamie Madill73a84962016-02-12 09:27:23 -05002089bool ValidateCompressedTexImage2D(Context *context,
2090 GLenum target,
2091 GLint level,
2092 GLenum internalformat,
2093 GLsizei width,
2094 GLsizei height,
2095 GLint border,
2096 GLsizei imageSize,
2097 const GLvoid *data)
2098{
Martin Radev1be913c2016-07-11 17:59:16 +03002099 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002100 {
2101 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002102 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002103 {
2104 return false;
2105 }
2106 }
2107 else
2108 {
Martin Radev1be913c2016-07-11 17:59:16 +03002109 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002110 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002111 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002112 data))
2113 {
2114 return false;
2115 }
2116 }
2117
2118 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002119 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002120 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002121 if (blockSizeOrErr.isError())
2122 {
2123 context->handleError(blockSizeOrErr.getError());
2124 return false;
2125 }
2126
2127 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002128 {
Jamie Madill437fa652016-05-03 15:13:24 -04002129 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002130 return false;
2131 }
2132
2133 return true;
2134}
2135
2136bool ValidateCompressedTexSubImage2D(Context *context,
2137 GLenum target,
2138 GLint level,
2139 GLint xoffset,
2140 GLint yoffset,
2141 GLsizei width,
2142 GLsizei height,
2143 GLenum format,
2144 GLsizei imageSize,
2145 const GLvoid *data)
2146{
Martin Radev1be913c2016-07-11 17:59:16 +03002147 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002148 {
2149 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002150 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002151 {
2152 return false;
2153 }
2154 }
2155 else
2156 {
Martin Radev1be913c2016-07-11 17:59:16 +03002157 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002158 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002159 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002160 data))
2161 {
2162 return false;
2163 }
2164 }
2165
2166 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002167 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002168 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002169 if (blockSizeOrErr.isError())
2170 {
2171 context->handleError(blockSizeOrErr.getError());
2172 return false;
2173 }
2174
2175 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002176 {
Jamie Madill437fa652016-05-03 15:13:24 -04002177 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002178 return false;
2179 }
2180
2181 return true;
2182}
2183
Olli Etuaho4f667482016-03-30 15:56:35 +03002184bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2185{
Geoff Lang496c02d2016-10-20 11:38:11 -07002186 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002187}
2188
2189bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2190{
2191 if (!context->getExtensions().mapBuffer)
2192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002194 return false;
2195 }
2196
2197 if (!ValidBufferTarget(context, target))
2198 {
Jamie Madill437fa652016-05-03 15:13:24 -04002199 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002200 return false;
2201 }
2202
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002203 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002204
2205 if (buffer == nullptr)
2206 {
Jamie Madill437fa652016-05-03 15:13:24 -04002207 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002208 return false;
2209 }
2210
2211 if (access != GL_WRITE_ONLY_OES)
2212 {
Jamie Madill437fa652016-05-03 15:13:24 -04002213 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002214 return false;
2215 }
2216
2217 if (buffer->isMapped())
2218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002220 return false;
2221 }
2222
2223 return true;
2224}
2225
2226bool ValidateUnmapBufferOES(Context *context, GLenum target)
2227{
2228 if (!context->getExtensions().mapBuffer)
2229 {
Jamie Madill437fa652016-05-03 15:13:24 -04002230 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002231 return false;
2232 }
2233
2234 return ValidateUnmapBufferBase(context, target);
2235}
2236
2237bool ValidateMapBufferRangeEXT(Context *context,
2238 GLenum target,
2239 GLintptr offset,
2240 GLsizeiptr length,
2241 GLbitfield access)
2242{
2243 if (!context->getExtensions().mapBufferRange)
2244 {
Jamie Madill437fa652016-05-03 15:13:24 -04002245 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002246 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2247 return false;
2248 }
2249
2250 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2251}
2252
2253bool ValidateFlushMappedBufferRangeEXT(Context *context,
2254 GLenum target,
2255 GLintptr offset,
2256 GLsizeiptr length)
2257{
2258 if (!context->getExtensions().mapBufferRange)
2259 {
Jamie Madill437fa652016-05-03 15:13:24 -04002260 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002261 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2262 return false;
2263 }
2264
2265 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2266}
2267
Ian Ewell54f87462016-03-10 13:47:21 -05002268bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2269{
2270 Texture *textureObject = context->getTexture(texture);
2271 if (textureObject && textureObject->getTarget() != target && texture != 0)
2272 {
Jamie Madill437fa652016-05-03 15:13:24 -04002273 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002274 return false;
2275 }
2276
Geoff Langf41a7152016-09-19 15:11:17 -04002277 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2278 !context->isTextureGenerated(texture))
2279 {
2280 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2281 return false;
2282 }
2283
Ian Ewell54f87462016-03-10 13:47:21 -05002284 switch (target)
2285 {
2286 case GL_TEXTURE_2D:
2287 case GL_TEXTURE_CUBE_MAP:
2288 break;
2289
2290 case GL_TEXTURE_3D:
2291 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002292 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002293 {
Jamie Madill437fa652016-05-03 15:13:24 -04002294 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002295 return false;
2296 }
2297 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002298
2299 case GL_TEXTURE_2D_MULTISAMPLE:
2300 if (context->getClientVersion() < Version(3, 1))
2301 {
2302 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2303 return false;
2304 }
Geoff Lang3b573612016-10-31 14:08:10 -04002305 break;
2306
Ian Ewell54f87462016-03-10 13:47:21 -05002307 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002308 if (!context->getExtensions().eglImageExternal &&
2309 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002310 {
Jamie Madill437fa652016-05-03 15:13:24 -04002311 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002312 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2313 return false;
2314 }
2315 break;
2316 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002317 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002318 return false;
2319 }
2320
2321 return true;
2322}
2323
Geoff Langd8605522016-04-13 10:19:12 -04002324bool ValidateBindUniformLocationCHROMIUM(Context *context,
2325 GLuint program,
2326 GLint location,
2327 const GLchar *name)
2328{
2329 if (!context->getExtensions().bindUniformLocation)
2330 {
Jamie Madill437fa652016-05-03 15:13:24 -04002331 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002332 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2333 return false;
2334 }
2335
2336 Program *programObject = GetValidProgram(context, program);
2337 if (!programObject)
2338 {
2339 return false;
2340 }
2341
2342 if (location < 0)
2343 {
Jamie Madill437fa652016-05-03 15:13:24 -04002344 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002345 return false;
2346 }
2347
2348 const Caps &caps = context->getCaps();
2349 if (static_cast<size_t>(location) >=
2350 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2351 {
Jamie Madill437fa652016-05-03 15:13:24 -04002352 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002353 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2354 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2355 return false;
2356 }
2357
2358 if (strncmp(name, "gl_", 3) == 0)
2359 {
Jamie Madill437fa652016-05-03 15:13:24 -04002360 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002361 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2362 return false;
2363 }
2364
2365 return true;
2366}
2367
Jamie Madille2e406c2016-06-02 13:04:10 -04002368bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002369{
2370 if (!context->getExtensions().framebufferMixedSamples)
2371 {
2372 context->handleError(
2373 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2374 return false;
2375 }
2376 switch (components)
2377 {
2378 case GL_RGB:
2379 case GL_RGBA:
2380 case GL_ALPHA:
2381 case GL_NONE:
2382 break;
2383 default:
2384 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002385 Error(GL_INVALID_ENUM,
2386 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002387 return false;
2388 }
2389
2390 return true;
2391}
2392
Sami Väisänene45e53b2016-05-25 10:36:04 +03002393// CHROMIUM_path_rendering
2394
2395bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2396{
2397 if (!context->getExtensions().pathRendering)
2398 {
2399 context->handleError(
2400 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2401 return false;
2402 }
2403 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2404 {
2405 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2406 return false;
2407 }
2408 if (matrix == nullptr)
2409 {
2410 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2411 return false;
2412 }
2413 return true;
2414}
2415
2416bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2417{
2418 if (!context->getExtensions().pathRendering)
2419 {
2420 context->handleError(
2421 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2422 return false;
2423 }
2424 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2425 {
2426 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2427 return false;
2428 }
2429 return true;
2430}
2431
2432bool ValidateGenPaths(Context *context, GLsizei range)
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
2441 // range = 0 is undefined in NV_path_rendering.
2442 // we add stricter semantic check here and require a non zero positive range.
2443 if (range <= 0)
2444 {
2445 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2446 return false;
2447 }
2448
2449 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2450 {
2451 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2452 return false;
2453 }
2454
2455 return true;
2456}
2457
2458bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2459{
2460 if (!context->getExtensions().pathRendering)
2461 {
2462 context->handleError(
2463 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2464 return false;
2465 }
2466
2467 // range = 0 is undefined in NV_path_rendering.
2468 // we add stricter semantic check here and require a non zero positive range.
2469 if (range <= 0)
2470 {
2471 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2472 return false;
2473 }
2474
2475 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2476 checkedRange += range;
2477
2478 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2479 {
2480 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2481 return false;
2482 }
2483 return true;
2484}
2485
2486bool ValidatePathCommands(Context *context,
2487 GLuint path,
2488 GLsizei numCommands,
2489 const GLubyte *commands,
2490 GLsizei numCoords,
2491 GLenum coordType,
2492 const void *coords)
2493{
2494 if (!context->getExtensions().pathRendering)
2495 {
2496 context->handleError(
2497 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2498 return false;
2499 }
2500 if (!context->hasPath(path))
2501 {
2502 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2503 return false;
2504 }
2505
2506 if (numCommands < 0)
2507 {
2508 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2509 return false;
2510 }
2511 else if (numCommands > 0)
2512 {
2513 if (!commands)
2514 {
2515 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2516 return false;
2517 }
2518 }
2519
2520 if (numCoords < 0)
2521 {
2522 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2523 return false;
2524 }
2525 else if (numCoords > 0)
2526 {
2527 if (!coords)
2528 {
2529 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2530 return false;
2531 }
2532 }
2533
2534 std::uint32_t coordTypeSize = 0;
2535 switch (coordType)
2536 {
2537 case GL_BYTE:
2538 coordTypeSize = sizeof(GLbyte);
2539 break;
2540
2541 case GL_UNSIGNED_BYTE:
2542 coordTypeSize = sizeof(GLubyte);
2543 break;
2544
2545 case GL_SHORT:
2546 coordTypeSize = sizeof(GLshort);
2547 break;
2548
2549 case GL_UNSIGNED_SHORT:
2550 coordTypeSize = sizeof(GLushort);
2551 break;
2552
2553 case GL_FLOAT:
2554 coordTypeSize = sizeof(GLfloat);
2555 break;
2556
2557 default:
2558 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2559 return false;
2560 }
2561
2562 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2563 checkedSize += (coordTypeSize * numCoords);
2564 if (!checkedSize.IsValid())
2565 {
2566 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2567 return false;
2568 }
2569
2570 // early return skips command data validation when it doesn't exist.
2571 if (!commands)
2572 return true;
2573
2574 GLsizei expectedNumCoords = 0;
2575 for (GLsizei i = 0; i < numCommands; ++i)
2576 {
2577 switch (commands[i])
2578 {
2579 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2580 break;
2581 case GL_MOVE_TO_CHROMIUM:
2582 case GL_LINE_TO_CHROMIUM:
2583 expectedNumCoords += 2;
2584 break;
2585 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2586 expectedNumCoords += 4;
2587 break;
2588 case GL_CUBIC_CURVE_TO_CHROMIUM:
2589 expectedNumCoords += 6;
2590 break;
2591 case GL_CONIC_CURVE_TO_CHROMIUM:
2592 expectedNumCoords += 5;
2593 break;
2594 default:
2595 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2596 return false;
2597 }
2598 }
2599 if (expectedNumCoords != numCoords)
2600 {
2601 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2602 return false;
2603 }
2604
2605 return true;
2606}
2607
2608bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2609{
2610 if (!context->getExtensions().pathRendering)
2611 {
2612 context->handleError(
2613 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2614 return false;
2615 }
2616 if (!context->hasPath(path))
2617 {
2618 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2619 return false;
2620 }
2621
2622 switch (pname)
2623 {
2624 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2625 if (value < 0.0f)
2626 {
2627 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2628 return false;
2629 }
2630 break;
2631 case GL_PATH_END_CAPS_CHROMIUM:
2632 switch (static_cast<GLenum>(value))
2633 {
2634 case GL_FLAT_CHROMIUM:
2635 case GL_SQUARE_CHROMIUM:
2636 case GL_ROUND_CHROMIUM:
2637 break;
2638 default:
2639 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2640 return false;
2641 }
2642 break;
2643 case GL_PATH_JOIN_STYLE_CHROMIUM:
2644 switch (static_cast<GLenum>(value))
2645 {
2646 case GL_MITER_REVERT_CHROMIUM:
2647 case GL_BEVEL_CHROMIUM:
2648 case GL_ROUND_CHROMIUM:
2649 break;
2650 default:
2651 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2652 return false;
2653 }
2654 case GL_PATH_MITER_LIMIT_CHROMIUM:
2655 if (value < 0.0f)
2656 {
2657 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2658 return false;
2659 }
2660 break;
2661
2662 case GL_PATH_STROKE_BOUND_CHROMIUM:
2663 // no errors, only clamping.
2664 break;
2665
2666 default:
2667 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2668 return false;
2669 }
2670 return true;
2671}
2672
2673bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2674{
2675 if (!context->getExtensions().pathRendering)
2676 {
2677 context->handleError(
2678 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2679 return false;
2680 }
2681
2682 if (!context->hasPath(path))
2683 {
2684 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2685 return false;
2686 }
2687 if (!value)
2688 {
2689 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2690 return false;
2691 }
2692
2693 switch (pname)
2694 {
2695 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2696 case GL_PATH_END_CAPS_CHROMIUM:
2697 case GL_PATH_JOIN_STYLE_CHROMIUM:
2698 case GL_PATH_MITER_LIMIT_CHROMIUM:
2699 case GL_PATH_STROKE_BOUND_CHROMIUM:
2700 break;
2701
2702 default:
2703 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2704 return false;
2705 }
2706
2707 return true;
2708}
2709
2710bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2711{
2712 if (!context->getExtensions().pathRendering)
2713 {
2714 context->handleError(
2715 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2716 return false;
2717 }
2718
2719 switch (func)
2720 {
2721 case GL_NEVER:
2722 case GL_ALWAYS:
2723 case GL_LESS:
2724 case GL_LEQUAL:
2725 case GL_EQUAL:
2726 case GL_GEQUAL:
2727 case GL_GREATER:
2728 case GL_NOTEQUAL:
2729 break;
2730 default:
2731 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2732 return false;
2733 }
2734
2735 return true;
2736}
2737
2738// Note that the spec specifies that for the path drawing commands
2739// if the path object is not an existing path object the command
2740// does nothing and no error is generated.
2741// However if the path object exists but has not been specified any
2742// commands then an error is generated.
2743
2744bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2745{
2746 if (!context->getExtensions().pathRendering)
2747 {
2748 context->handleError(
2749 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2750 return false;
2751 }
2752 if (context->hasPath(path) && !context->hasPathData(path))
2753 {
2754 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2755 return false;
2756 }
2757
2758 switch (fillMode)
2759 {
2760 case GL_COUNT_UP_CHROMIUM:
2761 case GL_COUNT_DOWN_CHROMIUM:
2762 break;
2763 default:
2764 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2765 return false;
2766 }
2767
2768 if (!isPow2(mask + 1))
2769 {
2770 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2771 return false;
2772 }
2773
2774 return true;
2775}
2776
2777bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2778{
2779 if (!context->getExtensions().pathRendering)
2780 {
2781 context->handleError(
2782 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2783 return false;
2784 }
2785 if (context->hasPath(path) && !context->hasPathData(path))
2786 {
2787 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2788 return false;
2789 }
2790
2791 return true;
2792}
2793
2794bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2795{
2796 if (!context->getExtensions().pathRendering)
2797 {
2798 context->handleError(
2799 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2800 return false;
2801 }
2802 if (context->hasPath(path) && !context->hasPathData(path))
2803 {
2804 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2805 return false;
2806 }
2807
2808 switch (coverMode)
2809 {
2810 case GL_CONVEX_HULL_CHROMIUM:
2811 case GL_BOUNDING_BOX_CHROMIUM:
2812 break;
2813 default:
2814 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2815 return false;
2816 }
2817 return true;
2818}
2819
2820bool ValidateStencilThenCoverFillPath(Context *context,
2821 GLuint path,
2822 GLenum fillMode,
2823 GLuint mask,
2824 GLenum coverMode)
2825{
2826 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2827 ValidateCoverPath(context, path, coverMode);
2828}
2829
2830bool ValidateStencilThenCoverStrokePath(Context *context,
2831 GLuint path,
2832 GLint reference,
2833 GLuint mask,
2834 GLenum coverMode)
2835{
2836 return ValidateStencilStrokePath(context, path, reference, mask) &&
2837 ValidateCoverPath(context, path, coverMode);
2838}
2839
2840bool ValidateIsPath(Context *context)
2841{
2842 if (!context->getExtensions().pathRendering)
2843 {
2844 context->handleError(
2845 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2846 return false;
2847 }
2848 return true;
2849}
2850
Sami Väisänend59ca052016-06-21 16:10:00 +03002851bool ValidateCoverFillPathInstanced(Context *context,
2852 GLsizei numPaths,
2853 GLenum pathNameType,
2854 const void *paths,
2855 GLuint pathBase,
2856 GLenum coverMode,
2857 GLenum transformType,
2858 const GLfloat *transformValues)
2859{
2860 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2861 transformType, transformValues))
2862 return false;
2863
2864 switch (coverMode)
2865 {
2866 case GL_CONVEX_HULL_CHROMIUM:
2867 case GL_BOUNDING_BOX_CHROMIUM:
2868 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2869 break;
2870 default:
2871 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2872 return false;
2873 }
2874
2875 return true;
2876}
2877
2878bool ValidateCoverStrokePathInstanced(Context *context,
2879 GLsizei numPaths,
2880 GLenum pathNameType,
2881 const void *paths,
2882 GLuint pathBase,
2883 GLenum coverMode,
2884 GLenum transformType,
2885 const GLfloat *transformValues)
2886{
2887 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2888 transformType, transformValues))
2889 return false;
2890
2891 switch (coverMode)
2892 {
2893 case GL_CONVEX_HULL_CHROMIUM:
2894 case GL_BOUNDING_BOX_CHROMIUM:
2895 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2896 break;
2897 default:
2898 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2899 return false;
2900 }
2901
2902 return true;
2903}
2904
2905bool ValidateStencilFillPathInstanced(Context *context,
2906 GLsizei numPaths,
2907 GLenum pathNameType,
2908 const void *paths,
2909 GLuint pathBase,
2910 GLenum fillMode,
2911 GLuint mask,
2912 GLenum transformType,
2913 const GLfloat *transformValues)
2914{
2915
2916 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2917 transformType, transformValues))
2918 return false;
2919
2920 switch (fillMode)
2921 {
2922 case GL_COUNT_UP_CHROMIUM:
2923 case GL_COUNT_DOWN_CHROMIUM:
2924 break;
2925 default:
2926 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2927 return false;
2928 }
2929 if (!isPow2(mask + 1))
2930 {
2931 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2932 return false;
2933 }
2934 return true;
2935}
2936
2937bool ValidateStencilStrokePathInstanced(Context *context,
2938 GLsizei numPaths,
2939 GLenum pathNameType,
2940 const void *paths,
2941 GLuint pathBase,
2942 GLint reference,
2943 GLuint mask,
2944 GLenum transformType,
2945 const GLfloat *transformValues)
2946{
2947 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2948 transformType, transformValues))
2949 return false;
2950
2951 // no more validation here.
2952
2953 return true;
2954}
2955
2956bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2957 GLsizei numPaths,
2958 GLenum pathNameType,
2959 const void *paths,
2960 GLuint pathBase,
2961 GLenum fillMode,
2962 GLuint mask,
2963 GLenum coverMode,
2964 GLenum transformType,
2965 const GLfloat *transformValues)
2966{
2967 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2968 transformType, transformValues))
2969 return false;
2970
2971 switch (coverMode)
2972 {
2973 case GL_CONVEX_HULL_CHROMIUM:
2974 case GL_BOUNDING_BOX_CHROMIUM:
2975 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2976 break;
2977 default:
2978 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2979 return false;
2980 }
2981
2982 switch (fillMode)
2983 {
2984 case GL_COUNT_UP_CHROMIUM:
2985 case GL_COUNT_DOWN_CHROMIUM:
2986 break;
2987 default:
2988 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2989 return false;
2990 }
2991 if (!isPow2(mask + 1))
2992 {
2993 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2994 return false;
2995 }
2996
2997 return true;
2998}
2999
3000bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3001 GLsizei numPaths,
3002 GLenum pathNameType,
3003 const void *paths,
3004 GLuint pathBase,
3005 GLint reference,
3006 GLuint mask,
3007 GLenum coverMode,
3008 GLenum transformType,
3009 const GLfloat *transformValues)
3010{
3011 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3012 transformType, transformValues))
3013 return false;
3014
3015 switch (coverMode)
3016 {
3017 case GL_CONVEX_HULL_CHROMIUM:
3018 case GL_BOUNDING_BOX_CHROMIUM:
3019 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3020 break;
3021 default:
3022 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3023 return false;
3024 }
3025
3026 return true;
3027}
3028
Sami Väisänen46eaa942016-06-29 10:26:37 +03003029bool ValidateBindFragmentInputLocation(Context *context,
3030 GLuint program,
3031 GLint location,
3032 const GLchar *name)
3033{
3034 if (!context->getExtensions().pathRendering)
3035 {
3036 context->handleError(
3037 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3038 return false;
3039 }
3040
3041 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3042 if (location >= MaxLocation)
3043 {
3044 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3045 return false;
3046 }
3047
3048 const auto *programObject = context->getProgram(program);
3049 if (!programObject)
3050 {
3051 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3052 return false;
3053 }
3054
3055 if (!name)
3056 {
3057 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3058 return false;
3059 }
3060
3061 if (angle::BeginsWith(name, "gl_"))
3062 {
3063 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3064 return false;
3065 }
3066
3067 return true;
3068}
3069
3070bool ValidateProgramPathFragmentInputGen(Context *context,
3071 GLuint program,
3072 GLint location,
3073 GLenum genMode,
3074 GLint components,
3075 const GLfloat *coeffs)
3076{
3077 if (!context->getExtensions().pathRendering)
3078 {
3079 context->handleError(
3080 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3081 return false;
3082 }
3083
3084 const auto *programObject = context->getProgram(program);
3085 if (!programObject || programObject->isFlaggedForDeletion())
3086 {
3087 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3088 return false;
3089 }
3090
3091 if (!programObject->isLinked())
3092 {
3093 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3094 return false;
3095 }
3096
3097 switch (genMode)
3098 {
3099 case GL_NONE:
3100 if (components != 0)
3101 {
3102 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3103 return false;
3104 }
3105 break;
3106
3107 case GL_OBJECT_LINEAR_CHROMIUM:
3108 case GL_EYE_LINEAR_CHROMIUM:
3109 case GL_CONSTANT_CHROMIUM:
3110 if (components < 1 || components > 4)
3111 {
3112 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3113 return false;
3114 }
3115 if (!coeffs)
3116 {
3117 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3118 return false;
3119 }
3120 break;
3121
3122 default:
3123 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3124 return false;
3125 }
3126
3127 // If the location is -1 then the command is silently ignored
3128 // and no further validation is needed.
3129 if (location == -1)
3130 return true;
3131
3132 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3133
3134 if (!binding.valid)
3135 {
3136 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3137 return false;
3138 }
3139
3140 if (binding.type != GL_NONE)
3141 {
3142 GLint expectedComponents = 0;
3143 switch (binding.type)
3144 {
3145 case GL_FLOAT:
3146 expectedComponents = 1;
3147 break;
3148 case GL_FLOAT_VEC2:
3149 expectedComponents = 2;
3150 break;
3151 case GL_FLOAT_VEC3:
3152 expectedComponents = 3;
3153 break;
3154 case GL_FLOAT_VEC4:
3155 expectedComponents = 4;
3156 break;
3157 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003158 context->handleError(
3159 Error(GL_INVALID_OPERATION,
3160 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003161 return false;
3162 }
3163 if (expectedComponents != components && genMode != GL_NONE)
3164 {
3165 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3166 return false;
3167 }
3168 }
3169 return true;
3170}
3171
Geoff Lang97073d12016-04-20 10:42:34 -07003172bool ValidateCopyTextureCHROMIUM(Context *context,
3173 GLuint sourceId,
3174 GLuint destId,
3175 GLint internalFormat,
3176 GLenum destType,
3177 GLboolean unpackFlipY,
3178 GLboolean unpackPremultiplyAlpha,
3179 GLboolean unpackUnmultiplyAlpha)
3180{
3181 if (!context->getExtensions().copyTexture)
3182 {
3183 context->handleError(
3184 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3185 return false;
3186 }
3187
3188 const gl::Texture *source = context->getTexture(sourceId);
3189 if (source == nullptr)
3190 {
3191 context->handleError(
3192 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3193 return false;
3194 }
3195
3196 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3197 {
3198 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3199 return false;
3200 }
3201
3202 GLenum sourceTarget = source->getTarget();
3203 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3204 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3205 {
3206 context->handleError(
3207 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3208 return false;
3209 }
3210
3211 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3212 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3213 {
3214 context->handleError(
3215 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3216 return false;
3217 }
3218
3219 const gl::Texture *dest = context->getTexture(destId);
3220 if (dest == nullptr)
3221 {
3222 context->handleError(
3223 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3224 return false;
3225 }
3226
3227 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3228 {
3229 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3230 return false;
3231 }
3232
3233 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3234 {
3235 context->handleError(
3236 Error(GL_INVALID_OPERATION,
3237 "Destination internal format and type combination is not valid."));
3238 return false;
3239 }
3240
3241 if (dest->getImmutableFormat())
3242 {
3243 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3244 return false;
3245 }
3246
3247 return true;
3248}
3249
3250bool ValidateCopySubTextureCHROMIUM(Context *context,
3251 GLuint sourceId,
3252 GLuint destId,
3253 GLint xoffset,
3254 GLint yoffset,
3255 GLint x,
3256 GLint y,
3257 GLsizei width,
3258 GLsizei height,
3259 GLboolean unpackFlipY,
3260 GLboolean unpackPremultiplyAlpha,
3261 GLboolean unpackUnmultiplyAlpha)
3262{
3263 if (!context->getExtensions().copyTexture)
3264 {
3265 context->handleError(
3266 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3267 return false;
3268 }
3269
3270 const gl::Texture *source = context->getTexture(sourceId);
3271 if (source == nullptr)
3272 {
3273 context->handleError(
3274 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3275 return false;
3276 }
3277
3278 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3279 {
3280 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3281 return false;
3282 }
3283
3284 GLenum sourceTarget = source->getTarget();
3285 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3286 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3287 {
3288 context->handleError(
3289 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3290 return false;
3291 }
3292
3293 if (x < 0 || y < 0)
3294 {
3295 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3296 return false;
3297 }
3298
3299 if (width < 0 || height < 0)
3300 {
3301 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3302 return false;
3303 }
3304
3305 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3306 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3307 {
3308 context->handleError(
3309 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3310 return false;
3311 }
3312
3313 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3314 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3315 {
3316 context->handleError(
3317 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3318 return false;
3319 }
3320
3321 const gl::Texture *dest = context->getTexture(destId);
3322 if (dest == nullptr)
3323 {
3324 context->handleError(
3325 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3326 return false;
3327 }
3328
3329 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3330 {
3331 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3332 return false;
3333 }
3334
3335 GLenum destTarget = dest->getTarget();
3336 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3337 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3338 {
3339 context->handleError(
3340 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3341 return false;
3342 }
3343
3344 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3345 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3346 {
3347 context->handleError(
3348 Error(GL_INVALID_OPERATION,
3349 "Destination internal format and type combination is not valid."));
3350 return false;
3351 }
3352
3353 if (xoffset < 0 || yoffset < 0)
3354 {
3355 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3356 return false;
3357 }
3358
3359 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3360 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3361 {
3362 context->handleError(
3363 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3364 return false;
3365 }
3366
3367 return true;
3368}
3369
Geoff Lang47110bf2016-04-20 11:13:22 -07003370bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3371{
3372 if (!context->getExtensions().copyCompressedTexture)
3373 {
3374 context->handleError(Error(GL_INVALID_OPERATION,
3375 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3376 return false;
3377 }
3378
3379 const gl::Texture *source = context->getTexture(sourceId);
3380 if (source == nullptr)
3381 {
3382 context->handleError(
3383 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3384 return false;
3385 }
3386
3387 if (source->getTarget() != GL_TEXTURE_2D)
3388 {
3389 context->handleError(
3390 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3391 return false;
3392 }
3393
3394 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3395 {
3396 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3397 return false;
3398 }
3399
3400 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3401 if (!sourceFormat.info->compressed)
3402 {
3403 context->handleError(
3404 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3405 return false;
3406 }
3407
3408 const gl::Texture *dest = context->getTexture(destId);
3409 if (dest == nullptr)
3410 {
3411 context->handleError(
3412 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3413 return false;
3414 }
3415
3416 if (dest->getTarget() != GL_TEXTURE_2D)
3417 {
3418 context->handleError(
3419 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3420 return false;
3421 }
3422
3423 if (dest->getImmutableFormat())
3424 {
3425 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3426 return false;
3427 }
3428
3429 return true;
3430}
3431
Martin Radev4c4c8e72016-08-04 12:25:34 +03003432bool ValidateCreateShader(Context *context, GLenum type)
3433{
3434 switch (type)
3435 {
3436 case GL_VERTEX_SHADER:
3437 case GL_FRAGMENT_SHADER:
3438 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003439
Martin Radev4c4c8e72016-08-04 12:25:34 +03003440 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003441 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003442 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003443 context->handleError(
3444 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3445 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003446 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003447 break;
3448
Martin Radev4c4c8e72016-08-04 12:25:34 +03003449 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003450 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003451 return false;
3452 }
Jamie Madill29639852016-09-02 15:00:09 -04003453
3454 return true;
3455}
3456
3457bool ValidateBufferData(ValidationContext *context,
3458 GLenum target,
3459 GLsizeiptr size,
3460 const GLvoid *data,
3461 GLenum usage)
3462{
3463 if (size < 0)
3464 {
3465 context->handleError(Error(GL_INVALID_VALUE));
3466 return false;
3467 }
3468
3469 switch (usage)
3470 {
3471 case GL_STREAM_DRAW:
3472 case GL_STATIC_DRAW:
3473 case GL_DYNAMIC_DRAW:
3474 break;
3475
3476 case GL_STREAM_READ:
3477 case GL_STREAM_COPY:
3478 case GL_STATIC_READ:
3479 case GL_STATIC_COPY:
3480 case GL_DYNAMIC_READ:
3481 case GL_DYNAMIC_COPY:
3482 if (context->getClientMajorVersion() < 3)
3483 {
3484 context->handleError(Error(GL_INVALID_ENUM));
3485 return false;
3486 }
3487 break;
3488
3489 default:
3490 context->handleError(Error(GL_INVALID_ENUM));
3491 return false;
3492 }
3493
3494 if (!ValidBufferTarget(context, target))
3495 {
3496 context->handleError(Error(GL_INVALID_ENUM));
3497 return false;
3498 }
3499
3500 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3501
3502 if (!buffer)
3503 {
3504 context->handleError(Error(GL_INVALID_OPERATION));
3505 return false;
3506 }
3507
3508 return true;
3509}
3510
3511bool ValidateBufferSubData(ValidationContext *context,
3512 GLenum target,
3513 GLintptr offset,
3514 GLsizeiptr size,
3515 const GLvoid *data)
3516{
3517 if (size < 0 || offset < 0)
3518 {
3519 context->handleError(Error(GL_INVALID_VALUE));
3520 return false;
3521 }
3522
3523 if (!ValidBufferTarget(context, target))
3524 {
3525 context->handleError(Error(GL_INVALID_ENUM));
3526 return false;
3527 }
3528
3529 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3530
3531 if (!buffer)
3532 {
3533 context->handleError(Error(GL_INVALID_OPERATION));
3534 return false;
3535 }
3536
3537 if (buffer->isMapped())
3538 {
3539 context->handleError(Error(GL_INVALID_OPERATION));
3540 return false;
3541 }
3542
3543 // Check for possible overflow of size + offset
3544 angle::CheckedNumeric<size_t> checkedSize(size);
3545 checkedSize += offset;
3546 if (!checkedSize.IsValid())
3547 {
3548 context->handleError(Error(GL_OUT_OF_MEMORY));
3549 return false;
3550 }
3551
3552 if (size + offset > buffer->getSize())
3553 {
3554 context->handleError(Error(GL_INVALID_VALUE));
3555 return false;
3556 }
3557
Martin Radev4c4c8e72016-08-04 12:25:34 +03003558 return true;
3559}
3560
Geoff Langc339c4e2016-11-29 10:37:36 -05003561bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003562{
Geoff Langc339c4e2016-11-29 10:37:36 -05003563 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003564 {
3565 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003566 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003567 return false;
3568 }
3569
3570 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3571 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003572 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003573 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003574 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003575 return false;
3576 }
3577
3578 return true;
3579}
3580
Jamie Madillef300b12016-10-07 15:12:09 -04003581bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3582{
3583 if (texture < GL_TEXTURE0 ||
3584 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3585 {
3586 context->handleError(Error(GL_INVALID_ENUM));
3587 return false;
3588 }
3589
3590 return true;
3591}
3592
3593bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3594{
3595 Program *programObject = GetValidProgram(context, program);
3596 if (!programObject)
3597 {
3598 return false;
3599 }
3600
3601 Shader *shaderObject = GetValidShader(context, shader);
3602 if (!shaderObject)
3603 {
3604 return false;
3605 }
3606
3607 switch (shaderObject->getType())
3608 {
3609 case GL_VERTEX_SHADER:
3610 {
3611 if (programObject->getAttachedVertexShader())
3612 {
3613 context->handleError(Error(GL_INVALID_OPERATION));
3614 return false;
3615 }
3616 break;
3617 }
3618 case GL_FRAGMENT_SHADER:
3619 {
3620 if (programObject->getAttachedFragmentShader())
3621 {
3622 context->handleError(Error(GL_INVALID_OPERATION));
3623 return false;
3624 }
3625 break;
3626 }
3627 case GL_COMPUTE_SHADER:
3628 {
3629 if (programObject->getAttachedComputeShader())
3630 {
3631 context->handleError(Error(GL_INVALID_OPERATION));
3632 return false;
3633 }
3634 break;
3635 }
3636 default:
3637 UNREACHABLE();
3638 break;
3639 }
3640
3641 return true;
3642}
3643
Jamie Madill01a80ee2016-11-07 12:06:18 -05003644bool ValidateBindAttribLocation(ValidationContext *context,
3645 GLuint program,
3646 GLuint index,
3647 const GLchar *name)
3648{
3649 if (index >= MAX_VERTEX_ATTRIBS)
3650 {
3651 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3652 return false;
3653 }
3654
3655 if (strncmp(name, "gl_", 3) == 0)
3656 {
3657 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3658 return false;
3659 }
3660
3661 return GetValidProgram(context, program) != nullptr;
3662}
3663
3664bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3665{
3666 if (!ValidBufferTarget(context, target))
3667 {
3668 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3669 return false;
3670 }
3671
3672 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3673 !context->isBufferGenerated(buffer))
3674 {
3675 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3676 return false;
3677 }
3678
3679 return true;
3680}
3681
3682bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3683{
3684 if (!ValidFramebufferTarget(target))
3685 {
3686 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3687 return false;
3688 }
3689
3690 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3691 !context->isFramebufferGenerated(framebuffer))
3692 {
3693 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3694 return false;
3695 }
3696
3697 return true;
3698}
3699
3700bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3701{
3702 if (target != GL_RENDERBUFFER)
3703 {
3704 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3705 return false;
3706 }
3707
3708 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3709 !context->isRenderbufferGenerated(renderbuffer))
3710 {
3711 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3712 return false;
3713 }
3714
3715 return true;
3716}
3717
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003718static bool ValidBlendEquationMode(GLenum mode)
3719{
3720 switch (mode)
3721 {
3722 case GL_FUNC_ADD:
3723 case GL_FUNC_SUBTRACT:
3724 case GL_FUNC_REVERSE_SUBTRACT:
3725 case GL_MIN:
3726 case GL_MAX:
3727 return true;
3728
3729 default:
3730 return false;
3731 }
3732}
3733
3734bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3735{
3736 if (!ValidBlendEquationMode(mode))
3737 {
3738 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3739 return false;
3740 }
3741
3742 return true;
3743}
3744
3745bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3746{
3747 if (!ValidBlendEquationMode(modeRGB))
3748 {
3749 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3750 return false;
3751 }
3752
3753 if (!ValidBlendEquationMode(modeAlpha))
3754 {
3755 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3756 return false;
3757 }
3758
3759 return true;
3760}
3761
3762bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3763{
3764 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3765}
3766
3767static bool ValidSrcBlendFunc(GLenum srcBlend)
3768{
3769 switch (srcBlend)
3770 {
3771 case GL_ZERO:
3772 case GL_ONE:
3773 case GL_SRC_COLOR:
3774 case GL_ONE_MINUS_SRC_COLOR:
3775 case GL_DST_COLOR:
3776 case GL_ONE_MINUS_DST_COLOR:
3777 case GL_SRC_ALPHA:
3778 case GL_ONE_MINUS_SRC_ALPHA:
3779 case GL_DST_ALPHA:
3780 case GL_ONE_MINUS_DST_ALPHA:
3781 case GL_CONSTANT_COLOR:
3782 case GL_ONE_MINUS_CONSTANT_COLOR:
3783 case GL_CONSTANT_ALPHA:
3784 case GL_ONE_MINUS_CONSTANT_ALPHA:
3785 case GL_SRC_ALPHA_SATURATE:
3786 return true;
3787
3788 default:
3789 return false;
3790 }
3791}
3792
3793static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3794{
3795 switch (dstBlend)
3796 {
3797 case GL_ZERO:
3798 case GL_ONE:
3799 case GL_SRC_COLOR:
3800 case GL_ONE_MINUS_SRC_COLOR:
3801 case GL_DST_COLOR:
3802 case GL_ONE_MINUS_DST_COLOR:
3803 case GL_SRC_ALPHA:
3804 case GL_ONE_MINUS_SRC_ALPHA:
3805 case GL_DST_ALPHA:
3806 case GL_ONE_MINUS_DST_ALPHA:
3807 case GL_CONSTANT_COLOR:
3808 case GL_ONE_MINUS_CONSTANT_COLOR:
3809 case GL_CONSTANT_ALPHA:
3810 case GL_ONE_MINUS_CONSTANT_ALPHA:
3811 return true;
3812
3813 case GL_SRC_ALPHA_SATURATE:
3814 return (contextMajorVersion >= 3);
3815
3816 default:
3817 return false;
3818 }
3819}
3820
3821bool ValidateBlendFuncSeparate(ValidationContext *context,
3822 GLenum srcRGB,
3823 GLenum dstRGB,
3824 GLenum srcAlpha,
3825 GLenum dstAlpha)
3826{
3827 if (!ValidSrcBlendFunc(srcRGB))
3828 {
3829 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3830 return false;
3831 }
3832
3833 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3834 {
3835 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3836 return false;
3837 }
3838
3839 if (!ValidSrcBlendFunc(srcAlpha))
3840 {
3841 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3842 return false;
3843 }
3844
3845 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3846 {
3847 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3848 return false;
3849 }
3850
Frank Henigman146e8a12017-03-02 23:22:37 -05003851 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3852 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003853 {
3854 bool constantColorUsed =
3855 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3856 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3857
3858 bool constantAlphaUsed =
3859 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3860 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3861
3862 if (constantColorUsed && constantAlphaUsed)
3863 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003864 const char *msg;
3865 if (context->getExtensions().webglCompatibility)
3866 {
3867 msg =
3868 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3869 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3870 }
3871 else
3872 {
3873 msg =
3874 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3875 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3876 "implementation.";
3877 ERR() << msg;
3878 }
3879 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003880 return false;
3881 }
3882 }
3883
3884 return true;
3885}
3886
Geoff Langc339c4e2016-11-29 10:37:36 -05003887bool ValidateGetString(Context *context, GLenum name)
3888{
3889 switch (name)
3890 {
3891 case GL_VENDOR:
3892 case GL_RENDERER:
3893 case GL_VERSION:
3894 case GL_SHADING_LANGUAGE_VERSION:
3895 case GL_EXTENSIONS:
3896 break;
3897
3898 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3899 if (!context->getExtensions().requestExtension)
3900 {
3901 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3902 return false;
3903 }
3904 break;
3905
3906 default:
3907 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3908 return false;
3909 }
3910
3911 return true;
3912}
3913
Geoff Lang47c48082016-12-07 15:38:13 -05003914bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3915{
3916 if (width <= 0.0f || isNaN(width))
3917 {
3918 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3919 return false;
3920 }
3921
3922 return true;
3923}
3924
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003925bool ValidateVertexAttribPointer(ValidationContext *context,
3926 GLuint index,
3927 GLint size,
3928 GLenum type,
3929 GLboolean normalized,
3930 GLsizei stride,
3931 const GLvoid *ptr)
3932{
3933 if (index >= MAX_VERTEX_ATTRIBS)
3934 {
3935 context->handleError(Error(GL_INVALID_VALUE, "Invalid index value."));
3936 return false;
3937 }
3938
3939 if (size < 1 || size > 4)
3940 {
3941 context->handleError(Error(GL_INVALID_VALUE, "Invalide size value."));
3942 return false;
3943 }
3944
3945 switch (type)
3946 {
3947 case GL_BYTE:
3948 case GL_UNSIGNED_BYTE:
3949 case GL_SHORT:
3950 case GL_UNSIGNED_SHORT:
3951 case GL_FIXED:
3952 case GL_FLOAT:
3953 break;
3954
3955 case GL_HALF_FLOAT:
3956 case GL_INT:
3957 case GL_UNSIGNED_INT:
3958 case GL_INT_2_10_10_10_REV:
3959 case GL_UNSIGNED_INT_2_10_10_10_REV:
3960 if (context->getClientMajorVersion() < 3)
3961 {
3962 context->handleError(
3963 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
3964 return false;
3965 }
3966 break;
3967
3968 default:
3969 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
3970 return false;
3971 }
3972
3973 if (stride < 0)
3974 {
3975 context->handleError(Error(GL_INVALID_VALUE, "Invalid stride."));
3976 return false;
3977 }
3978
3979 if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
3980 {
3981 context->handleError(Error(GL_INVALID_OPERATION, "Invalid size for a sized vertex type."));
3982 return false;
3983 }
3984
3985 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3986 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3987 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3988 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003989 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3990 context->getGLState().getVertexArray()->id() == 0;
3991 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003992 {
3993 context->handleError(
3994 Error(GL_INVALID_OPERATION,
3995 "Pointer is null with a non-zero VAO bound and zero bound to GL_ARRAY_BUFFER."));
3996 return false;
3997 }
3998
3999 if (context->getExtensions().webglCompatibility)
4000 {
4001 // WebGL 1.0 [Section 6.14] Fixed point support
4002 // The WebGL API does not support the GL_FIXED data type.
4003 if (type == GL_FIXED)
4004 {
4005 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4006 return false;
4007 }
4008
4009 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
4010 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
4011 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
4012 // parameter exceeds 255.
4013 constexpr GLsizei kMaxWebGLStride = 255;
4014 if (stride > kMaxWebGLStride)
4015 {
4016 context->handleError(
4017 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
4018 return false;
4019 }
4020
4021 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
4022 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
4023 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
4024 // or an INVALID_OPERATION error is generated.
4025 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, false);
4026 size_t typeSize = GetVertexFormatTypeSize(internalType);
4027
4028 ASSERT(isPow2(typeSize) && typeSize > 0);
4029 size_t sizeMask = (typeSize - 1);
4030 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
4031 {
4032 context->handleError(
4033 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
4034 return false;
4035 }
4036
4037 if ((stride & sizeMask) != 0)
4038 {
4039 context->handleError(
4040 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
4041 return false;
4042 }
4043 }
4044
4045 return true;
4046}
4047
Frank Henigman6137ddc2017-02-10 18:55:07 -05004048bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
4049{
4050 if (context->getExtensions().webglCompatibility && zNear > zFar)
4051 {
4052 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4053 return false;
4054 }
4055
4056 return true;
4057}
4058
Jamie Madille8fb6402017-02-14 17:56:40 -05004059bool ValidateRenderbufferStorage(ValidationContext *context,
4060 GLenum target,
4061 GLenum internalformat,
4062 GLsizei width,
4063 GLsizei height)
4064{
4065 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4066 height);
4067}
4068
4069bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4070 GLenum target,
4071 GLsizei samples,
4072 GLenum internalformat,
4073 GLsizei width,
4074 GLsizei height)
4075{
4076 if (!context->getExtensions().framebufferMultisample)
4077 {
4078 context->handleError(
4079 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4080 return false;
4081 }
4082
4083 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4084 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4085 // generated.
4086 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4087 {
4088 context->handleError(Error(GL_INVALID_VALUE));
4089 return false;
4090 }
4091
4092 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4093 // the specified storage. This is different than ES 3.0 in which a sample number higher
4094 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4095 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4096 if (context->getClientMajorVersion() >= 3)
4097 {
4098 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4099 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4100 {
4101 context->handleError(Error(GL_OUT_OF_MEMORY));
4102 return false;
4103 }
4104 }
4105
4106 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4107 width, height);
4108}
4109
Jamie Madillc29968b2016-01-20 11:17:23 -05004110} // namespace gl