blob: c24fa4804c97fb532699ecc4f0b6aaed87b5b909 [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,
Geoff Langfc72a072017-03-24 14:52:39 -04003174 GLint sourceLevel,
3175 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003176 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003177 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003178 GLint internalFormat,
3179 GLenum destType,
3180 GLboolean unpackFlipY,
3181 GLboolean unpackPremultiplyAlpha,
3182 GLboolean unpackUnmultiplyAlpha)
3183{
3184 if (!context->getExtensions().copyTexture)
3185 {
3186 context->handleError(
3187 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3188 return false;
3189 }
3190
3191 const gl::Texture *source = context->getTexture(sourceId);
3192 if (source == nullptr)
3193 {
3194 context->handleError(
3195 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3196 return false;
3197 }
3198
3199 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3200 {
3201 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3202 return false;
3203 }
3204
3205 GLenum sourceTarget = source->getTarget();
3206 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3207 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3208 {
3209 context->handleError(
3210 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3211 return false;
3212 }
3213
3214 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3215 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3216 {
3217 context->handleError(
3218 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3219 return false;
3220 }
3221
3222 const gl::Texture *dest = context->getTexture(destId);
3223 if (dest == nullptr)
3224 {
3225 context->handleError(
3226 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3227 return false;
3228 }
3229
3230 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3231 {
3232 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3233 return false;
3234 }
3235
3236 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3237 {
3238 context->handleError(
3239 Error(GL_INVALID_OPERATION,
3240 "Destination internal format and type combination is not valid."));
3241 return false;
3242 }
3243
3244 if (dest->getImmutableFormat())
3245 {
3246 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3247 return false;
3248 }
3249
3250 return true;
3251}
3252
3253bool ValidateCopySubTextureCHROMIUM(Context *context,
3254 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003255 GLint sourceLevel,
3256 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003257 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003258 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003259 GLint xoffset,
3260 GLint yoffset,
3261 GLint x,
3262 GLint y,
3263 GLsizei width,
3264 GLsizei height,
3265 GLboolean unpackFlipY,
3266 GLboolean unpackPremultiplyAlpha,
3267 GLboolean unpackUnmultiplyAlpha)
3268{
3269 if (!context->getExtensions().copyTexture)
3270 {
3271 context->handleError(
3272 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3273 return false;
3274 }
3275
3276 const gl::Texture *source = context->getTexture(sourceId);
3277 if (source == nullptr)
3278 {
3279 context->handleError(
3280 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3281 return false;
3282 }
3283
3284 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3285 {
3286 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3287 return false;
3288 }
3289
3290 GLenum sourceTarget = source->getTarget();
3291 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3292 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3293 {
3294 context->handleError(
3295 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3296 return false;
3297 }
3298
3299 if (x < 0 || y < 0)
3300 {
3301 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3302 return false;
3303 }
3304
3305 if (width < 0 || height < 0)
3306 {
3307 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3308 return false;
3309 }
3310
3311 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3312 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3313 {
3314 context->handleError(
3315 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3316 return false;
3317 }
3318
3319 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3320 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3321 {
3322 context->handleError(
3323 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3324 return false;
3325 }
3326
3327 const gl::Texture *dest = context->getTexture(destId);
3328 if (dest == nullptr)
3329 {
3330 context->handleError(
3331 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3332 return false;
3333 }
3334
3335 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3336 {
3337 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3338 return false;
3339 }
3340
Geoff Lang97073d12016-04-20 10:42:34 -07003341 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3342 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3343 {
3344 context->handleError(
3345 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3346 return false;
3347 }
3348
3349 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3350 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3351 {
3352 context->handleError(
3353 Error(GL_INVALID_OPERATION,
3354 "Destination internal format and type combination is not valid."));
3355 return false;
3356 }
3357
3358 if (xoffset < 0 || yoffset < 0)
3359 {
3360 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3361 return false;
3362 }
3363
3364 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3365 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3366 {
3367 context->handleError(
3368 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3369 return false;
3370 }
3371
3372 return true;
3373}
3374
Geoff Lang47110bf2016-04-20 11:13:22 -07003375bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3376{
3377 if (!context->getExtensions().copyCompressedTexture)
3378 {
3379 context->handleError(Error(GL_INVALID_OPERATION,
3380 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3381 return false;
3382 }
3383
3384 const gl::Texture *source = context->getTexture(sourceId);
3385 if (source == nullptr)
3386 {
3387 context->handleError(
3388 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3389 return false;
3390 }
3391
3392 if (source->getTarget() != GL_TEXTURE_2D)
3393 {
3394 context->handleError(
3395 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3396 return false;
3397 }
3398
3399 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3400 {
3401 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3402 return false;
3403 }
3404
3405 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3406 if (!sourceFormat.info->compressed)
3407 {
3408 context->handleError(
3409 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3410 return false;
3411 }
3412
3413 const gl::Texture *dest = context->getTexture(destId);
3414 if (dest == nullptr)
3415 {
3416 context->handleError(
3417 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3418 return false;
3419 }
3420
3421 if (dest->getTarget() != GL_TEXTURE_2D)
3422 {
3423 context->handleError(
3424 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3425 return false;
3426 }
3427
3428 if (dest->getImmutableFormat())
3429 {
3430 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3431 return false;
3432 }
3433
3434 return true;
3435}
3436
Martin Radev4c4c8e72016-08-04 12:25:34 +03003437bool ValidateCreateShader(Context *context, GLenum type)
3438{
3439 switch (type)
3440 {
3441 case GL_VERTEX_SHADER:
3442 case GL_FRAGMENT_SHADER:
3443 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003444
Martin Radev4c4c8e72016-08-04 12:25:34 +03003445 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003446 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003447 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003448 context->handleError(
3449 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3450 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003451 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003452 break;
3453
Martin Radev4c4c8e72016-08-04 12:25:34 +03003454 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003455 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003456 return false;
3457 }
Jamie Madill29639852016-09-02 15:00:09 -04003458
3459 return true;
3460}
3461
3462bool ValidateBufferData(ValidationContext *context,
3463 GLenum target,
3464 GLsizeiptr size,
3465 const GLvoid *data,
3466 GLenum usage)
3467{
3468 if (size < 0)
3469 {
3470 context->handleError(Error(GL_INVALID_VALUE));
3471 return false;
3472 }
3473
3474 switch (usage)
3475 {
3476 case GL_STREAM_DRAW:
3477 case GL_STATIC_DRAW:
3478 case GL_DYNAMIC_DRAW:
3479 break;
3480
3481 case GL_STREAM_READ:
3482 case GL_STREAM_COPY:
3483 case GL_STATIC_READ:
3484 case GL_STATIC_COPY:
3485 case GL_DYNAMIC_READ:
3486 case GL_DYNAMIC_COPY:
3487 if (context->getClientMajorVersion() < 3)
3488 {
3489 context->handleError(Error(GL_INVALID_ENUM));
3490 return false;
3491 }
3492 break;
3493
3494 default:
3495 context->handleError(Error(GL_INVALID_ENUM));
3496 return false;
3497 }
3498
3499 if (!ValidBufferTarget(context, target))
3500 {
3501 context->handleError(Error(GL_INVALID_ENUM));
3502 return false;
3503 }
3504
3505 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3506
3507 if (!buffer)
3508 {
3509 context->handleError(Error(GL_INVALID_OPERATION));
3510 return false;
3511 }
3512
3513 return true;
3514}
3515
3516bool ValidateBufferSubData(ValidationContext *context,
3517 GLenum target,
3518 GLintptr offset,
3519 GLsizeiptr size,
3520 const GLvoid *data)
3521{
3522 if (size < 0 || offset < 0)
3523 {
3524 context->handleError(Error(GL_INVALID_VALUE));
3525 return false;
3526 }
3527
3528 if (!ValidBufferTarget(context, target))
3529 {
3530 context->handleError(Error(GL_INVALID_ENUM));
3531 return false;
3532 }
3533
3534 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3535
3536 if (!buffer)
3537 {
3538 context->handleError(Error(GL_INVALID_OPERATION));
3539 return false;
3540 }
3541
3542 if (buffer->isMapped())
3543 {
3544 context->handleError(Error(GL_INVALID_OPERATION));
3545 return false;
3546 }
3547
3548 // Check for possible overflow of size + offset
3549 angle::CheckedNumeric<size_t> checkedSize(size);
3550 checkedSize += offset;
3551 if (!checkedSize.IsValid())
3552 {
3553 context->handleError(Error(GL_OUT_OF_MEMORY));
3554 return false;
3555 }
3556
3557 if (size + offset > buffer->getSize())
3558 {
3559 context->handleError(Error(GL_INVALID_VALUE));
3560 return false;
3561 }
3562
Martin Radev4c4c8e72016-08-04 12:25:34 +03003563 return true;
3564}
3565
Geoff Langc339c4e2016-11-29 10:37:36 -05003566bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003567{
Geoff Langc339c4e2016-11-29 10:37:36 -05003568 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003569 {
3570 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003571 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003572 return false;
3573 }
3574
3575 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3576 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003577 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003578 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003579 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003580 return false;
3581 }
3582
3583 return true;
3584}
3585
Jamie Madillef300b12016-10-07 15:12:09 -04003586bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3587{
3588 if (texture < GL_TEXTURE0 ||
3589 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3590 {
3591 context->handleError(Error(GL_INVALID_ENUM));
3592 return false;
3593 }
3594
3595 return true;
3596}
3597
3598bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3599{
3600 Program *programObject = GetValidProgram(context, program);
3601 if (!programObject)
3602 {
3603 return false;
3604 }
3605
3606 Shader *shaderObject = GetValidShader(context, shader);
3607 if (!shaderObject)
3608 {
3609 return false;
3610 }
3611
3612 switch (shaderObject->getType())
3613 {
3614 case GL_VERTEX_SHADER:
3615 {
3616 if (programObject->getAttachedVertexShader())
3617 {
3618 context->handleError(Error(GL_INVALID_OPERATION));
3619 return false;
3620 }
3621 break;
3622 }
3623 case GL_FRAGMENT_SHADER:
3624 {
3625 if (programObject->getAttachedFragmentShader())
3626 {
3627 context->handleError(Error(GL_INVALID_OPERATION));
3628 return false;
3629 }
3630 break;
3631 }
3632 case GL_COMPUTE_SHADER:
3633 {
3634 if (programObject->getAttachedComputeShader())
3635 {
3636 context->handleError(Error(GL_INVALID_OPERATION));
3637 return false;
3638 }
3639 break;
3640 }
3641 default:
3642 UNREACHABLE();
3643 break;
3644 }
3645
3646 return true;
3647}
3648
Jamie Madill01a80ee2016-11-07 12:06:18 -05003649bool ValidateBindAttribLocation(ValidationContext *context,
3650 GLuint program,
3651 GLuint index,
3652 const GLchar *name)
3653{
3654 if (index >= MAX_VERTEX_ATTRIBS)
3655 {
3656 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3657 return false;
3658 }
3659
3660 if (strncmp(name, "gl_", 3) == 0)
3661 {
3662 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3663 return false;
3664 }
3665
3666 return GetValidProgram(context, program) != nullptr;
3667}
3668
3669bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3670{
3671 if (!ValidBufferTarget(context, target))
3672 {
3673 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3674 return false;
3675 }
3676
3677 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3678 !context->isBufferGenerated(buffer))
3679 {
3680 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3681 return false;
3682 }
3683
3684 return true;
3685}
3686
3687bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3688{
3689 if (!ValidFramebufferTarget(target))
3690 {
3691 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3692 return false;
3693 }
3694
3695 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3696 !context->isFramebufferGenerated(framebuffer))
3697 {
3698 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3699 return false;
3700 }
3701
3702 return true;
3703}
3704
3705bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3706{
3707 if (target != GL_RENDERBUFFER)
3708 {
3709 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3710 return false;
3711 }
3712
3713 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3714 !context->isRenderbufferGenerated(renderbuffer))
3715 {
3716 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3717 return false;
3718 }
3719
3720 return true;
3721}
3722
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003723static bool ValidBlendEquationMode(GLenum mode)
3724{
3725 switch (mode)
3726 {
3727 case GL_FUNC_ADD:
3728 case GL_FUNC_SUBTRACT:
3729 case GL_FUNC_REVERSE_SUBTRACT:
3730 case GL_MIN:
3731 case GL_MAX:
3732 return true;
3733
3734 default:
3735 return false;
3736 }
3737}
3738
3739bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3740{
3741 if (!ValidBlendEquationMode(mode))
3742 {
3743 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3744 return false;
3745 }
3746
3747 return true;
3748}
3749
3750bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3751{
3752 if (!ValidBlendEquationMode(modeRGB))
3753 {
3754 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3755 return false;
3756 }
3757
3758 if (!ValidBlendEquationMode(modeAlpha))
3759 {
3760 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3761 return false;
3762 }
3763
3764 return true;
3765}
3766
3767bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3768{
3769 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3770}
3771
3772static bool ValidSrcBlendFunc(GLenum srcBlend)
3773{
3774 switch (srcBlend)
3775 {
3776 case GL_ZERO:
3777 case GL_ONE:
3778 case GL_SRC_COLOR:
3779 case GL_ONE_MINUS_SRC_COLOR:
3780 case GL_DST_COLOR:
3781 case GL_ONE_MINUS_DST_COLOR:
3782 case GL_SRC_ALPHA:
3783 case GL_ONE_MINUS_SRC_ALPHA:
3784 case GL_DST_ALPHA:
3785 case GL_ONE_MINUS_DST_ALPHA:
3786 case GL_CONSTANT_COLOR:
3787 case GL_ONE_MINUS_CONSTANT_COLOR:
3788 case GL_CONSTANT_ALPHA:
3789 case GL_ONE_MINUS_CONSTANT_ALPHA:
3790 case GL_SRC_ALPHA_SATURATE:
3791 return true;
3792
3793 default:
3794 return false;
3795 }
3796}
3797
3798static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3799{
3800 switch (dstBlend)
3801 {
3802 case GL_ZERO:
3803 case GL_ONE:
3804 case GL_SRC_COLOR:
3805 case GL_ONE_MINUS_SRC_COLOR:
3806 case GL_DST_COLOR:
3807 case GL_ONE_MINUS_DST_COLOR:
3808 case GL_SRC_ALPHA:
3809 case GL_ONE_MINUS_SRC_ALPHA:
3810 case GL_DST_ALPHA:
3811 case GL_ONE_MINUS_DST_ALPHA:
3812 case GL_CONSTANT_COLOR:
3813 case GL_ONE_MINUS_CONSTANT_COLOR:
3814 case GL_CONSTANT_ALPHA:
3815 case GL_ONE_MINUS_CONSTANT_ALPHA:
3816 return true;
3817
3818 case GL_SRC_ALPHA_SATURATE:
3819 return (contextMajorVersion >= 3);
3820
3821 default:
3822 return false;
3823 }
3824}
3825
3826bool ValidateBlendFuncSeparate(ValidationContext *context,
3827 GLenum srcRGB,
3828 GLenum dstRGB,
3829 GLenum srcAlpha,
3830 GLenum dstAlpha)
3831{
3832 if (!ValidSrcBlendFunc(srcRGB))
3833 {
3834 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3835 return false;
3836 }
3837
3838 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3839 {
3840 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3841 return false;
3842 }
3843
3844 if (!ValidSrcBlendFunc(srcAlpha))
3845 {
3846 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3847 return false;
3848 }
3849
3850 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3851 {
3852 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3853 return false;
3854 }
3855
Frank Henigman146e8a12017-03-02 23:22:37 -05003856 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3857 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003858 {
3859 bool constantColorUsed =
3860 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3861 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3862
3863 bool constantAlphaUsed =
3864 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3865 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3866
3867 if (constantColorUsed && constantAlphaUsed)
3868 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003869 const char *msg;
3870 if (context->getExtensions().webglCompatibility)
3871 {
3872 msg =
3873 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3874 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3875 }
3876 else
3877 {
3878 msg =
3879 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3880 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3881 "implementation.";
3882 ERR() << msg;
3883 }
3884 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003885 return false;
3886 }
3887 }
3888
3889 return true;
3890}
3891
Geoff Langc339c4e2016-11-29 10:37:36 -05003892bool ValidateGetString(Context *context, GLenum name)
3893{
3894 switch (name)
3895 {
3896 case GL_VENDOR:
3897 case GL_RENDERER:
3898 case GL_VERSION:
3899 case GL_SHADING_LANGUAGE_VERSION:
3900 case GL_EXTENSIONS:
3901 break;
3902
3903 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3904 if (!context->getExtensions().requestExtension)
3905 {
3906 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3907 return false;
3908 }
3909 break;
3910
3911 default:
3912 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3913 return false;
3914 }
3915
3916 return true;
3917}
3918
Geoff Lang47c48082016-12-07 15:38:13 -05003919bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3920{
3921 if (width <= 0.0f || isNaN(width))
3922 {
3923 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3924 return false;
3925 }
3926
3927 return true;
3928}
3929
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003930bool ValidateVertexAttribPointer(ValidationContext *context,
3931 GLuint index,
3932 GLint size,
3933 GLenum type,
3934 GLboolean normalized,
3935 GLsizei stride,
3936 const GLvoid *ptr)
3937{
3938 if (index >= MAX_VERTEX_ATTRIBS)
3939 {
3940 context->handleError(Error(GL_INVALID_VALUE, "Invalid index value."));
3941 return false;
3942 }
3943
3944 if (size < 1 || size > 4)
3945 {
3946 context->handleError(Error(GL_INVALID_VALUE, "Invalide size value."));
3947 return false;
3948 }
3949
3950 switch (type)
3951 {
3952 case GL_BYTE:
3953 case GL_UNSIGNED_BYTE:
3954 case GL_SHORT:
3955 case GL_UNSIGNED_SHORT:
3956 case GL_FIXED:
3957 case GL_FLOAT:
3958 break;
3959
3960 case GL_HALF_FLOAT:
3961 case GL_INT:
3962 case GL_UNSIGNED_INT:
3963 case GL_INT_2_10_10_10_REV:
3964 case GL_UNSIGNED_INT_2_10_10_10_REV:
3965 if (context->getClientMajorVersion() < 3)
3966 {
3967 context->handleError(
3968 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
3969 return false;
3970 }
3971 break;
3972
3973 default:
3974 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
3975 return false;
3976 }
3977
3978 if (stride < 0)
3979 {
3980 context->handleError(Error(GL_INVALID_VALUE, "Invalid stride."));
3981 return false;
3982 }
3983
3984 if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
3985 {
3986 context->handleError(Error(GL_INVALID_OPERATION, "Invalid size for a sized vertex type."));
3987 return false;
3988 }
3989
3990 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3991 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3992 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3993 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003994 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3995 context->getGLState().getVertexArray()->id() == 0;
3996 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003997 {
3998 context->handleError(
3999 Error(GL_INVALID_OPERATION,
4000 "Pointer is null with a non-zero VAO bound and zero bound to GL_ARRAY_BUFFER."));
4001 return false;
4002 }
4003
4004 if (context->getExtensions().webglCompatibility)
4005 {
4006 // WebGL 1.0 [Section 6.14] Fixed point support
4007 // The WebGL API does not support the GL_FIXED data type.
4008 if (type == GL_FIXED)
4009 {
4010 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4011 return false;
4012 }
4013
4014 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
4015 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
4016 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
4017 // parameter exceeds 255.
4018 constexpr GLsizei kMaxWebGLStride = 255;
4019 if (stride > kMaxWebGLStride)
4020 {
4021 context->handleError(
4022 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
4023 return false;
4024 }
4025
4026 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
4027 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
4028 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
4029 // or an INVALID_OPERATION error is generated.
4030 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, false);
4031 size_t typeSize = GetVertexFormatTypeSize(internalType);
4032
4033 ASSERT(isPow2(typeSize) && typeSize > 0);
4034 size_t sizeMask = (typeSize - 1);
4035 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
4036 {
4037 context->handleError(
4038 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
4039 return false;
4040 }
4041
4042 if ((stride & sizeMask) != 0)
4043 {
4044 context->handleError(
4045 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
4046 return false;
4047 }
4048 }
4049
4050 return true;
4051}
4052
Frank Henigman6137ddc2017-02-10 18:55:07 -05004053bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
4054{
4055 if (context->getExtensions().webglCompatibility && zNear > zFar)
4056 {
4057 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4058 return false;
4059 }
4060
4061 return true;
4062}
4063
Jamie Madille8fb6402017-02-14 17:56:40 -05004064bool ValidateRenderbufferStorage(ValidationContext *context,
4065 GLenum target,
4066 GLenum internalformat,
4067 GLsizei width,
4068 GLsizei height)
4069{
4070 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4071 height);
4072}
4073
4074bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4075 GLenum target,
4076 GLsizei samples,
4077 GLenum internalformat,
4078 GLsizei width,
4079 GLsizei height)
4080{
4081 if (!context->getExtensions().framebufferMultisample)
4082 {
4083 context->handleError(
4084 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4085 return false;
4086 }
4087
4088 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4089 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4090 // generated.
4091 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4092 {
4093 context->handleError(Error(GL_INVALID_VALUE));
4094 return false;
4095 }
4096
4097 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4098 // the specified storage. This is different than ES 3.0 in which a sample number higher
4099 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4100 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4101 if (context->getClientMajorVersion() >= 3)
4102 {
4103 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4104 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4105 {
4106 context->handleError(Error(GL_OUT_OF_MEMORY));
4107 return false;
4108 }
4109 }
4110
4111 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4112 width, height);
4113}
4114
Jamie Madillc29968b2016-01-20 11:17:23 -05004115} // namespace gl