blob: ddc1a2e27bcf8d58547fcc755407f3a15811002f [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Texture.h"
18#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
22#include "libANGLE/Uniform.h"
23#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES.h"
25#include "libANGLE/validationES3.h"
Corentin Wallez0c7baf12016-12-19 15:43:10 -050026#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
78 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
79 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
95 context->handleError(
96 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
97 return false;
98 }
99
100 if (paths == nullptr)
101 {
102 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
103 return false;
104 }
105
106 if (numPaths < 0)
107 {
108 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
114 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
160 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
188 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
193 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
202 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang97073d12016-04-20 10:42:34 -0700209bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
210{
211 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
212 switch (internalFormatInfo.format)
213 {
214 case GL_ALPHA:
215 case GL_LUMINANCE:
216 case GL_LUMINANCE_ALPHA:
217 case GL_RGB:
218 case GL_RGBA:
219 return true;
220
221 case GL_RED:
222 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
223
224 case GL_BGRA_EXT:
225 return context->getExtensions().textureFormatBGRA8888;
226
227 default:
228 return false;
229 }
230}
231
232bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
233{
234 switch (internalFormat)
235 {
236 case GL_RGB:
237 case GL_RGBA:
238 break;
239
240 case GL_BGRA_EXT:
241 return context->getExtensions().textureFormatBGRA8888;
242
243 default:
244 return false;
245 }
246
247 switch (type)
248 {
249 case GL_UNSIGNED_BYTE:
250 break;
251
252 default:
253 return false;
254 }
255
256 return true;
257}
258
259bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
260{
261 switch (target)
262 {
263 case GL_TEXTURE_2D:
264 return true;
265
266 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
267 // supported
268
269 default:
270 return false;
271 }
272}
273
274bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
275{
276 if (IsValidCopyTextureDestinationTarget(context, target))
277 {
278 return true;
279 }
280
281 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
282 // supported
283
284 return false;
285}
286
Jamie Madillc29968b2016-01-20 11:17:23 -0500287} // anonymous namespace
288
Geoff Langff5b2d52016-09-07 11:32:23 -0400289bool ValidateES2TexImageParameters(Context *context,
290 GLenum target,
291 GLint level,
292 GLenum internalformat,
293 bool isCompressed,
294 bool isSubImage,
295 GLint xoffset,
296 GLint yoffset,
297 GLsizei width,
298 GLsizei height,
299 GLint border,
300 GLenum format,
301 GLenum type,
302 GLsizei imageSize,
303 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304{
Jamie Madill6f38f822014-06-06 17:12:20 -0400305 if (!ValidTexture2DDestinationTarget(context, target))
306 {
Jamie Madill437fa652016-05-03 15:13:24 -0400307 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400308 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400309 }
310
Austin Kinross08528e12015-10-07 16:24:40 -0700311 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 {
Jamie Madill437fa652016-05-03 15:13:24 -0400313 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400315 }
316
He Yunchaoced53ae2016-11-29 15:00:51 +0800317 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400318 std::numeric_limits<GLsizei>::max() - yoffset < height)
319 {
Jamie Madill437fa652016-05-03 15:13:24 -0400320 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
Geoff Lang005df412013-10-16 14:12:50 -0400324 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Jamie Madill437fa652016-05-03 15:13:24 -0400326 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 }
329
Geoff Langaae65a42014-05-26 12:43:44 -0400330 const gl::Caps &caps = context->getCaps();
331
Geoff Langa9be0dc2014-12-17 12:34:40 -0500332 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
335 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 {
Jamie Madill437fa652016-05-03 15:13:24 -0400337 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500341 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500342 {
343 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 {
Jamie Madill437fa652016-05-03 15:13:24 -0400345 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348
Geoff Langa9be0dc2014-12-17 12:34:40 -0500349 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
350 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
354 }
355 }
356 else
357 {
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400360 }
361
He Yunchaoced53ae2016-11-29 15:00:51 +0800362 gl::Texture *texture =
363 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 if (!texture)
365 {
Jamie Madill437fa652016-05-03 15:13:24 -0400366 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 }
369
Geoff Langa9be0dc2014-12-17 12:34:40 -0500370 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371 {
Geoff Langc51642b2016-11-14 16:18:26 -0500372 GLenum textureFormat = texture->getFormat(target, level).asSized();
373 if (textureFormat == GL_NONE)
374 {
375 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
376 return false;
377 }
378
Geoff Langa9be0dc2014-12-17 12:34:40 -0500379 if (format != GL_NONE)
380 {
Geoff Langc51642b2016-11-14 16:18:26 -0500381 if (gl::GetSizedInternalFormat(format, type) != textureFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500382 {
Jamie Madill437fa652016-05-03 15:13:24 -0400383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500384 return false;
385 }
386 }
387
388 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
389 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
390 {
Jamie Madill437fa652016-05-03 15:13:24 -0400391 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500392 return false;
393 }
394 }
395 else
396 {
Geoff Lang69cce582015-09-17 13:20:36 -0400397 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500398 {
Jamie Madill437fa652016-05-03 15:13:24 -0400399 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500400 return false;
401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 }
403
404 // Verify zero border
405 if (border != 0)
406 {
Jamie Madill437fa652016-05-03 15:13:24 -0400407 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409 }
410
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 if (isCompressed)
412 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400413 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400414 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415 switch (actualInternalFormat)
416 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
419 if (!context->getExtensions().textureCompressionDXT1)
420 {
421 context->handleError(Error(GL_INVALID_ENUM));
422 return false;
423 }
424 break;
425 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
426 if (!context->getExtensions().textureCompressionDXT1)
427 {
428 context->handleError(Error(GL_INVALID_ENUM));
429 return false;
430 }
431 break;
432 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
433 if (!context->getExtensions().textureCompressionDXT5)
434 {
435 context->handleError(Error(GL_INVALID_ENUM));
436 return false;
437 }
438 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800439 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
440 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
441 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
442 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
443 if (!context->getExtensions().textureCompressionS3TCsRGB)
444 {
445 context->handleError(Error(GL_INVALID_ENUM));
446 return false;
447 }
448 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800449 case GL_ETC1_RGB8_OES:
450 if (!context->getExtensions().compressedETC1RGB8Texture)
451 {
452 context->handleError(Error(GL_INVALID_ENUM));
453 return false;
454 }
455 break;
456 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
457 if (!context->getExtensions().lossyETCDecode)
458 {
459 context->handleError(Error(
460 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
461 return false;
462 }
463 break;
464 default:
465 context->handleError(
466 Error(GL_INVALID_ENUM,
467 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400468 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400469 }
Geoff Lang44ff5a72017-02-03 15:15:43 -0500470 if (!ValidCompressedImageSize(context, actualInternalFormat, xoffset, yoffset, width,
471 height))
tmartino0ccd5ae2015-10-01 14:33:14 -0400472 {
Jamie Madill437fa652016-05-03 15:13:24 -0400473 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400474 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400475 }
476 }
477 else
478 {
479 // validate <type> by itself (used as secondary key below)
480 switch (type)
481 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800482 case GL_UNSIGNED_BYTE:
483 case GL_UNSIGNED_SHORT_5_6_5:
484 case GL_UNSIGNED_SHORT_4_4_4_4:
485 case GL_UNSIGNED_SHORT_5_5_5_1:
486 case GL_UNSIGNED_SHORT:
487 case GL_UNSIGNED_INT:
488 case GL_UNSIGNED_INT_24_8_OES:
489 case GL_HALF_FLOAT_OES:
490 case GL_FLOAT:
491 break;
492 default:
493 context->handleError(Error(GL_INVALID_ENUM));
494 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400495 }
496
497 // validate <format> + <type> combinations
498 // - invalid <format> -> sets INVALID_ENUM
499 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
500 switch (format)
501 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800502 case GL_ALPHA:
503 case GL_LUMINANCE:
504 case GL_LUMINANCE_ALPHA:
505 switch (type)
506 {
507 case GL_UNSIGNED_BYTE:
508 case GL_FLOAT:
509 case GL_HALF_FLOAT_OES:
510 break;
511 default:
512 context->handleError(Error(GL_INVALID_OPERATION));
513 return false;
514 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400515 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800516 case GL_RED:
517 case GL_RG:
518 if (!context->getExtensions().textureRG)
519 {
520 context->handleError(Error(GL_INVALID_ENUM));
521 return false;
522 }
523 switch (type)
524 {
525 case GL_UNSIGNED_BYTE:
526 case GL_FLOAT:
527 case GL_HALF_FLOAT_OES:
528 break;
529 default:
530 context->handleError(Error(GL_INVALID_OPERATION));
531 return false;
532 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400533 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800534 case GL_RGB:
535 switch (type)
536 {
537 case GL_UNSIGNED_BYTE:
538 case GL_UNSIGNED_SHORT_5_6_5:
539 case GL_FLOAT:
540 case GL_HALF_FLOAT_OES:
541 break;
542 default:
543 context->handleError(Error(GL_INVALID_OPERATION));
544 return false;
545 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400546 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800547 case GL_RGBA:
548 switch (type)
549 {
550 case GL_UNSIGNED_BYTE:
551 case GL_UNSIGNED_SHORT_4_4_4_4:
552 case GL_UNSIGNED_SHORT_5_5_5_1:
553 case GL_FLOAT:
554 case GL_HALF_FLOAT_OES:
555 break;
556 default:
557 context->handleError(Error(GL_INVALID_OPERATION));
558 return false;
559 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400560 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800561 case GL_BGRA_EXT:
562 switch (type)
563 {
564 case GL_UNSIGNED_BYTE:
565 break;
566 default:
567 context->handleError(Error(GL_INVALID_OPERATION));
568 return false;
569 }
570 break;
571 case GL_SRGB_EXT:
572 case GL_SRGB_ALPHA_EXT:
573 if (!context->getExtensions().sRGB)
574 {
575 context->handleError(Error(GL_INVALID_ENUM));
576 return false;
577 }
578 switch (type)
579 {
580 case GL_UNSIGNED_BYTE:
581 break;
582 default:
583 context->handleError(Error(GL_INVALID_OPERATION));
584 return false;
585 }
586 break;
587 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
588 // handled below
589 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
590 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
591 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
592 break;
593 case GL_DEPTH_COMPONENT:
594 switch (type)
595 {
596 case GL_UNSIGNED_SHORT:
597 case GL_UNSIGNED_INT:
598 break;
599 default:
600 context->handleError(Error(GL_INVALID_OPERATION));
601 return false;
602 }
603 break;
604 case GL_DEPTH_STENCIL_OES:
605 switch (type)
606 {
607 case GL_UNSIGNED_INT_24_8_OES:
608 break;
609 default:
610 context->handleError(Error(GL_INVALID_OPERATION));
611 return false;
612 }
613 break;
614 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400615 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400616 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400617 }
618
619 switch (format)
620 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800621 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
622 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
623 if (context->getExtensions().textureCompressionDXT1)
624 {
625 context->handleError(Error(GL_INVALID_OPERATION));
626 return false;
627 }
628 else
629 {
630 context->handleError(Error(GL_INVALID_ENUM));
631 return false;
632 }
633 break;
634 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
635 if (context->getExtensions().textureCompressionDXT3)
636 {
637 context->handleError(Error(GL_INVALID_OPERATION));
638 return false;
639 }
640 else
641 {
642 context->handleError(Error(GL_INVALID_ENUM));
643 return false;
644 }
645 break;
646 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
647 if (context->getExtensions().textureCompressionDXT5)
648 {
649 context->handleError(Error(GL_INVALID_OPERATION));
650 return false;
651 }
652 else
653 {
654 context->handleError(Error(GL_INVALID_ENUM));
655 return false;
656 }
657 break;
658 case GL_ETC1_RGB8_OES:
659 if (context->getExtensions().compressedETC1RGB8Texture)
660 {
661 context->handleError(Error(GL_INVALID_OPERATION));
662 return false;
663 }
664 else
665 {
666 context->handleError(Error(GL_INVALID_ENUM));
667 return false;
668 }
669 break;
670 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
671 if (context->getExtensions().lossyETCDecode)
672 {
673 context->handleError(
674 Error(GL_INVALID_OPERATION,
675 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
676 return false;
677 }
678 else
679 {
680 context->handleError(Error(
681 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
682 return false;
683 }
684 break;
685 case GL_DEPTH_COMPONENT:
686 case GL_DEPTH_STENCIL_OES:
687 if (!context->getExtensions().depthTextures)
688 {
689 context->handleError(Error(GL_INVALID_VALUE));
690 return false;
691 }
692 if (target != GL_TEXTURE_2D)
693 {
694 context->handleError(Error(GL_INVALID_OPERATION));
695 return false;
696 }
697 // OES_depth_texture supports loading depth data and multiple levels,
698 // but ANGLE_depth_texture does not
699 if (pixels != NULL || level != 0)
700 {
701 context->handleError(Error(GL_INVALID_OPERATION));
702 return false;
703 }
704 break;
705 default:
706 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400707 }
708
709 if (type == GL_FLOAT)
710 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400711 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400712 {
Jamie Madill437fa652016-05-03 15:13:24 -0400713 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400714 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400715 }
716 }
717 else if (type == GL_HALF_FLOAT_OES)
718 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400719 if (!context->getExtensions().textureHalfFloat)
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 }
726
Geoff Langff5b2d52016-09-07 11:32:23 -0400727 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
728 imageSize))
729 {
730 return false;
731 }
732
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 return true;
734}
735
Jamie Madillc29968b2016-01-20 11:17:23 -0500736bool ValidateES2CopyTexImageParameters(ValidationContext *context,
737 GLenum target,
738 GLint level,
739 GLenum internalformat,
740 bool isSubImage,
741 GLint xoffset,
742 GLint yoffset,
743 GLint x,
744 GLint y,
745 GLsizei width,
746 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 GLint border)
748{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500749 if (!ValidTexture2DDestinationTarget(context, target))
750 {
Jamie Madill437fa652016-05-03 15:13:24 -0400751 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500752 return false;
753 }
754
Geoff Langcc507aa2016-12-12 10:09:52 -0500755 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
756 {
757 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
758 return false;
759 }
760
Jamie Madill0c8abca2016-07-22 20:21:26 -0400761 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400762 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400763 xoffset, yoffset, 0, x, y, width, height, border,
764 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400765 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 }
768
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700769 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400770 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400771 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772
773 // [OpenGL ES 2.0.24] table 3.9
774 if (isSubImage)
775 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400776 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800778 case GL_ALPHA:
779 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
780 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
781 {
782 context->handleError(Error(GL_INVALID_OPERATION));
783 return false;
784 }
785 break;
786 case GL_LUMINANCE:
787 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
788 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
789 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
790 colorbufferFormat != GL_RGBA8_OES)
791 {
792 context->handleError(Error(GL_INVALID_OPERATION));
793 return false;
794 }
795 break;
796 case GL_RED_EXT:
797 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
798 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
799 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
800 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
801 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
802 colorbufferFormat != GL_RGBA32F)
803 {
804 context->handleError(Error(GL_INVALID_OPERATION));
805 return false;
806 }
807 break;
808 case GL_RG_EXT:
809 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
810 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
811 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
812 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
813 colorbufferFormat != GL_RGBA32F)
814 {
815 context->handleError(Error(GL_INVALID_OPERATION));
816 return false;
817 }
818 break;
819 case GL_RGB:
820 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
821 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
822 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
823 colorbufferFormat != GL_RGBA32F)
824 {
825 context->handleError(Error(GL_INVALID_OPERATION));
826 return false;
827 }
828 break;
829 case GL_LUMINANCE_ALPHA:
830 case GL_RGBA:
831 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
832 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
833 {
834 context->handleError(Error(GL_INVALID_OPERATION));
835 return false;
836 }
837 break;
838 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
839 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
840 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
841 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
842 case GL_ETC1_RGB8_OES:
843 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400844 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400845 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800846 case GL_DEPTH_COMPONENT:
847 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800850 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400851 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400852 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500854
Jamie Madill0c8abca2016-07-22 20:21:26 -0400855 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500856 {
Jamie Madill437fa652016-05-03 15:13:24 -0400857 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500858 return false;
859 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 }
861 else
862 {
863 switch (internalformat)
864 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 case GL_ALPHA:
866 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
867 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
868 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
869 {
870 context->handleError(Error(GL_INVALID_OPERATION));
871 return false;
872 }
873 break;
874 case GL_LUMINANCE:
875 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
876 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
877 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
878 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
879 colorbufferFormat != GL_BGR5_A1_ANGLEX)
880 {
881 context->handleError(Error(GL_INVALID_OPERATION));
882 return false;
883 }
884 break;
885 case GL_RED_EXT:
886 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
887 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
888 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
889 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
890 colorbufferFormat != GL_BGR5_A1_ANGLEX)
891 {
892 context->handleError(Error(GL_INVALID_OPERATION));
893 return false;
894 }
895 break;
896 case GL_RG_EXT:
897 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
898 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
899 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
900 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
901 {
902 context->handleError(Error(GL_INVALID_OPERATION));
903 return false;
904 }
905 break;
906 case GL_RGB:
907 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
908 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
909 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
910 colorbufferFormat != GL_BGR5_A1_ANGLEX)
911 {
912 context->handleError(Error(GL_INVALID_OPERATION));
913 return false;
914 }
915 break;
916 case GL_LUMINANCE_ALPHA:
917 case GL_RGBA:
918 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
919 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
920 colorbufferFormat != GL_BGR5_A1_ANGLEX)
921 {
922 context->handleError(Error(GL_INVALID_OPERATION));
923 return false;
924 }
925 break;
926 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
927 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
928 if (context->getExtensions().textureCompressionDXT1)
929 {
930 context->handleError(Error(GL_INVALID_OPERATION));
931 return false;
932 }
933 else
934 {
935 context->handleError(Error(GL_INVALID_ENUM));
936 return false;
937 }
938 break;
939 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
940 if (context->getExtensions().textureCompressionDXT3)
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_DXT5_ANGLE:
952 if (context->getExtensions().textureCompressionDXT5)
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_ETC1_RGB8_OES:
964 if (context->getExtensions().compressedETC1RGB8Texture)
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_LOSSY_DECODE_ANGLE:
976 if (context->getExtensions().lossyETCDecode)
977 {
978 context->handleError(Error(GL_INVALID_OPERATION,
979 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
980 return false;
981 }
982 else
983 {
984 context->handleError(Error(
985 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
986 return false;
987 }
988 break;
989 case GL_DEPTH_COMPONENT:
990 case GL_DEPTH_COMPONENT16:
991 case GL_DEPTH_COMPONENT32_OES:
992 case GL_DEPTH_STENCIL_OES:
993 case GL_DEPTH24_STENCIL8_OES:
994 if (context->getExtensions().depthTextures)
995 {
996 context->handleError(Error(GL_INVALID_OPERATION));
997 return false;
998 }
999 else
1000 {
1001 context->handleError(Error(GL_INVALID_ENUM));
1002 return false;
1003 }
1004 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001005 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001006 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 }
1008 }
1009
Geoff Lang784a8fd2013-09-24 12:33:16 -04001010 // If width or height is zero, it is a no-op. Return false without setting an error.
1011 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012}
1013
He Yunchaoced53ae2016-11-29 15:00:51 +08001014bool ValidateES2TexStorageParameters(Context *context,
1015 GLenum target,
1016 GLsizei levels,
1017 GLenum internalformat,
1018 GLsizei width,
1019 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020{
1021 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1022 {
Jamie Madill437fa652016-05-03 15:13:24 -04001023 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026
1027 if (width < 1 || height < 1 || levels < 1)
1028 {
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001030 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 }
1032
1033 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1034 {
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001036 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 }
1038
1039 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1040 {
Jamie Madill437fa652016-05-03 15:13:24 -04001041 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001042 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001043 }
1044
Geoff Lang5d601382014-07-22 15:14:06 -04001045 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1046 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 {
Jamie Madill437fa652016-05-03 15:13:24 -04001048 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001049 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 }
1051
Geoff Langaae65a42014-05-26 12:43:44 -04001052 const gl::Caps &caps = context->getCaps();
1053
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001054 switch (target)
1055 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 case GL_TEXTURE_2D:
1057 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1058 static_cast<GLuint>(height) > caps.max2DTextureSize)
1059 {
1060 context->handleError(Error(GL_INVALID_VALUE));
1061 return false;
1062 }
1063 break;
1064 case GL_TEXTURE_CUBE_MAP:
1065 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1066 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1067 {
1068 context->handleError(Error(GL_INVALID_VALUE));
1069 return false;
1070 }
1071 break;
1072 default:
1073 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001074 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 }
1076
Geoff Langc0b9ef42014-07-02 10:02:37 -04001077 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 {
1079 if (!gl::isPow2(width) || !gl::isPow2(height))
1080 {
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 }
1084 }
1085
1086 switch (internalformat)
1087 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001088 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1089 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1090 if (!context->getExtensions().textureCompressionDXT1)
1091 {
1092 context->handleError(Error(GL_INVALID_ENUM));
1093 return false;
1094 }
1095 break;
1096 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1097 if (!context->getExtensions().textureCompressionDXT3)
1098 {
1099 context->handleError(Error(GL_INVALID_ENUM));
1100 return false;
1101 }
1102 break;
1103 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1104 if (!context->getExtensions().textureCompressionDXT5)
1105 {
1106 context->handleError(Error(GL_INVALID_ENUM));
1107 return false;
1108 }
1109 break;
1110 case GL_ETC1_RGB8_OES:
1111 if (!context->getExtensions().compressedETC1RGB8Texture)
1112 {
1113 context->handleError(Error(GL_INVALID_ENUM));
1114 return false;
1115 }
1116 break;
1117 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1118 if (!context->getExtensions().lossyETCDecode)
1119 {
1120 context->handleError(
1121 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1122 return false;
1123 }
1124 break;
1125 case GL_RGBA32F_EXT:
1126 case GL_RGB32F_EXT:
1127 case GL_ALPHA32F_EXT:
1128 case GL_LUMINANCE32F_EXT:
1129 case GL_LUMINANCE_ALPHA32F_EXT:
1130 if (!context->getExtensions().textureFloat)
1131 {
1132 context->handleError(Error(GL_INVALID_ENUM));
1133 return false;
1134 }
1135 break;
1136 case GL_RGBA16F_EXT:
1137 case GL_RGB16F_EXT:
1138 case GL_ALPHA16F_EXT:
1139 case GL_LUMINANCE16F_EXT:
1140 case GL_LUMINANCE_ALPHA16F_EXT:
1141 if (!context->getExtensions().textureHalfFloat)
1142 {
1143 context->handleError(Error(GL_INVALID_ENUM));
1144 return false;
1145 }
1146 break;
1147 case GL_R8_EXT:
1148 case GL_RG8_EXT:
1149 case GL_R16F_EXT:
1150 case GL_RG16F_EXT:
1151 case GL_R32F_EXT:
1152 case GL_RG32F_EXT:
1153 if (!context->getExtensions().textureRG)
1154 {
1155 context->handleError(Error(GL_INVALID_ENUM));
1156 return false;
1157 }
1158 break;
1159 case GL_DEPTH_COMPONENT16:
1160 case GL_DEPTH_COMPONENT32_OES:
1161 case GL_DEPTH24_STENCIL8_OES:
1162 if (!context->getExtensions().depthTextures)
1163 {
1164 context->handleError(Error(GL_INVALID_ENUM));
1165 return false;
1166 }
1167 if (target != GL_TEXTURE_2D)
1168 {
1169 context->handleError(Error(GL_INVALID_OPERATION));
1170 return false;
1171 }
1172 // ANGLE_depth_texture only supports 1-level textures
1173 if (levels != 1)
1174 {
1175 context->handleError(Error(GL_INVALID_OPERATION));
1176 return false;
1177 }
1178 break;
1179 default:
1180 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 }
1182
Geoff Lang691e58c2014-12-19 17:03:25 -05001183 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 if (!texture || texture->id() == 0)
1185 {
Jamie Madill437fa652016-05-03 15:13:24 -04001186 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001187 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001188 }
1189
Geoff Lang69cce582015-09-17 13:20:36 -04001190 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191 {
Jamie Madill437fa652016-05-03 15:13:24 -04001192 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001193 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194 }
1195
1196 return true;
1197}
1198
He Yunchaoced53ae2016-11-29 15:00:51 +08001199bool ValidateDiscardFramebufferEXT(Context *context,
1200 GLenum target,
1201 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001202 const GLenum *attachments)
1203{
Jamie Madillc29968b2016-01-20 11:17:23 -05001204 if (!context->getExtensions().discardFramebuffer)
1205 {
Jamie Madill437fa652016-05-03 15:13:24 -04001206 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001207 return false;
1208 }
1209
Austin Kinross08332632015-05-05 13:35:47 -07001210 bool defaultFramebuffer = false;
1211
1212 switch (target)
1213 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 case GL_FRAMEBUFFER:
1215 defaultFramebuffer =
1216 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1217 break;
1218 default:
1219 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1220 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001221 }
1222
He Yunchaoced53ae2016-11-29 15:00:51 +08001223 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1224 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001225}
1226
Austin Kinrossbc781f32015-10-26 09:27:38 -07001227bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1228{
1229 if (!context->getExtensions().vertexArrayObject)
1230 {
Jamie Madill437fa652016-05-03 15:13:24 -04001231 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001232 return false;
1233 }
1234
1235 return ValidateBindVertexArrayBase(context, array);
1236}
1237
1238bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1239{
1240 if (!context->getExtensions().vertexArrayObject)
1241 {
Jamie Madill437fa652016-05-03 15:13:24 -04001242 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001243 return false;
1244 }
1245
Olli Etuaho41997e72016-03-10 13:38:39 +02001246 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001247}
1248
1249bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1250{
1251 if (!context->getExtensions().vertexArrayObject)
1252 {
Jamie Madill437fa652016-05-03 15:13:24 -04001253 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001254 return false;
1255 }
1256
Olli Etuaho41997e72016-03-10 13:38:39 +02001257 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001258}
1259
1260bool ValidateIsVertexArrayOES(Context *context)
1261{
1262 if (!context->getExtensions().vertexArrayObject)
1263 {
Jamie Madill437fa652016-05-03 15:13:24 -04001264 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001265 return false;
1266 }
1267
1268 return true;
1269}
Geoff Langc5629752015-12-07 16:29:04 -05001270
1271bool ValidateProgramBinaryOES(Context *context,
1272 GLuint program,
1273 GLenum binaryFormat,
1274 const void *binary,
1275 GLint length)
1276{
1277 if (!context->getExtensions().getProgramBinary)
1278 {
Jamie Madill437fa652016-05-03 15:13:24 -04001279 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001280 return false;
1281 }
1282
1283 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1284}
1285
1286bool ValidateGetProgramBinaryOES(Context *context,
1287 GLuint program,
1288 GLsizei bufSize,
1289 GLsizei *length,
1290 GLenum *binaryFormat,
1291 void *binary)
1292{
1293 if (!context->getExtensions().getProgramBinary)
1294 {
Jamie Madill437fa652016-05-03 15:13:24 -04001295 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001296 return false;
1297 }
1298
1299 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1300}
Geoff Lange102fee2015-12-10 11:23:30 -05001301
Geoff Lang70d0f492015-12-10 17:45:46 -05001302static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1303{
1304 switch (source)
1305 {
1306 case GL_DEBUG_SOURCE_API:
1307 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1308 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1309 case GL_DEBUG_SOURCE_OTHER:
1310 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1311 return !mustBeThirdPartyOrApplication;
1312
1313 case GL_DEBUG_SOURCE_THIRD_PARTY:
1314 case GL_DEBUG_SOURCE_APPLICATION:
1315 return true;
1316
1317 default:
1318 return false;
1319 }
1320}
1321
1322static bool ValidDebugType(GLenum type)
1323{
1324 switch (type)
1325 {
1326 case GL_DEBUG_TYPE_ERROR:
1327 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1328 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1329 case GL_DEBUG_TYPE_PERFORMANCE:
1330 case GL_DEBUG_TYPE_PORTABILITY:
1331 case GL_DEBUG_TYPE_OTHER:
1332 case GL_DEBUG_TYPE_MARKER:
1333 case GL_DEBUG_TYPE_PUSH_GROUP:
1334 case GL_DEBUG_TYPE_POP_GROUP:
1335 return true;
1336
1337 default:
1338 return false;
1339 }
1340}
1341
1342static bool ValidDebugSeverity(GLenum severity)
1343{
1344 switch (severity)
1345 {
1346 case GL_DEBUG_SEVERITY_HIGH:
1347 case GL_DEBUG_SEVERITY_MEDIUM:
1348 case GL_DEBUG_SEVERITY_LOW:
1349 case GL_DEBUG_SEVERITY_NOTIFICATION:
1350 return true;
1351
1352 default:
1353 return false;
1354 }
1355}
1356
Geoff Lange102fee2015-12-10 11:23:30 -05001357bool ValidateDebugMessageControlKHR(Context *context,
1358 GLenum source,
1359 GLenum type,
1360 GLenum severity,
1361 GLsizei count,
1362 const GLuint *ids,
1363 GLboolean enabled)
1364{
1365 if (!context->getExtensions().debug)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001368 return false;
1369 }
1370
Geoff Lang70d0f492015-12-10 17:45:46 -05001371 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001374 return false;
1375 }
1376
1377 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1378 {
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001380 return false;
1381 }
1382
1383 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001386 return false;
1387 }
1388
1389 if (count > 0)
1390 {
1391 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001394 GL_INVALID_OPERATION,
1395 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1396 return false;
1397 }
1398
1399 if (severity != GL_DONT_CARE)
1400 {
Jamie Madill437fa652016-05-03 15:13:24 -04001401 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001402 Error(GL_INVALID_OPERATION,
1403 "If count is greater than zero, severity must be GL_DONT_CARE."));
1404 return false;
1405 }
1406 }
1407
Geoff Lange102fee2015-12-10 11:23:30 -05001408 return true;
1409}
1410
1411bool ValidateDebugMessageInsertKHR(Context *context,
1412 GLenum source,
1413 GLenum type,
1414 GLuint id,
1415 GLenum severity,
1416 GLsizei length,
1417 const GLchar *buf)
1418{
1419 if (!context->getExtensions().debug)
1420 {
Jamie Madill437fa652016-05-03 15:13:24 -04001421 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001422 return false;
1423 }
1424
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001425 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001426 {
1427 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1428 // not generate an error.
1429 return false;
1430 }
1431
1432 if (!ValidDebugSeverity(severity))
1433 {
Jamie Madill437fa652016-05-03 15:13:24 -04001434 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001435 return false;
1436 }
1437
1438 if (!ValidDebugType(type))
1439 {
Jamie Madill437fa652016-05-03 15:13:24 -04001440 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001441 return false;
1442 }
1443
1444 if (!ValidDebugSource(source, true))
1445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001447 return false;
1448 }
1449
1450 size_t messageLength = (length < 0) ? strlen(buf) : length;
1451 if (messageLength > context->getExtensions().maxDebugMessageLength)
1452 {
Jamie Madill437fa652016-05-03 15:13:24 -04001453 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001454 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1455 return false;
1456 }
1457
Geoff Lange102fee2015-12-10 11:23:30 -05001458 return true;
1459}
1460
1461bool ValidateDebugMessageCallbackKHR(Context *context,
1462 GLDEBUGPROCKHR callback,
1463 const void *userParam)
1464{
1465 if (!context->getExtensions().debug)
1466 {
Jamie Madill437fa652016-05-03 15:13:24 -04001467 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001468 return false;
1469 }
1470
Geoff Lange102fee2015-12-10 11:23:30 -05001471 return true;
1472}
1473
1474bool ValidateGetDebugMessageLogKHR(Context *context,
1475 GLuint count,
1476 GLsizei bufSize,
1477 GLenum *sources,
1478 GLenum *types,
1479 GLuint *ids,
1480 GLenum *severities,
1481 GLsizei *lengths,
1482 GLchar *messageLog)
1483{
1484 if (!context->getExtensions().debug)
1485 {
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001487 return false;
1488 }
1489
Geoff Lang70d0f492015-12-10 17:45:46 -05001490 if (bufSize < 0 && messageLog != nullptr)
1491 {
Jamie Madill437fa652016-05-03 15:13:24 -04001492 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001493 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1494 return false;
1495 }
1496
Geoff Lange102fee2015-12-10 11:23:30 -05001497 return true;
1498}
1499
1500bool ValidatePushDebugGroupKHR(Context *context,
1501 GLenum source,
1502 GLuint id,
1503 GLsizei length,
1504 const GLchar *message)
1505{
1506 if (!context->getExtensions().debug)
1507 {
Jamie Madill437fa652016-05-03 15:13:24 -04001508 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001509 return false;
1510 }
1511
Geoff Lang70d0f492015-12-10 17:45:46 -05001512 if (!ValidDebugSource(source, true))
1513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001515 return false;
1516 }
1517
1518 size_t messageLength = (length < 0) ? strlen(message) : length;
1519 if (messageLength > context->getExtensions().maxDebugMessageLength)
1520 {
Jamie Madill437fa652016-05-03 15:13:24 -04001521 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001522 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1523 return false;
1524 }
1525
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001526 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001527 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001530 Error(GL_STACK_OVERFLOW,
1531 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1532 return false;
1533 }
1534
Geoff Lange102fee2015-12-10 11:23:30 -05001535 return true;
1536}
1537
1538bool ValidatePopDebugGroupKHR(Context *context)
1539{
1540 if (!context->getExtensions().debug)
1541 {
Jamie Madill437fa652016-05-03 15:13:24 -04001542 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001543 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 <= 1)
1548 {
Jamie Madill437fa652016-05-03 15:13:24 -04001549 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001550 return false;
1551 }
1552
1553 return true;
1554}
1555
1556static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1557{
1558 switch (identifier)
1559 {
1560 case GL_BUFFER:
1561 if (context->getBuffer(name) == nullptr)
1562 {
Jamie Madill437fa652016-05-03 15:13:24 -04001563 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001564 return false;
1565 }
1566 return true;
1567
1568 case GL_SHADER:
1569 if (context->getShader(name) == nullptr)
1570 {
Jamie Madill437fa652016-05-03 15:13:24 -04001571 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001572 return false;
1573 }
1574 return true;
1575
1576 case GL_PROGRAM:
1577 if (context->getProgram(name) == nullptr)
1578 {
Jamie Madill437fa652016-05-03 15:13:24 -04001579 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001580 return false;
1581 }
1582 return true;
1583
1584 case GL_VERTEX_ARRAY:
1585 if (context->getVertexArray(name) == nullptr)
1586 {
Jamie Madill437fa652016-05-03 15:13:24 -04001587 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001588 return false;
1589 }
1590 return true;
1591
1592 case GL_QUERY:
1593 if (context->getQuery(name) == nullptr)
1594 {
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001596 return false;
1597 }
1598 return true;
1599
1600 case GL_TRANSFORM_FEEDBACK:
1601 if (context->getTransformFeedback(name) == nullptr)
1602 {
Jamie Madill437fa652016-05-03 15:13:24 -04001603 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001604 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1605 return false;
1606 }
1607 return true;
1608
1609 case GL_SAMPLER:
1610 if (context->getSampler(name) == nullptr)
1611 {
Jamie Madill437fa652016-05-03 15:13:24 -04001612 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001613 return false;
1614 }
1615 return true;
1616
1617 case GL_TEXTURE:
1618 if (context->getTexture(name) == nullptr)
1619 {
Jamie Madill437fa652016-05-03 15:13:24 -04001620 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001621 return false;
1622 }
1623 return true;
1624
1625 case GL_RENDERBUFFER:
1626 if (context->getRenderbuffer(name) == nullptr)
1627 {
Jamie Madill437fa652016-05-03 15:13:24 -04001628 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001629 return false;
1630 }
1631 return true;
1632
1633 case GL_FRAMEBUFFER:
1634 if (context->getFramebuffer(name) == nullptr)
1635 {
Jamie Madill437fa652016-05-03 15:13:24 -04001636 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001637 return false;
1638 }
1639 return true;
1640
1641 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001643 return false;
1644 }
Geoff Lange102fee2015-12-10 11:23:30 -05001645}
1646
Martin Radev9d901792016-07-15 15:58:58 +03001647static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1648{
1649 size_t labelLength = 0;
1650
1651 if (length < 0)
1652 {
1653 if (label != nullptr)
1654 {
1655 labelLength = strlen(label);
1656 }
1657 }
1658 else
1659 {
1660 labelLength = static_cast<size_t>(length);
1661 }
1662
1663 if (labelLength > context->getExtensions().maxLabelLength)
1664 {
1665 context->handleError(
1666 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1667 return false;
1668 }
1669
1670 return true;
1671}
1672
Geoff Lange102fee2015-12-10 11:23:30 -05001673bool ValidateObjectLabelKHR(Context *context,
1674 GLenum identifier,
1675 GLuint name,
1676 GLsizei length,
1677 const GLchar *label)
1678{
1679 if (!context->getExtensions().debug)
1680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001682 return false;
1683 }
1684
Geoff Lang70d0f492015-12-10 17:45:46 -05001685 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1686 {
1687 return false;
1688 }
1689
Martin Radev9d901792016-07-15 15:58:58 +03001690 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001691 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001692 return false;
1693 }
1694
Geoff Lange102fee2015-12-10 11:23:30 -05001695 return true;
1696}
1697
1698bool ValidateGetObjectLabelKHR(Context *context,
1699 GLenum identifier,
1700 GLuint name,
1701 GLsizei bufSize,
1702 GLsizei *length,
1703 GLchar *label)
1704{
1705 if (!context->getExtensions().debug)
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001708 return false;
1709 }
1710
Geoff Lang70d0f492015-12-10 17:45:46 -05001711 if (bufSize < 0)
1712 {
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001714 return false;
1715 }
1716
1717 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1718 {
1719 return false;
1720 }
1721
Martin Radev9d901792016-07-15 15:58:58 +03001722 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001723}
1724
1725static bool ValidateObjectPtrName(Context *context, const void *ptr)
1726{
1727 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1728 {
Jamie Madill437fa652016-05-03 15:13:24 -04001729 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001730 return false;
1731 }
1732
Geoff Lange102fee2015-12-10 11:23:30 -05001733 return true;
1734}
1735
1736bool ValidateObjectPtrLabelKHR(Context *context,
1737 const void *ptr,
1738 GLsizei length,
1739 const GLchar *label)
1740{
1741 if (!context->getExtensions().debug)
1742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001744 return false;
1745 }
1746
Geoff Lang70d0f492015-12-10 17:45:46 -05001747 if (!ValidateObjectPtrName(context, ptr))
1748 {
1749 return false;
1750 }
1751
Martin Radev9d901792016-07-15 15:58:58 +03001752 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001753 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001754 return false;
1755 }
1756
Geoff Lange102fee2015-12-10 11:23:30 -05001757 return true;
1758}
1759
1760bool ValidateGetObjectPtrLabelKHR(Context *context,
1761 const void *ptr,
1762 GLsizei bufSize,
1763 GLsizei *length,
1764 GLchar *label)
1765{
1766 if (!context->getExtensions().debug)
1767 {
Jamie Madill437fa652016-05-03 15:13:24 -04001768 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001769 return false;
1770 }
1771
Geoff Lang70d0f492015-12-10 17:45:46 -05001772 if (bufSize < 0)
1773 {
Jamie Madill437fa652016-05-03 15:13:24 -04001774 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001775 return false;
1776 }
1777
1778 if (!ValidateObjectPtrName(context, ptr))
1779 {
1780 return false;
1781 }
1782
Martin Radev9d901792016-07-15 15:58:58 +03001783 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001784}
1785
1786bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1787{
1788 if (!context->getExtensions().debug)
1789 {
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001791 return false;
1792 }
1793
Geoff Lang70d0f492015-12-10 17:45:46 -05001794 // TODO: represent this in Context::getQueryParameterInfo.
1795 switch (pname)
1796 {
1797 case GL_DEBUG_CALLBACK_FUNCTION:
1798 case GL_DEBUG_CALLBACK_USER_PARAM:
1799 break;
1800
1801 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001802 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001803 return false;
1804 }
1805
Geoff Lange102fee2015-12-10 11:23:30 -05001806 return true;
1807}
Jamie Madillc29968b2016-01-20 11:17:23 -05001808
1809bool ValidateBlitFramebufferANGLE(Context *context,
1810 GLint srcX0,
1811 GLint srcY0,
1812 GLint srcX1,
1813 GLint srcY1,
1814 GLint dstX0,
1815 GLint dstY0,
1816 GLint dstX1,
1817 GLint dstY1,
1818 GLbitfield mask,
1819 GLenum filter)
1820{
1821 if (!context->getExtensions().framebufferBlit)
1822 {
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 return false;
1825 }
1826
1827 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1828 {
1829 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001830 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001831 GL_INVALID_OPERATION,
1832 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1833 return false;
1834 }
1835
1836 if (filter == GL_LINEAR)
1837 {
Jamie Madill437fa652016-05-03 15:13:24 -04001838 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001839 return false;
1840 }
1841
Jamie Madill51f40ec2016-06-15 14:06:00 -04001842 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1843 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001844
1845 if (mask & GL_COLOR_BUFFER_BIT)
1846 {
1847 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1848 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1849
1850 if (readColorAttachment && drawColorAttachment)
1851 {
1852 if (!(readColorAttachment->type() == GL_TEXTURE &&
1853 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1854 readColorAttachment->type() != GL_RENDERBUFFER &&
1855 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860
Geoff Langa15472a2015-08-11 11:48:03 -04001861 for (size_t drawbufferIdx = 0;
1862 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001863 {
Geoff Langa15472a2015-08-11 11:48:03 -04001864 const FramebufferAttachment *attachment =
1865 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1866 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001867 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001868 if (!(attachment->type() == GL_TEXTURE &&
1869 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1870 attachment->type() != GL_RENDERBUFFER &&
1871 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1872 {
Jamie Madill437fa652016-05-03 15:13:24 -04001873 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001874 return false;
1875 }
1876
1877 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001878 if (!Format::SameSized(attachment->getFormat(),
1879 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001882 return false;
1883 }
1884 }
1885 }
1886
Jamie Madill51f40ec2016-06-15 14:06:00 -04001887 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1889 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1890 {
Jamie Madill437fa652016-05-03 15:13:24 -04001891 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001892 return false;
1893 }
1894 }
1895 }
1896
1897 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1898 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1899 for (size_t i = 0; i < 2; i++)
1900 {
1901 if (mask & masks[i])
1902 {
1903 const FramebufferAttachment *readBuffer =
1904 readFramebuffer->getAttachment(attachments[i]);
1905 const FramebufferAttachment *drawBuffer =
1906 drawFramebuffer->getAttachment(attachments[i]);
1907
1908 if (readBuffer && drawBuffer)
1909 {
1910 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1911 dstX0, dstY0, dstX1, dstY1))
1912 {
1913 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05001914 context->handleError(Error(GL_INVALID_OPERATION,
1915 "Only whole-buffer depth and stencil blits are "
1916 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001917 return false;
1918 }
1919
1920 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1921 {
Jamie Madill437fa652016-05-03 15:13:24 -04001922 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001923 return false;
1924 }
1925 }
1926 }
1927 }
1928
1929 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1930 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001931}
Jamie Madillc29968b2016-01-20 11:17:23 -05001932
1933bool ValidateClear(ValidationContext *context, GLbitfield mask)
1934{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001935 auto fbo = context->getGLState().getDrawFramebuffer();
1936 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001937 {
Jamie Madill437fa652016-05-03 15:13:24 -04001938 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001939 return false;
1940 }
1941
1942 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001945 return false;
1946 }
1947
1948 return true;
1949}
1950
1951bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1952{
1953 if (!context->getExtensions().drawBuffers)
1954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001956 return false;
1957 }
1958
1959 return ValidateDrawBuffersBase(context, n, bufs);
1960}
1961
Jamie Madill73a84962016-02-12 09:27:23 -05001962bool ValidateTexImage2D(Context *context,
1963 GLenum target,
1964 GLint level,
1965 GLint internalformat,
1966 GLsizei width,
1967 GLsizei height,
1968 GLint border,
1969 GLenum format,
1970 GLenum type,
1971 const GLvoid *pixels)
1972{
Martin Radev1be913c2016-07-11 17:59:16 +03001973 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001974 {
1975 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001976 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001977 }
1978
Martin Radev1be913c2016-07-11 17:59:16 +03001979 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001980 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001981 0, 0, width, height, 1, border, format, type, -1,
1982 pixels);
1983}
1984
1985bool ValidateTexImage2DRobust(Context *context,
1986 GLenum target,
1987 GLint level,
1988 GLint internalformat,
1989 GLsizei width,
1990 GLsizei height,
1991 GLint border,
1992 GLenum format,
1993 GLenum type,
1994 GLsizei bufSize,
1995 const GLvoid *pixels)
1996{
1997 if (!ValidateRobustEntryPoint(context, bufSize))
1998 {
1999 return false;
2000 }
2001
2002 if (context->getClientMajorVersion() < 3)
2003 {
2004 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2005 0, 0, width, height, border, format, type, bufSize,
2006 pixels);
2007 }
2008
2009 ASSERT(context->getClientMajorVersion() >= 3);
2010 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2011 0, 0, width, height, 1, border, format, type, bufSize,
2012 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002013}
2014
2015bool ValidateTexSubImage2D(Context *context,
2016 GLenum target,
2017 GLint level,
2018 GLint xoffset,
2019 GLint yoffset,
2020 GLsizei width,
2021 GLsizei height,
2022 GLenum format,
2023 GLenum type,
2024 const GLvoid *pixels)
2025{
2026
Martin Radev1be913c2016-07-11 17:59:16 +03002027 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002028 {
2029 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002030 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002031 }
2032
Martin Radev1be913c2016-07-11 17:59:16 +03002033 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002034 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002035 yoffset, 0, width, height, 1, 0, format, type, -1,
2036 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002037}
2038
Geoff Langc52f6f12016-10-14 10:18:00 -04002039bool ValidateTexSubImage2DRobustANGLE(Context *context,
2040 GLenum target,
2041 GLint level,
2042 GLint xoffset,
2043 GLint yoffset,
2044 GLsizei width,
2045 GLsizei height,
2046 GLenum format,
2047 GLenum type,
2048 GLsizei bufSize,
2049 const GLvoid *pixels)
2050{
2051 if (!ValidateRobustEntryPoint(context, bufSize))
2052 {
2053 return false;
2054 }
2055
2056 if (context->getClientMajorVersion() < 3)
2057 {
2058 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2059 yoffset, width, height, 0, format, type, bufSize,
2060 pixels);
2061 }
2062
2063 ASSERT(context->getClientMajorVersion() >= 3);
2064 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2065 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2066 pixels);
2067}
2068
Jamie Madill73a84962016-02-12 09:27:23 -05002069bool ValidateCompressedTexImage2D(Context *context,
2070 GLenum target,
2071 GLint level,
2072 GLenum internalformat,
2073 GLsizei width,
2074 GLsizei height,
2075 GLint border,
2076 GLsizei imageSize,
2077 const GLvoid *data)
2078{
Martin Radev1be913c2016-07-11 17:59:16 +03002079 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002080 {
2081 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002082 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002083 {
2084 return false;
2085 }
2086 }
2087 else
2088 {
Martin Radev1be913c2016-07-11 17:59:16 +03002089 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002090 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002091 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002092 data))
2093 {
2094 return false;
2095 }
2096 }
2097
2098 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002099 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002100 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002101 if (blockSizeOrErr.isError())
2102 {
2103 context->handleError(blockSizeOrErr.getError());
2104 return false;
2105 }
2106
2107 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002108 {
Jamie Madill437fa652016-05-03 15:13:24 -04002109 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002110 return false;
2111 }
2112
2113 return true;
2114}
2115
2116bool ValidateCompressedTexSubImage2D(Context *context,
2117 GLenum target,
2118 GLint level,
2119 GLint xoffset,
2120 GLint yoffset,
2121 GLsizei width,
2122 GLsizei height,
2123 GLenum format,
2124 GLsizei imageSize,
2125 const GLvoid *data)
2126{
Martin Radev1be913c2016-07-11 17:59:16 +03002127 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002128 {
2129 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002130 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002131 {
2132 return false;
2133 }
2134 }
2135 else
2136 {
Martin Radev1be913c2016-07-11 17:59:16 +03002137 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002138 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002139 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002140 data))
2141 {
2142 return false;
2143 }
2144 }
2145
2146 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002147 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002148 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002149 if (blockSizeOrErr.isError())
2150 {
2151 context->handleError(blockSizeOrErr.getError());
2152 return false;
2153 }
2154
2155 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002156 {
Jamie Madill437fa652016-05-03 15:13:24 -04002157 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002158 return false;
2159 }
2160
2161 return true;
2162}
2163
Olli Etuaho4f667482016-03-30 15:56:35 +03002164bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2165{
Geoff Lang496c02d2016-10-20 11:38:11 -07002166 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002167}
2168
2169bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2170{
2171 if (!context->getExtensions().mapBuffer)
2172 {
Jamie Madill437fa652016-05-03 15:13:24 -04002173 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002174 return false;
2175 }
2176
2177 if (!ValidBufferTarget(context, target))
2178 {
Jamie Madill437fa652016-05-03 15:13:24 -04002179 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002180 return false;
2181 }
2182
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002183 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002184
2185 if (buffer == nullptr)
2186 {
Jamie Madill437fa652016-05-03 15:13:24 -04002187 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002188 return false;
2189 }
2190
2191 if (access != GL_WRITE_ONLY_OES)
2192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002194 return false;
2195 }
2196
2197 if (buffer->isMapped())
2198 {
Jamie Madill437fa652016-05-03 15:13:24 -04002199 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002200 return false;
2201 }
2202
2203 return true;
2204}
2205
2206bool ValidateUnmapBufferOES(Context *context, GLenum target)
2207{
2208 if (!context->getExtensions().mapBuffer)
2209 {
Jamie Madill437fa652016-05-03 15:13:24 -04002210 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002211 return false;
2212 }
2213
2214 return ValidateUnmapBufferBase(context, target);
2215}
2216
2217bool ValidateMapBufferRangeEXT(Context *context,
2218 GLenum target,
2219 GLintptr offset,
2220 GLsizeiptr length,
2221 GLbitfield access)
2222{
2223 if (!context->getExtensions().mapBufferRange)
2224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002226 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2227 return false;
2228 }
2229
2230 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2231}
2232
2233bool ValidateFlushMappedBufferRangeEXT(Context *context,
2234 GLenum target,
2235 GLintptr offset,
2236 GLsizeiptr length)
2237{
2238 if (!context->getExtensions().mapBufferRange)
2239 {
Jamie Madill437fa652016-05-03 15:13:24 -04002240 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002241 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2242 return false;
2243 }
2244
2245 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2246}
2247
Ian Ewell54f87462016-03-10 13:47:21 -05002248bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2249{
2250 Texture *textureObject = context->getTexture(texture);
2251 if (textureObject && textureObject->getTarget() != target && texture != 0)
2252 {
Jamie Madill437fa652016-05-03 15:13:24 -04002253 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002254 return false;
2255 }
2256
Geoff Langf41a7152016-09-19 15:11:17 -04002257 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2258 !context->isTextureGenerated(texture))
2259 {
2260 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2261 return false;
2262 }
2263
Ian Ewell54f87462016-03-10 13:47:21 -05002264 switch (target)
2265 {
2266 case GL_TEXTURE_2D:
2267 case GL_TEXTURE_CUBE_MAP:
2268 break;
2269
2270 case GL_TEXTURE_3D:
2271 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002272 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002273 {
Jamie Madill437fa652016-05-03 15:13:24 -04002274 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002275 return false;
2276 }
2277 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002278
2279 case GL_TEXTURE_2D_MULTISAMPLE:
2280 if (context->getClientVersion() < Version(3, 1))
2281 {
2282 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2283 return false;
2284 }
Geoff Lang3b573612016-10-31 14:08:10 -04002285 break;
2286
Ian Ewell54f87462016-03-10 13:47:21 -05002287 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002288 if (!context->getExtensions().eglImageExternal &&
2289 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002290 {
Jamie Madill437fa652016-05-03 15:13:24 -04002291 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002292 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2293 return false;
2294 }
2295 break;
2296 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002297 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002298 return false;
2299 }
2300
2301 return true;
2302}
2303
Geoff Langd8605522016-04-13 10:19:12 -04002304bool ValidateBindUniformLocationCHROMIUM(Context *context,
2305 GLuint program,
2306 GLint location,
2307 const GLchar *name)
2308{
2309 if (!context->getExtensions().bindUniformLocation)
2310 {
Jamie Madill437fa652016-05-03 15:13:24 -04002311 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002312 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2313 return false;
2314 }
2315
2316 Program *programObject = GetValidProgram(context, program);
2317 if (!programObject)
2318 {
2319 return false;
2320 }
2321
2322 if (location < 0)
2323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002325 return false;
2326 }
2327
2328 const Caps &caps = context->getCaps();
2329 if (static_cast<size_t>(location) >=
2330 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2331 {
Jamie Madill437fa652016-05-03 15:13:24 -04002332 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002333 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2334 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2335 return false;
2336 }
2337
2338 if (strncmp(name, "gl_", 3) == 0)
2339 {
Jamie Madill437fa652016-05-03 15:13:24 -04002340 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002341 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2342 return false;
2343 }
2344
2345 return true;
2346}
2347
Jamie Madille2e406c2016-06-02 13:04:10 -04002348bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002349{
2350 if (!context->getExtensions().framebufferMixedSamples)
2351 {
2352 context->handleError(
2353 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2354 return false;
2355 }
2356 switch (components)
2357 {
2358 case GL_RGB:
2359 case GL_RGBA:
2360 case GL_ALPHA:
2361 case GL_NONE:
2362 break;
2363 default:
2364 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002365 Error(GL_INVALID_ENUM,
2366 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002367 return false;
2368 }
2369
2370 return true;
2371}
2372
Sami Väisänene45e53b2016-05-25 10:36:04 +03002373// CHROMIUM_path_rendering
2374
2375bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2376{
2377 if (!context->getExtensions().pathRendering)
2378 {
2379 context->handleError(
2380 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2381 return false;
2382 }
2383 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2384 {
2385 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2386 return false;
2387 }
2388 if (matrix == nullptr)
2389 {
2390 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2391 return false;
2392 }
2393 return true;
2394}
2395
2396bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2397{
2398 if (!context->getExtensions().pathRendering)
2399 {
2400 context->handleError(
2401 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2402 return false;
2403 }
2404 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2405 {
2406 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2407 return false;
2408 }
2409 return true;
2410}
2411
2412bool ValidateGenPaths(Context *context, GLsizei range)
2413{
2414 if (!context->getExtensions().pathRendering)
2415 {
2416 context->handleError(
2417 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2418 return false;
2419 }
2420
2421 // range = 0 is undefined in NV_path_rendering.
2422 // we add stricter semantic check here and require a non zero positive range.
2423 if (range <= 0)
2424 {
2425 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2426 return false;
2427 }
2428
2429 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2430 {
2431 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2432 return false;
2433 }
2434
2435 return true;
2436}
2437
2438bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2439{
2440 if (!context->getExtensions().pathRendering)
2441 {
2442 context->handleError(
2443 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2444 return false;
2445 }
2446
2447 // range = 0 is undefined in NV_path_rendering.
2448 // we add stricter semantic check here and require a non zero positive range.
2449 if (range <= 0)
2450 {
2451 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2452 return false;
2453 }
2454
2455 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2456 checkedRange += range;
2457
2458 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2459 {
2460 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2461 return false;
2462 }
2463 return true;
2464}
2465
2466bool ValidatePathCommands(Context *context,
2467 GLuint path,
2468 GLsizei numCommands,
2469 const GLubyte *commands,
2470 GLsizei numCoords,
2471 GLenum coordType,
2472 const void *coords)
2473{
2474 if (!context->getExtensions().pathRendering)
2475 {
2476 context->handleError(
2477 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2478 return false;
2479 }
2480 if (!context->hasPath(path))
2481 {
2482 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2483 return false;
2484 }
2485
2486 if (numCommands < 0)
2487 {
2488 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2489 return false;
2490 }
2491 else if (numCommands > 0)
2492 {
2493 if (!commands)
2494 {
2495 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2496 return false;
2497 }
2498 }
2499
2500 if (numCoords < 0)
2501 {
2502 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2503 return false;
2504 }
2505 else if (numCoords > 0)
2506 {
2507 if (!coords)
2508 {
2509 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2510 return false;
2511 }
2512 }
2513
2514 std::uint32_t coordTypeSize = 0;
2515 switch (coordType)
2516 {
2517 case GL_BYTE:
2518 coordTypeSize = sizeof(GLbyte);
2519 break;
2520
2521 case GL_UNSIGNED_BYTE:
2522 coordTypeSize = sizeof(GLubyte);
2523 break;
2524
2525 case GL_SHORT:
2526 coordTypeSize = sizeof(GLshort);
2527 break;
2528
2529 case GL_UNSIGNED_SHORT:
2530 coordTypeSize = sizeof(GLushort);
2531 break;
2532
2533 case GL_FLOAT:
2534 coordTypeSize = sizeof(GLfloat);
2535 break;
2536
2537 default:
2538 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2539 return false;
2540 }
2541
2542 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2543 checkedSize += (coordTypeSize * numCoords);
2544 if (!checkedSize.IsValid())
2545 {
2546 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2547 return false;
2548 }
2549
2550 // early return skips command data validation when it doesn't exist.
2551 if (!commands)
2552 return true;
2553
2554 GLsizei expectedNumCoords = 0;
2555 for (GLsizei i = 0; i < numCommands; ++i)
2556 {
2557 switch (commands[i])
2558 {
2559 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2560 break;
2561 case GL_MOVE_TO_CHROMIUM:
2562 case GL_LINE_TO_CHROMIUM:
2563 expectedNumCoords += 2;
2564 break;
2565 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2566 expectedNumCoords += 4;
2567 break;
2568 case GL_CUBIC_CURVE_TO_CHROMIUM:
2569 expectedNumCoords += 6;
2570 break;
2571 case GL_CONIC_CURVE_TO_CHROMIUM:
2572 expectedNumCoords += 5;
2573 break;
2574 default:
2575 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2576 return false;
2577 }
2578 }
2579 if (expectedNumCoords != numCoords)
2580 {
2581 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2582 return false;
2583 }
2584
2585 return true;
2586}
2587
2588bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2589{
2590 if (!context->getExtensions().pathRendering)
2591 {
2592 context->handleError(
2593 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2594 return false;
2595 }
2596 if (!context->hasPath(path))
2597 {
2598 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2599 return false;
2600 }
2601
2602 switch (pname)
2603 {
2604 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2605 if (value < 0.0f)
2606 {
2607 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2608 return false;
2609 }
2610 break;
2611 case GL_PATH_END_CAPS_CHROMIUM:
2612 switch (static_cast<GLenum>(value))
2613 {
2614 case GL_FLAT_CHROMIUM:
2615 case GL_SQUARE_CHROMIUM:
2616 case GL_ROUND_CHROMIUM:
2617 break;
2618 default:
2619 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2620 return false;
2621 }
2622 break;
2623 case GL_PATH_JOIN_STYLE_CHROMIUM:
2624 switch (static_cast<GLenum>(value))
2625 {
2626 case GL_MITER_REVERT_CHROMIUM:
2627 case GL_BEVEL_CHROMIUM:
2628 case GL_ROUND_CHROMIUM:
2629 break;
2630 default:
2631 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2632 return false;
2633 }
2634 case GL_PATH_MITER_LIMIT_CHROMIUM:
2635 if (value < 0.0f)
2636 {
2637 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2638 return false;
2639 }
2640 break;
2641
2642 case GL_PATH_STROKE_BOUND_CHROMIUM:
2643 // no errors, only clamping.
2644 break;
2645
2646 default:
2647 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2648 return false;
2649 }
2650 return true;
2651}
2652
2653bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2654{
2655 if (!context->getExtensions().pathRendering)
2656 {
2657 context->handleError(
2658 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2659 return false;
2660 }
2661
2662 if (!context->hasPath(path))
2663 {
2664 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2665 return false;
2666 }
2667 if (!value)
2668 {
2669 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2670 return false;
2671 }
2672
2673 switch (pname)
2674 {
2675 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2676 case GL_PATH_END_CAPS_CHROMIUM:
2677 case GL_PATH_JOIN_STYLE_CHROMIUM:
2678 case GL_PATH_MITER_LIMIT_CHROMIUM:
2679 case GL_PATH_STROKE_BOUND_CHROMIUM:
2680 break;
2681
2682 default:
2683 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2684 return false;
2685 }
2686
2687 return true;
2688}
2689
2690bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2691{
2692 if (!context->getExtensions().pathRendering)
2693 {
2694 context->handleError(
2695 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2696 return false;
2697 }
2698
2699 switch (func)
2700 {
2701 case GL_NEVER:
2702 case GL_ALWAYS:
2703 case GL_LESS:
2704 case GL_LEQUAL:
2705 case GL_EQUAL:
2706 case GL_GEQUAL:
2707 case GL_GREATER:
2708 case GL_NOTEQUAL:
2709 break;
2710 default:
2711 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2712 return false;
2713 }
2714
2715 return true;
2716}
2717
2718// Note that the spec specifies that for the path drawing commands
2719// if the path object is not an existing path object the command
2720// does nothing and no error is generated.
2721// However if the path object exists but has not been specified any
2722// commands then an error is generated.
2723
2724bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2725{
2726 if (!context->getExtensions().pathRendering)
2727 {
2728 context->handleError(
2729 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2730 return false;
2731 }
2732 if (context->hasPath(path) && !context->hasPathData(path))
2733 {
2734 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2735 return false;
2736 }
2737
2738 switch (fillMode)
2739 {
2740 case GL_COUNT_UP_CHROMIUM:
2741 case GL_COUNT_DOWN_CHROMIUM:
2742 break;
2743 default:
2744 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2745 return false;
2746 }
2747
2748 if (!isPow2(mask + 1))
2749 {
2750 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2751 return false;
2752 }
2753
2754 return true;
2755}
2756
2757bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2758{
2759 if (!context->getExtensions().pathRendering)
2760 {
2761 context->handleError(
2762 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2763 return false;
2764 }
2765 if (context->hasPath(path) && !context->hasPathData(path))
2766 {
2767 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2768 return false;
2769 }
2770
2771 return true;
2772}
2773
2774bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2775{
2776 if (!context->getExtensions().pathRendering)
2777 {
2778 context->handleError(
2779 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2780 return false;
2781 }
2782 if (context->hasPath(path) && !context->hasPathData(path))
2783 {
2784 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2785 return false;
2786 }
2787
2788 switch (coverMode)
2789 {
2790 case GL_CONVEX_HULL_CHROMIUM:
2791 case GL_BOUNDING_BOX_CHROMIUM:
2792 break;
2793 default:
2794 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2795 return false;
2796 }
2797 return true;
2798}
2799
2800bool ValidateStencilThenCoverFillPath(Context *context,
2801 GLuint path,
2802 GLenum fillMode,
2803 GLuint mask,
2804 GLenum coverMode)
2805{
2806 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2807 ValidateCoverPath(context, path, coverMode);
2808}
2809
2810bool ValidateStencilThenCoverStrokePath(Context *context,
2811 GLuint path,
2812 GLint reference,
2813 GLuint mask,
2814 GLenum coverMode)
2815{
2816 return ValidateStencilStrokePath(context, path, reference, mask) &&
2817 ValidateCoverPath(context, path, coverMode);
2818}
2819
2820bool ValidateIsPath(Context *context)
2821{
2822 if (!context->getExtensions().pathRendering)
2823 {
2824 context->handleError(
2825 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2826 return false;
2827 }
2828 return true;
2829}
2830
Sami Väisänend59ca052016-06-21 16:10:00 +03002831bool ValidateCoverFillPathInstanced(Context *context,
2832 GLsizei numPaths,
2833 GLenum pathNameType,
2834 const void *paths,
2835 GLuint pathBase,
2836 GLenum coverMode,
2837 GLenum transformType,
2838 const GLfloat *transformValues)
2839{
2840 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2841 transformType, transformValues))
2842 return false;
2843
2844 switch (coverMode)
2845 {
2846 case GL_CONVEX_HULL_CHROMIUM:
2847 case GL_BOUNDING_BOX_CHROMIUM:
2848 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2849 break;
2850 default:
2851 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2852 return false;
2853 }
2854
2855 return true;
2856}
2857
2858bool ValidateCoverStrokePathInstanced(Context *context,
2859 GLsizei numPaths,
2860 GLenum pathNameType,
2861 const void *paths,
2862 GLuint pathBase,
2863 GLenum coverMode,
2864 GLenum transformType,
2865 const GLfloat *transformValues)
2866{
2867 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2868 transformType, transformValues))
2869 return false;
2870
2871 switch (coverMode)
2872 {
2873 case GL_CONVEX_HULL_CHROMIUM:
2874 case GL_BOUNDING_BOX_CHROMIUM:
2875 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2876 break;
2877 default:
2878 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2879 return false;
2880 }
2881
2882 return true;
2883}
2884
2885bool ValidateStencilFillPathInstanced(Context *context,
2886 GLsizei numPaths,
2887 GLenum pathNameType,
2888 const void *paths,
2889 GLuint pathBase,
2890 GLenum fillMode,
2891 GLuint mask,
2892 GLenum transformType,
2893 const GLfloat *transformValues)
2894{
2895
2896 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2897 transformType, transformValues))
2898 return false;
2899
2900 switch (fillMode)
2901 {
2902 case GL_COUNT_UP_CHROMIUM:
2903 case GL_COUNT_DOWN_CHROMIUM:
2904 break;
2905 default:
2906 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2907 return false;
2908 }
2909 if (!isPow2(mask + 1))
2910 {
2911 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2912 return false;
2913 }
2914 return true;
2915}
2916
2917bool ValidateStencilStrokePathInstanced(Context *context,
2918 GLsizei numPaths,
2919 GLenum pathNameType,
2920 const void *paths,
2921 GLuint pathBase,
2922 GLint reference,
2923 GLuint mask,
2924 GLenum transformType,
2925 const GLfloat *transformValues)
2926{
2927 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2928 transformType, transformValues))
2929 return false;
2930
2931 // no more validation here.
2932
2933 return true;
2934}
2935
2936bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2937 GLsizei numPaths,
2938 GLenum pathNameType,
2939 const void *paths,
2940 GLuint pathBase,
2941 GLenum fillMode,
2942 GLuint mask,
2943 GLenum coverMode,
2944 GLenum transformType,
2945 const GLfloat *transformValues)
2946{
2947 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2948 transformType, transformValues))
2949 return false;
2950
2951 switch (coverMode)
2952 {
2953 case GL_CONVEX_HULL_CHROMIUM:
2954 case GL_BOUNDING_BOX_CHROMIUM:
2955 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2956 break;
2957 default:
2958 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2959 return false;
2960 }
2961
2962 switch (fillMode)
2963 {
2964 case GL_COUNT_UP_CHROMIUM:
2965 case GL_COUNT_DOWN_CHROMIUM:
2966 break;
2967 default:
2968 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2969 return false;
2970 }
2971 if (!isPow2(mask + 1))
2972 {
2973 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2974 return false;
2975 }
2976
2977 return true;
2978}
2979
2980bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2981 GLsizei numPaths,
2982 GLenum pathNameType,
2983 const void *paths,
2984 GLuint pathBase,
2985 GLint reference,
2986 GLuint mask,
2987 GLenum coverMode,
2988 GLenum transformType,
2989 const GLfloat *transformValues)
2990{
2991 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2992 transformType, transformValues))
2993 return false;
2994
2995 switch (coverMode)
2996 {
2997 case GL_CONVEX_HULL_CHROMIUM:
2998 case GL_BOUNDING_BOX_CHROMIUM:
2999 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3000 break;
3001 default:
3002 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3003 return false;
3004 }
3005
3006 return true;
3007}
3008
Sami Väisänen46eaa942016-06-29 10:26:37 +03003009bool ValidateBindFragmentInputLocation(Context *context,
3010 GLuint program,
3011 GLint location,
3012 const GLchar *name)
3013{
3014 if (!context->getExtensions().pathRendering)
3015 {
3016 context->handleError(
3017 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3018 return false;
3019 }
3020
3021 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3022 if (location >= MaxLocation)
3023 {
3024 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3025 return false;
3026 }
3027
3028 const auto *programObject = context->getProgram(program);
3029 if (!programObject)
3030 {
3031 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3032 return false;
3033 }
3034
3035 if (!name)
3036 {
3037 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3038 return false;
3039 }
3040
3041 if (angle::BeginsWith(name, "gl_"))
3042 {
3043 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3044 return false;
3045 }
3046
3047 return true;
3048}
3049
3050bool ValidateProgramPathFragmentInputGen(Context *context,
3051 GLuint program,
3052 GLint location,
3053 GLenum genMode,
3054 GLint components,
3055 const GLfloat *coeffs)
3056{
3057 if (!context->getExtensions().pathRendering)
3058 {
3059 context->handleError(
3060 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3061 return false;
3062 }
3063
3064 const auto *programObject = context->getProgram(program);
3065 if (!programObject || programObject->isFlaggedForDeletion())
3066 {
3067 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3068 return false;
3069 }
3070
3071 if (!programObject->isLinked())
3072 {
3073 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3074 return false;
3075 }
3076
3077 switch (genMode)
3078 {
3079 case GL_NONE:
3080 if (components != 0)
3081 {
3082 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3083 return false;
3084 }
3085 break;
3086
3087 case GL_OBJECT_LINEAR_CHROMIUM:
3088 case GL_EYE_LINEAR_CHROMIUM:
3089 case GL_CONSTANT_CHROMIUM:
3090 if (components < 1 || components > 4)
3091 {
3092 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3093 return false;
3094 }
3095 if (!coeffs)
3096 {
3097 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3098 return false;
3099 }
3100 break;
3101
3102 default:
3103 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3104 return false;
3105 }
3106
3107 // If the location is -1 then the command is silently ignored
3108 // and no further validation is needed.
3109 if (location == -1)
3110 return true;
3111
3112 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3113
3114 if (!binding.valid)
3115 {
3116 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3117 return false;
3118 }
3119
3120 if (binding.type != GL_NONE)
3121 {
3122 GLint expectedComponents = 0;
3123 switch (binding.type)
3124 {
3125 case GL_FLOAT:
3126 expectedComponents = 1;
3127 break;
3128 case GL_FLOAT_VEC2:
3129 expectedComponents = 2;
3130 break;
3131 case GL_FLOAT_VEC3:
3132 expectedComponents = 3;
3133 break;
3134 case GL_FLOAT_VEC4:
3135 expectedComponents = 4;
3136 break;
3137 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003138 context->handleError(
3139 Error(GL_INVALID_OPERATION,
3140 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003141 return false;
3142 }
3143 if (expectedComponents != components && genMode != GL_NONE)
3144 {
3145 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3146 return false;
3147 }
3148 }
3149 return true;
3150}
3151
Geoff Lang97073d12016-04-20 10:42:34 -07003152bool ValidateCopyTextureCHROMIUM(Context *context,
3153 GLuint sourceId,
3154 GLuint destId,
3155 GLint internalFormat,
3156 GLenum destType,
3157 GLboolean unpackFlipY,
3158 GLboolean unpackPremultiplyAlpha,
3159 GLboolean unpackUnmultiplyAlpha)
3160{
3161 if (!context->getExtensions().copyTexture)
3162 {
3163 context->handleError(
3164 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3165 return false;
3166 }
3167
3168 const gl::Texture *source = context->getTexture(sourceId);
3169 if (source == nullptr)
3170 {
3171 context->handleError(
3172 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3173 return false;
3174 }
3175
3176 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3177 {
3178 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3179 return false;
3180 }
3181
3182 GLenum sourceTarget = source->getTarget();
3183 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3184 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3185 {
3186 context->handleError(
3187 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3188 return false;
3189 }
3190
3191 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3192 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3193 {
3194 context->handleError(
3195 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3196 return false;
3197 }
3198
3199 const gl::Texture *dest = context->getTexture(destId);
3200 if (dest == nullptr)
3201 {
3202 context->handleError(
3203 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3204 return false;
3205 }
3206
3207 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3208 {
3209 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3210 return false;
3211 }
3212
3213 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3214 {
3215 context->handleError(
3216 Error(GL_INVALID_OPERATION,
3217 "Destination internal format and type combination is not valid."));
3218 return false;
3219 }
3220
3221 if (dest->getImmutableFormat())
3222 {
3223 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3224 return false;
3225 }
3226
3227 return true;
3228}
3229
3230bool ValidateCopySubTextureCHROMIUM(Context *context,
3231 GLuint sourceId,
3232 GLuint destId,
3233 GLint xoffset,
3234 GLint yoffset,
3235 GLint x,
3236 GLint y,
3237 GLsizei width,
3238 GLsizei height,
3239 GLboolean unpackFlipY,
3240 GLboolean unpackPremultiplyAlpha,
3241 GLboolean unpackUnmultiplyAlpha)
3242{
3243 if (!context->getExtensions().copyTexture)
3244 {
3245 context->handleError(
3246 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3247 return false;
3248 }
3249
3250 const gl::Texture *source = context->getTexture(sourceId);
3251 if (source == nullptr)
3252 {
3253 context->handleError(
3254 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3255 return false;
3256 }
3257
3258 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3259 {
3260 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3261 return false;
3262 }
3263
3264 GLenum sourceTarget = source->getTarget();
3265 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3266 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3267 {
3268 context->handleError(
3269 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3270 return false;
3271 }
3272
3273 if (x < 0 || y < 0)
3274 {
3275 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3276 return false;
3277 }
3278
3279 if (width < 0 || height < 0)
3280 {
3281 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3282 return false;
3283 }
3284
3285 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3286 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3287 {
3288 context->handleError(
3289 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3290 return false;
3291 }
3292
3293 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3294 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3295 {
3296 context->handleError(
3297 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3298 return false;
3299 }
3300
3301 const gl::Texture *dest = context->getTexture(destId);
3302 if (dest == nullptr)
3303 {
3304 context->handleError(
3305 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3306 return false;
3307 }
3308
3309 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3310 {
3311 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3312 return false;
3313 }
3314
3315 GLenum destTarget = dest->getTarget();
3316 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3317 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3318 {
3319 context->handleError(
3320 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3321 return false;
3322 }
3323
3324 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3325 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3326 {
3327 context->handleError(
3328 Error(GL_INVALID_OPERATION,
3329 "Destination internal format and type combination is not valid."));
3330 return false;
3331 }
3332
3333 if (xoffset < 0 || yoffset < 0)
3334 {
3335 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3336 return false;
3337 }
3338
3339 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3340 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3341 {
3342 context->handleError(
3343 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3344 return false;
3345 }
3346
3347 return true;
3348}
3349
Geoff Lang47110bf2016-04-20 11:13:22 -07003350bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3351{
3352 if (!context->getExtensions().copyCompressedTexture)
3353 {
3354 context->handleError(Error(GL_INVALID_OPERATION,
3355 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3356 return false;
3357 }
3358
3359 const gl::Texture *source = context->getTexture(sourceId);
3360 if (source == nullptr)
3361 {
3362 context->handleError(
3363 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3364 return false;
3365 }
3366
3367 if (source->getTarget() != GL_TEXTURE_2D)
3368 {
3369 context->handleError(
3370 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3371 return false;
3372 }
3373
3374 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3375 {
3376 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3377 return false;
3378 }
3379
3380 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3381 if (!sourceFormat.info->compressed)
3382 {
3383 context->handleError(
3384 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3385 return false;
3386 }
3387
3388 const gl::Texture *dest = context->getTexture(destId);
3389 if (dest == nullptr)
3390 {
3391 context->handleError(
3392 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3393 return false;
3394 }
3395
3396 if (dest->getTarget() != GL_TEXTURE_2D)
3397 {
3398 context->handleError(
3399 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3400 return false;
3401 }
3402
3403 if (dest->getImmutableFormat())
3404 {
3405 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3406 return false;
3407 }
3408
3409 return true;
3410}
3411
Martin Radev4c4c8e72016-08-04 12:25:34 +03003412bool ValidateCreateShader(Context *context, GLenum type)
3413{
3414 switch (type)
3415 {
3416 case GL_VERTEX_SHADER:
3417 case GL_FRAGMENT_SHADER:
3418 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003419
Martin Radev4c4c8e72016-08-04 12:25:34 +03003420 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003421 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003422 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003423 context->handleError(
3424 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3425 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003426 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003427 break;
3428
Martin Radev4c4c8e72016-08-04 12:25:34 +03003429 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003430 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003431 return false;
3432 }
Jamie Madill29639852016-09-02 15:00:09 -04003433
3434 return true;
3435}
3436
3437bool ValidateBufferData(ValidationContext *context,
3438 GLenum target,
3439 GLsizeiptr size,
3440 const GLvoid *data,
3441 GLenum usage)
3442{
3443 if (size < 0)
3444 {
3445 context->handleError(Error(GL_INVALID_VALUE));
3446 return false;
3447 }
3448
3449 switch (usage)
3450 {
3451 case GL_STREAM_DRAW:
3452 case GL_STATIC_DRAW:
3453 case GL_DYNAMIC_DRAW:
3454 break;
3455
3456 case GL_STREAM_READ:
3457 case GL_STREAM_COPY:
3458 case GL_STATIC_READ:
3459 case GL_STATIC_COPY:
3460 case GL_DYNAMIC_READ:
3461 case GL_DYNAMIC_COPY:
3462 if (context->getClientMajorVersion() < 3)
3463 {
3464 context->handleError(Error(GL_INVALID_ENUM));
3465 return false;
3466 }
3467 break;
3468
3469 default:
3470 context->handleError(Error(GL_INVALID_ENUM));
3471 return false;
3472 }
3473
3474 if (!ValidBufferTarget(context, target))
3475 {
3476 context->handleError(Error(GL_INVALID_ENUM));
3477 return false;
3478 }
3479
3480 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3481
3482 if (!buffer)
3483 {
3484 context->handleError(Error(GL_INVALID_OPERATION));
3485 return false;
3486 }
3487
3488 return true;
3489}
3490
3491bool ValidateBufferSubData(ValidationContext *context,
3492 GLenum target,
3493 GLintptr offset,
3494 GLsizeiptr size,
3495 const GLvoid *data)
3496{
3497 if (size < 0 || offset < 0)
3498 {
3499 context->handleError(Error(GL_INVALID_VALUE));
3500 return false;
3501 }
3502
3503 if (!ValidBufferTarget(context, target))
3504 {
3505 context->handleError(Error(GL_INVALID_ENUM));
3506 return false;
3507 }
3508
3509 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3510
3511 if (!buffer)
3512 {
3513 context->handleError(Error(GL_INVALID_OPERATION));
3514 return false;
3515 }
3516
3517 if (buffer->isMapped())
3518 {
3519 context->handleError(Error(GL_INVALID_OPERATION));
3520 return false;
3521 }
3522
3523 // Check for possible overflow of size + offset
3524 angle::CheckedNumeric<size_t> checkedSize(size);
3525 checkedSize += offset;
3526 if (!checkedSize.IsValid())
3527 {
3528 context->handleError(Error(GL_OUT_OF_MEMORY));
3529 return false;
3530 }
3531
3532 if (size + offset > buffer->getSize())
3533 {
3534 context->handleError(Error(GL_INVALID_VALUE));
3535 return false;
3536 }
3537
Martin Radev4c4c8e72016-08-04 12:25:34 +03003538 return true;
3539}
3540
Geoff Langc339c4e2016-11-29 10:37:36 -05003541bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003542{
Geoff Langc339c4e2016-11-29 10:37:36 -05003543 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003544 {
3545 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003546 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003547 return false;
3548 }
3549
3550 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3551 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003552 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003553 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003554 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003555 return false;
3556 }
3557
3558 return true;
3559}
3560
Jamie Madillef300b12016-10-07 15:12:09 -04003561bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3562{
3563 if (texture < GL_TEXTURE0 ||
3564 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3565 {
3566 context->handleError(Error(GL_INVALID_ENUM));
3567 return false;
3568 }
3569
3570 return true;
3571}
3572
3573bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3574{
3575 Program *programObject = GetValidProgram(context, program);
3576 if (!programObject)
3577 {
3578 return false;
3579 }
3580
3581 Shader *shaderObject = GetValidShader(context, shader);
3582 if (!shaderObject)
3583 {
3584 return false;
3585 }
3586
3587 switch (shaderObject->getType())
3588 {
3589 case GL_VERTEX_SHADER:
3590 {
3591 if (programObject->getAttachedVertexShader())
3592 {
3593 context->handleError(Error(GL_INVALID_OPERATION));
3594 return false;
3595 }
3596 break;
3597 }
3598 case GL_FRAGMENT_SHADER:
3599 {
3600 if (programObject->getAttachedFragmentShader())
3601 {
3602 context->handleError(Error(GL_INVALID_OPERATION));
3603 return false;
3604 }
3605 break;
3606 }
3607 case GL_COMPUTE_SHADER:
3608 {
3609 if (programObject->getAttachedComputeShader())
3610 {
3611 context->handleError(Error(GL_INVALID_OPERATION));
3612 return false;
3613 }
3614 break;
3615 }
3616 default:
3617 UNREACHABLE();
3618 break;
3619 }
3620
3621 return true;
3622}
3623
Jamie Madill01a80ee2016-11-07 12:06:18 -05003624bool ValidateBindAttribLocation(ValidationContext *context,
3625 GLuint program,
3626 GLuint index,
3627 const GLchar *name)
3628{
3629 if (index >= MAX_VERTEX_ATTRIBS)
3630 {
3631 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3632 return false;
3633 }
3634
3635 if (strncmp(name, "gl_", 3) == 0)
3636 {
3637 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3638 return false;
3639 }
3640
3641 return GetValidProgram(context, program) != nullptr;
3642}
3643
3644bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3645{
3646 if (!ValidBufferTarget(context, target))
3647 {
3648 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3649 return false;
3650 }
3651
3652 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3653 !context->isBufferGenerated(buffer))
3654 {
3655 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3656 return false;
3657 }
3658
3659 return true;
3660}
3661
3662bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3663{
3664 if (!ValidFramebufferTarget(target))
3665 {
3666 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3667 return false;
3668 }
3669
3670 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3671 !context->isFramebufferGenerated(framebuffer))
3672 {
3673 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3674 return false;
3675 }
3676
3677 return true;
3678}
3679
3680bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3681{
3682 if (target != GL_RENDERBUFFER)
3683 {
3684 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3685 return false;
3686 }
3687
3688 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3689 !context->isRenderbufferGenerated(renderbuffer))
3690 {
3691 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3692 return false;
3693 }
3694
3695 return true;
3696}
3697
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003698static bool ValidBlendEquationMode(GLenum mode)
3699{
3700 switch (mode)
3701 {
3702 case GL_FUNC_ADD:
3703 case GL_FUNC_SUBTRACT:
3704 case GL_FUNC_REVERSE_SUBTRACT:
3705 case GL_MIN:
3706 case GL_MAX:
3707 return true;
3708
3709 default:
3710 return false;
3711 }
3712}
3713
3714bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3715{
3716 if (!ValidBlendEquationMode(mode))
3717 {
3718 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3719 return false;
3720 }
3721
3722 return true;
3723}
3724
3725bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3726{
3727 if (!ValidBlendEquationMode(modeRGB))
3728 {
3729 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3730 return false;
3731 }
3732
3733 if (!ValidBlendEquationMode(modeAlpha))
3734 {
3735 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3736 return false;
3737 }
3738
3739 return true;
3740}
3741
3742bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3743{
3744 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3745}
3746
3747static bool ValidSrcBlendFunc(GLenum srcBlend)
3748{
3749 switch (srcBlend)
3750 {
3751 case GL_ZERO:
3752 case GL_ONE:
3753 case GL_SRC_COLOR:
3754 case GL_ONE_MINUS_SRC_COLOR:
3755 case GL_DST_COLOR:
3756 case GL_ONE_MINUS_DST_COLOR:
3757 case GL_SRC_ALPHA:
3758 case GL_ONE_MINUS_SRC_ALPHA:
3759 case GL_DST_ALPHA:
3760 case GL_ONE_MINUS_DST_ALPHA:
3761 case GL_CONSTANT_COLOR:
3762 case GL_ONE_MINUS_CONSTANT_COLOR:
3763 case GL_CONSTANT_ALPHA:
3764 case GL_ONE_MINUS_CONSTANT_ALPHA:
3765 case GL_SRC_ALPHA_SATURATE:
3766 return true;
3767
3768 default:
3769 return false;
3770 }
3771}
3772
3773static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3774{
3775 switch (dstBlend)
3776 {
3777 case GL_ZERO:
3778 case GL_ONE:
3779 case GL_SRC_COLOR:
3780 case GL_ONE_MINUS_SRC_COLOR:
3781 case GL_DST_COLOR:
3782 case GL_ONE_MINUS_DST_COLOR:
3783 case GL_SRC_ALPHA:
3784 case GL_ONE_MINUS_SRC_ALPHA:
3785 case GL_DST_ALPHA:
3786 case GL_ONE_MINUS_DST_ALPHA:
3787 case GL_CONSTANT_COLOR:
3788 case GL_ONE_MINUS_CONSTANT_COLOR:
3789 case GL_CONSTANT_ALPHA:
3790 case GL_ONE_MINUS_CONSTANT_ALPHA:
3791 return true;
3792
3793 case GL_SRC_ALPHA_SATURATE:
3794 return (contextMajorVersion >= 3);
3795
3796 default:
3797 return false;
3798 }
3799}
3800
3801bool ValidateBlendFuncSeparate(ValidationContext *context,
3802 GLenum srcRGB,
3803 GLenum dstRGB,
3804 GLenum srcAlpha,
3805 GLenum dstAlpha)
3806{
3807 if (!ValidSrcBlendFunc(srcRGB))
3808 {
3809 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3810 return false;
3811 }
3812
3813 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3814 {
3815 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3816 return false;
3817 }
3818
3819 if (!ValidSrcBlendFunc(srcAlpha))
3820 {
3821 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3822 return false;
3823 }
3824
3825 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3826 {
3827 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3828 return false;
3829 }
3830
3831 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3832 {
3833 bool constantColorUsed =
3834 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3835 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3836
3837 bool constantAlphaUsed =
3838 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3839 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3840
3841 if (constantColorUsed && constantAlphaUsed)
3842 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003843 ERR() << "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3844 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3845 "implementation.";
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003846 context->handleError(Error(GL_INVALID_OPERATION,
3847 "Simultaneous use of "
3848 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3849 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3850 "supported by this implementation."));
3851 return false;
3852 }
3853 }
3854
3855 return true;
3856}
3857
Geoff Langc339c4e2016-11-29 10:37:36 -05003858bool ValidateGetString(Context *context, GLenum name)
3859{
3860 switch (name)
3861 {
3862 case GL_VENDOR:
3863 case GL_RENDERER:
3864 case GL_VERSION:
3865 case GL_SHADING_LANGUAGE_VERSION:
3866 case GL_EXTENSIONS:
3867 break;
3868
3869 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3870 if (!context->getExtensions().requestExtension)
3871 {
3872 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3873 return false;
3874 }
3875 break;
3876
3877 default:
3878 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3879 return false;
3880 }
3881
3882 return true;
3883}
3884
Geoff Lang47c48082016-12-07 15:38:13 -05003885bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3886{
3887 if (width <= 0.0f || isNaN(width))
3888 {
3889 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3890 return false;
3891 }
3892
3893 return true;
3894}
3895
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003896bool ValidateVertexAttribPointer(ValidationContext *context,
3897 GLuint index,
3898 GLint size,
3899 GLenum type,
3900 GLboolean normalized,
3901 GLsizei stride,
3902 const GLvoid *ptr)
3903{
3904 if (index >= MAX_VERTEX_ATTRIBS)
3905 {
3906 context->handleError(Error(GL_INVALID_VALUE, "Invalid index value."));
3907 return false;
3908 }
3909
3910 if (size < 1 || size > 4)
3911 {
3912 context->handleError(Error(GL_INVALID_VALUE, "Invalide size value."));
3913 return false;
3914 }
3915
3916 switch (type)
3917 {
3918 case GL_BYTE:
3919 case GL_UNSIGNED_BYTE:
3920 case GL_SHORT:
3921 case GL_UNSIGNED_SHORT:
3922 case GL_FIXED:
3923 case GL_FLOAT:
3924 break;
3925
3926 case GL_HALF_FLOAT:
3927 case GL_INT:
3928 case GL_UNSIGNED_INT:
3929 case GL_INT_2_10_10_10_REV:
3930 case GL_UNSIGNED_INT_2_10_10_10_REV:
3931 if (context->getClientMajorVersion() < 3)
3932 {
3933 context->handleError(
3934 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
3935 return false;
3936 }
3937 break;
3938
3939 default:
3940 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
3941 return false;
3942 }
3943
3944 if (stride < 0)
3945 {
3946 context->handleError(Error(GL_INVALID_VALUE, "Invalid stride."));
3947 return false;
3948 }
3949
3950 if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
3951 {
3952 context->handleError(Error(GL_INVALID_OPERATION, "Invalid size for a sized vertex type."));
3953 return false;
3954 }
3955
3956 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3957 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3958 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3959 // and the pointer argument is not NULL.
3960 if (context->getGLState().getVertexArray()->id() != 0 &&
3961 context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
3962 {
3963 context->handleError(
3964 Error(GL_INVALID_OPERATION,
3965 "Pointer is null with a non-zero VAO bound and zero bound to GL_ARRAY_BUFFER."));
3966 return false;
3967 }
3968
3969 if (context->getExtensions().webglCompatibility)
3970 {
3971 // WebGL 1.0 [Section 6.14] Fixed point support
3972 // The WebGL API does not support the GL_FIXED data type.
3973 if (type == GL_FIXED)
3974 {
3975 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3976 return false;
3977 }
3978
3979 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
3980 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
3981 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
3982 // parameter exceeds 255.
3983 constexpr GLsizei kMaxWebGLStride = 255;
3984 if (stride > kMaxWebGLStride)
3985 {
3986 context->handleError(
3987 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
3988 return false;
3989 }
3990
3991 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
3992 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
3993 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
3994 // or an INVALID_OPERATION error is generated.
3995 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, false);
3996 size_t typeSize = GetVertexFormatTypeSize(internalType);
3997
3998 ASSERT(isPow2(typeSize) && typeSize > 0);
3999 size_t sizeMask = (typeSize - 1);
4000 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
4001 {
4002 context->handleError(
4003 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
4004 return false;
4005 }
4006
4007 if ((stride & sizeMask) != 0)
4008 {
4009 context->handleError(
4010 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
4011 return false;
4012 }
4013 }
4014
4015 return true;
4016}
4017
Frank Henigman6137ddc2017-02-10 18:55:07 -05004018bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
4019{
4020 if (context->getExtensions().webglCompatibility && zNear > zFar)
4021 {
4022 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4023 return false;
4024 }
4025
4026 return true;
4027}
4028
Jamie Madillc29968b2016-01-20 11:17:23 -05004029} // namespace gl