blob: 6ac835788b6b228be25048d87c6d729e673aeb1a [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"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27namespace gl
28{
29
Jamie Madillc29968b2016-01-20 11:17:23 -050030namespace
31{
32
33bool IsPartialBlit(gl::Context *context,
34 const FramebufferAttachment *readBuffer,
35 const FramebufferAttachment *writeBuffer,
36 GLint srcX0,
37 GLint srcY0,
38 GLint srcX1,
39 GLint srcY1,
40 GLint dstX0,
41 GLint dstY0,
42 GLint dstX1,
43 GLint dstY1)
44{
45 const Extents &writeSize = writeBuffer->getSize();
46 const Extents &readSize = readBuffer->getSize();
47
48 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
49 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
50 {
51 return true;
52 }
53
Jamie Madilldfde6ab2016-06-09 07:07:18 -070054 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050055 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050057 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
58 scissor.height < writeSize.height;
59 }
60
61 return false;
62}
63
Sami Väisänend59ca052016-06-21 16:10:00 +030064template <typename T>
65bool ValidatePathInstances(gl::Context *context,
66 GLsizei numPaths,
67 const void *paths,
68 GLuint pathBase)
69{
70 const auto *array = static_cast<const T *>(paths);
71
72 for (GLsizei i = 0; i < numPaths; ++i)
73 {
74 const GLuint pathName = array[i] + pathBase;
75 if (context->hasPath(pathName) && !context->hasPathData(pathName))
76 {
77 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
78 return false;
79 }
80 }
81 return true;
82}
83
84bool ValidateInstancedPathParameters(gl::Context *context,
85 GLsizei numPaths,
86 GLenum pathNameType,
87 const void *paths,
88 GLuint pathBase,
89 GLenum transformType,
90 const GLfloat *transformValues)
91{
92 if (!context->getExtensions().pathRendering)
93 {
94 context->handleError(
95 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
96 return false;
97 }
98
99 if (paths == nullptr)
100 {
101 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
102 return false;
103 }
104
105 if (numPaths < 0)
106 {
107 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
108 return false;
109 }
110
111 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
112 {
113 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
114 return false;
115 }
116
117 std::uint32_t pathNameTypeSize = 0;
118 std::uint32_t componentCount = 0;
119
120 switch (pathNameType)
121 {
122 case GL_UNSIGNED_BYTE:
123 pathNameTypeSize = sizeof(GLubyte);
124 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
125 return false;
126 break;
127
128 case GL_BYTE:
129 pathNameTypeSize = sizeof(GLbyte);
130 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
131 return false;
132 break;
133
134 case GL_UNSIGNED_SHORT:
135 pathNameTypeSize = sizeof(GLushort);
136 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
137 return false;
138 break;
139
140 case GL_SHORT:
141 pathNameTypeSize = sizeof(GLshort);
142 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
143 return false;
144 break;
145
146 case GL_UNSIGNED_INT:
147 pathNameTypeSize = sizeof(GLuint);
148 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
149 return false;
150 break;
151
152 case GL_INT:
153 pathNameTypeSize = sizeof(GLint);
154 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
155 return false;
156 break;
157
158 default:
159 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
160 return false;
161 }
162
163 switch (transformType)
164 {
165 case GL_NONE:
166 componentCount = 0;
167 break;
168 case GL_TRANSLATE_X_CHROMIUM:
169 case GL_TRANSLATE_Y_CHROMIUM:
170 componentCount = 1;
171 break;
172 case GL_TRANSLATE_2D_CHROMIUM:
173 componentCount = 2;
174 break;
175 case GL_TRANSLATE_3D_CHROMIUM:
176 componentCount = 3;
177 break;
178 case GL_AFFINE_2D_CHROMIUM:
179 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
180 componentCount = 6;
181 break;
182 case GL_AFFINE_3D_CHROMIUM:
183 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
184 componentCount = 12;
185 break;
186 default:
187 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
188 return false;
189 }
190 if (componentCount != 0 && transformValues == nullptr)
191 {
192 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
193 return false;
194 }
195
196 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
197 checkedSize += (numPaths * pathNameTypeSize);
198 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
199 if (!checkedSize.IsValid())
200 {
201 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
202 return false;
203 }
204
205 return true;
206}
207
Geoff Lang97073d12016-04-20 10:42:34 -0700208bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
209{
210 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
211 switch (internalFormatInfo.format)
212 {
213 case GL_ALPHA:
214 case GL_LUMINANCE:
215 case GL_LUMINANCE_ALPHA:
216 case GL_RGB:
217 case GL_RGBA:
218 return true;
219
220 case GL_RED:
221 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
222
223 case GL_BGRA_EXT:
224 return context->getExtensions().textureFormatBGRA8888;
225
226 default:
227 return false;
228 }
229}
230
231bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
232{
233 switch (internalFormat)
234 {
235 case GL_RGB:
236 case GL_RGBA:
237 break;
238
239 case GL_BGRA_EXT:
240 return context->getExtensions().textureFormatBGRA8888;
241
242 default:
243 return false;
244 }
245
246 switch (type)
247 {
248 case GL_UNSIGNED_BYTE:
249 break;
250
251 default:
252 return false;
253 }
254
255 return true;
256}
257
258bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
259{
260 switch (target)
261 {
262 case GL_TEXTURE_2D:
263 return true;
264
265 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
266 // supported
267
268 default:
269 return false;
270 }
271}
272
273bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
274{
275 if (IsValidCopyTextureDestinationTarget(context, target))
276 {
277 return true;
278 }
279
280 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
281 // supported
282
283 return false;
284}
285
Jamie Madillc29968b2016-01-20 11:17:23 -0500286} // anonymous namespace
287
Geoff Langff5b2d52016-09-07 11:32:23 -0400288bool ValidateES2TexImageParameters(Context *context,
289 GLenum target,
290 GLint level,
291 GLenum internalformat,
292 bool isCompressed,
293 bool isSubImage,
294 GLint xoffset,
295 GLint yoffset,
296 GLsizei width,
297 GLsizei height,
298 GLint border,
299 GLenum format,
300 GLenum type,
301 GLsizei imageSize,
302 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400303{
Jamie Madill6f38f822014-06-06 17:12:20 -0400304 if (!ValidTexture2DDestinationTarget(context, target))
305 {
Jamie Madill437fa652016-05-03 15:13:24 -0400306 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400307 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400308 }
309
Austin Kinross08528e12015-10-07 16:24:40 -0700310 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400311 {
Jamie Madill437fa652016-05-03 15:13:24 -0400312 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400313 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400314 }
315
He Yunchaoced53ae2016-11-29 15:00:51 +0800316 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400317 std::numeric_limits<GLsizei>::max() - yoffset < height)
318 {
Jamie Madill437fa652016-05-03 15:13:24 -0400319 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400320 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400321 }
322
Geoff Lang005df412013-10-16 14:12:50 -0400323 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 {
Jamie Madill437fa652016-05-03 15:13:24 -0400325 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 }
328
Geoff Langaae65a42014-05-26 12:43:44 -0400329 const gl::Caps &caps = context->getCaps();
330
Geoff Langa9be0dc2014-12-17 12:34:40 -0500331 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500333 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
334 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 {
Jamie Madill437fa652016-05-03 15:13:24 -0400336 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400338 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500339 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500340 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500341 {
342 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343 {
Jamie Madill437fa652016-05-03 15:13:24 -0400344 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347
Geoff Langa9be0dc2014-12-17 12:34:40 -0500348 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
349 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
350 {
Jamie Madill437fa652016-05-03 15:13:24 -0400351 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500352 return false;
353 }
354 }
355 else
356 {
Jamie Madill437fa652016-05-03 15:13:24 -0400357 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400359 }
360
He Yunchaoced53ae2016-11-29 15:00:51 +0800361 gl::Texture *texture =
362 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 if (!texture)
364 {
Jamie Madill437fa652016-05-03 15:13:24 -0400365 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
368
Geoff Langa9be0dc2014-12-17 12:34:40 -0500369 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370 {
Geoff Langc51642b2016-11-14 16:18:26 -0500371 GLenum textureFormat = texture->getFormat(target, level).asSized();
372 if (textureFormat == GL_NONE)
373 {
374 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
375 return false;
376 }
377
Geoff Langa9be0dc2014-12-17 12:34:40 -0500378 if (format != GL_NONE)
379 {
Geoff Langc51642b2016-11-14 16:18:26 -0500380 if (gl::GetSizedInternalFormat(format, type) != textureFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500381 {
Jamie Madill437fa652016-05-03 15:13:24 -0400382 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500383 return false;
384 }
385 }
386
387 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
388 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
389 {
Jamie Madill437fa652016-05-03 15:13:24 -0400390 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500391 return false;
392 }
393 }
394 else
395 {
Geoff Lang69cce582015-09-17 13:20:36 -0400396 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500397 {
Jamie Madill437fa652016-05-03 15:13:24 -0400398 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500399 return false;
400 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 }
402
403 // Verify zero border
404 if (border != 0)
405 {
Jamie Madill437fa652016-05-03 15:13:24 -0400406 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 if (isCompressed)
411 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400412 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400413 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 switch (actualInternalFormat)
415 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800416 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
417 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
418 if (!context->getExtensions().textureCompressionDXT1)
419 {
420 context->handleError(Error(GL_INVALID_ENUM));
421 return false;
422 }
423 break;
424 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
425 if (!context->getExtensions().textureCompressionDXT1)
426 {
427 context->handleError(Error(GL_INVALID_ENUM));
428 return false;
429 }
430 break;
431 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
432 if (!context->getExtensions().textureCompressionDXT5)
433 {
434 context->handleError(Error(GL_INVALID_ENUM));
435 return false;
436 }
437 break;
438 case GL_ETC1_RGB8_OES:
439 if (!context->getExtensions().compressedETC1RGB8Texture)
440 {
441 context->handleError(Error(GL_INVALID_ENUM));
442 return false;
443 }
444 break;
445 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
446 if (!context->getExtensions().lossyETCDecode)
447 {
448 context->handleError(Error(
449 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
450 return false;
451 }
452 break;
453 default:
454 context->handleError(
455 Error(GL_INVALID_ENUM,
456 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400457 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400458 }
459 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
460 {
Jamie Madill437fa652016-05-03 15:13:24 -0400461 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400462 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400463 }
464 }
465 else
466 {
467 // validate <type> by itself (used as secondary key below)
468 switch (type)
469 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800470 case GL_UNSIGNED_BYTE:
471 case GL_UNSIGNED_SHORT_5_6_5:
472 case GL_UNSIGNED_SHORT_4_4_4_4:
473 case GL_UNSIGNED_SHORT_5_5_5_1:
474 case GL_UNSIGNED_SHORT:
475 case GL_UNSIGNED_INT:
476 case GL_UNSIGNED_INT_24_8_OES:
477 case GL_HALF_FLOAT_OES:
478 case GL_FLOAT:
479 break;
480 default:
481 context->handleError(Error(GL_INVALID_ENUM));
482 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400483 }
484
485 // validate <format> + <type> combinations
486 // - invalid <format> -> sets INVALID_ENUM
487 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
488 switch (format)
489 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800490 case GL_ALPHA:
491 case GL_LUMINANCE:
492 case GL_LUMINANCE_ALPHA:
493 switch (type)
494 {
495 case GL_UNSIGNED_BYTE:
496 case GL_FLOAT:
497 case GL_HALF_FLOAT_OES:
498 break;
499 default:
500 context->handleError(Error(GL_INVALID_OPERATION));
501 return false;
502 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400503 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800504 case GL_RED:
505 case GL_RG:
506 if (!context->getExtensions().textureRG)
507 {
508 context->handleError(Error(GL_INVALID_ENUM));
509 return false;
510 }
511 switch (type)
512 {
513 case GL_UNSIGNED_BYTE:
514 case GL_FLOAT:
515 case GL_HALF_FLOAT_OES:
516 break;
517 default:
518 context->handleError(Error(GL_INVALID_OPERATION));
519 return false;
520 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400521 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800522 case GL_RGB:
523 switch (type)
524 {
525 case GL_UNSIGNED_BYTE:
526 case GL_UNSIGNED_SHORT_5_6_5:
527 case GL_FLOAT:
528 case GL_HALF_FLOAT_OES:
529 break;
530 default:
531 context->handleError(Error(GL_INVALID_OPERATION));
532 return false;
533 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400534 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800535 case GL_RGBA:
536 switch (type)
537 {
538 case GL_UNSIGNED_BYTE:
539 case GL_UNSIGNED_SHORT_4_4_4_4:
540 case GL_UNSIGNED_SHORT_5_5_5_1:
541 case GL_FLOAT:
542 case GL_HALF_FLOAT_OES:
543 break;
544 default:
545 context->handleError(Error(GL_INVALID_OPERATION));
546 return false;
547 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400548 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800549 case GL_BGRA_EXT:
550 switch (type)
551 {
552 case GL_UNSIGNED_BYTE:
553 break;
554 default:
555 context->handleError(Error(GL_INVALID_OPERATION));
556 return false;
557 }
558 break;
559 case GL_SRGB_EXT:
560 case GL_SRGB_ALPHA_EXT:
561 if (!context->getExtensions().sRGB)
562 {
563 context->handleError(Error(GL_INVALID_ENUM));
564 return false;
565 }
566 switch (type)
567 {
568 case GL_UNSIGNED_BYTE:
569 break;
570 default:
571 context->handleError(Error(GL_INVALID_OPERATION));
572 return false;
573 }
574 break;
575 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
576 // handled below
577 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
578 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
579 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
580 break;
581 case GL_DEPTH_COMPONENT:
582 switch (type)
583 {
584 case GL_UNSIGNED_SHORT:
585 case GL_UNSIGNED_INT:
586 break;
587 default:
588 context->handleError(Error(GL_INVALID_OPERATION));
589 return false;
590 }
591 break;
592 case GL_DEPTH_STENCIL_OES:
593 switch (type)
594 {
595 case GL_UNSIGNED_INT_24_8_OES:
596 break;
597 default:
598 context->handleError(Error(GL_INVALID_OPERATION));
599 return false;
600 }
601 break;
602 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400603 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400604 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400605 }
606
607 switch (format)
608 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800609 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
610 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
611 if (context->getExtensions().textureCompressionDXT1)
612 {
613 context->handleError(Error(GL_INVALID_OPERATION));
614 return false;
615 }
616 else
617 {
618 context->handleError(Error(GL_INVALID_ENUM));
619 return false;
620 }
621 break;
622 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
623 if (context->getExtensions().textureCompressionDXT3)
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_DXT5_ANGLE:
635 if (context->getExtensions().textureCompressionDXT5)
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_ETC1_RGB8_OES:
647 if (context->getExtensions().compressedETC1RGB8Texture)
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_LOSSY_DECODE_ANGLE:
659 if (context->getExtensions().lossyETCDecode)
660 {
661 context->handleError(
662 Error(GL_INVALID_OPERATION,
663 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
664 return false;
665 }
666 else
667 {
668 context->handleError(Error(
669 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
670 return false;
671 }
672 break;
673 case GL_DEPTH_COMPONENT:
674 case GL_DEPTH_STENCIL_OES:
675 if (!context->getExtensions().depthTextures)
676 {
677 context->handleError(Error(GL_INVALID_VALUE));
678 return false;
679 }
680 if (target != GL_TEXTURE_2D)
681 {
682 context->handleError(Error(GL_INVALID_OPERATION));
683 return false;
684 }
685 // OES_depth_texture supports loading depth data and multiple levels,
686 // but ANGLE_depth_texture does not
687 if (pixels != NULL || level != 0)
688 {
689 context->handleError(Error(GL_INVALID_OPERATION));
690 return false;
691 }
692 break;
693 default:
694 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400695 }
696
697 if (type == GL_FLOAT)
698 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400699 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700 {
Jamie Madill437fa652016-05-03 15:13:24 -0400701 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400702 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400703 }
704 }
705 else if (type == GL_HALF_FLOAT_OES)
706 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400707 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400708 {
Jamie Madill437fa652016-05-03 15:13:24 -0400709 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400710 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400711 }
712 }
713 }
714
Geoff Langff5b2d52016-09-07 11:32:23 -0400715 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
716 imageSize))
717 {
718 return false;
719 }
720
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400721 return true;
722}
723
Jamie Madillc29968b2016-01-20 11:17:23 -0500724bool ValidateES2CopyTexImageParameters(ValidationContext *context,
725 GLenum target,
726 GLint level,
727 GLenum internalformat,
728 bool isSubImage,
729 GLint xoffset,
730 GLint yoffset,
731 GLint x,
732 GLint y,
733 GLsizei width,
734 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400735 GLint border)
736{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500737 if (!ValidTexture2DDestinationTarget(context, target))
738 {
Jamie Madill437fa652016-05-03 15:13:24 -0400739 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500740 return false;
741 }
742
Jamie Madill0c8abca2016-07-22 20:21:26 -0400743 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400744 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400745 xoffset, yoffset, 0, x, y, width, height, border,
746 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400748 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400749 }
750
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700751 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400752 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400753 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754
755 // [OpenGL ES 2.0.24] table 3.9
756 if (isSubImage)
757 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400758 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800760 case GL_ALPHA:
761 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
762 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
763 {
764 context->handleError(Error(GL_INVALID_OPERATION));
765 return false;
766 }
767 break;
768 case GL_LUMINANCE:
769 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
770 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
771 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
772 colorbufferFormat != GL_RGBA8_OES)
773 {
774 context->handleError(Error(GL_INVALID_OPERATION));
775 return false;
776 }
777 break;
778 case GL_RED_EXT:
779 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
780 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
781 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
782 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
783 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
784 colorbufferFormat != GL_RGBA32F)
785 {
786 context->handleError(Error(GL_INVALID_OPERATION));
787 return false;
788 }
789 break;
790 case GL_RG_EXT:
791 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
792 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
793 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
794 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
795 colorbufferFormat != GL_RGBA32F)
796 {
797 context->handleError(Error(GL_INVALID_OPERATION));
798 return false;
799 }
800 break;
801 case GL_RGB:
802 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
803 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
804 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
805 colorbufferFormat != GL_RGBA32F)
806 {
807 context->handleError(Error(GL_INVALID_OPERATION));
808 return false;
809 }
810 break;
811 case GL_LUMINANCE_ALPHA:
812 case GL_RGBA:
813 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
814 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
815 {
816 context->handleError(Error(GL_INVALID_OPERATION));
817 return false;
818 }
819 break;
820 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
821 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
822 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
823 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
824 case GL_ETC1_RGB8_OES:
825 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400826 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400827 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800828 case GL_DEPTH_COMPONENT:
829 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400830 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400831 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800832 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400833 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400834 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500836
Jamie Madill0c8abca2016-07-22 20:21:26 -0400837 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500838 {
Jamie Madill437fa652016-05-03 15:13:24 -0400839 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500840 return false;
841 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 }
843 else
844 {
845 switch (internalformat)
846 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800847 case GL_ALPHA:
848 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
849 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
850 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
851 {
852 context->handleError(Error(GL_INVALID_OPERATION));
853 return false;
854 }
855 break;
856 case GL_LUMINANCE:
857 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
858 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
859 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
860 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
861 colorbufferFormat != GL_BGR5_A1_ANGLEX)
862 {
863 context->handleError(Error(GL_INVALID_OPERATION));
864 return false;
865 }
866 break;
867 case GL_RED_EXT:
868 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
869 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
870 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
871 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
872 colorbufferFormat != GL_BGR5_A1_ANGLEX)
873 {
874 context->handleError(Error(GL_INVALID_OPERATION));
875 return false;
876 }
877 break;
878 case GL_RG_EXT:
879 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
880 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
881 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
882 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
883 {
884 context->handleError(Error(GL_INVALID_OPERATION));
885 return false;
886 }
887 break;
888 case GL_RGB:
889 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
890 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
891 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
892 colorbufferFormat != GL_BGR5_A1_ANGLEX)
893 {
894 context->handleError(Error(GL_INVALID_OPERATION));
895 return false;
896 }
897 break;
898 case GL_LUMINANCE_ALPHA:
899 case GL_RGBA:
900 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
901 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
902 colorbufferFormat != GL_BGR5_A1_ANGLEX)
903 {
904 context->handleError(Error(GL_INVALID_OPERATION));
905 return false;
906 }
907 break;
908 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
909 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
910 if (context->getExtensions().textureCompressionDXT1)
911 {
912 context->handleError(Error(GL_INVALID_OPERATION));
913 return false;
914 }
915 else
916 {
917 context->handleError(Error(GL_INVALID_ENUM));
918 return false;
919 }
920 break;
921 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
922 if (context->getExtensions().textureCompressionDXT3)
923 {
924 context->handleError(Error(GL_INVALID_OPERATION));
925 return false;
926 }
927 else
928 {
929 context->handleError(Error(GL_INVALID_ENUM));
930 return false;
931 }
932 break;
933 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
934 if (context->getExtensions().textureCompressionDXT5)
935 {
936 context->handleError(Error(GL_INVALID_OPERATION));
937 return false;
938 }
939 else
940 {
941 context->handleError(Error(GL_INVALID_ENUM));
942 return false;
943 }
944 break;
945 case GL_ETC1_RGB8_OES:
946 if (context->getExtensions().compressedETC1RGB8Texture)
947 {
948 context->handleError(Error(GL_INVALID_OPERATION));
949 return false;
950 }
951 else
952 {
953 context->handleError(Error(GL_INVALID_ENUM));
954 return false;
955 }
956 break;
957 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
958 if (context->getExtensions().lossyETCDecode)
959 {
960 context->handleError(Error(GL_INVALID_OPERATION,
961 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
962 return false;
963 }
964 else
965 {
966 context->handleError(Error(
967 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
968 return false;
969 }
970 break;
971 case GL_DEPTH_COMPONENT:
972 case GL_DEPTH_COMPONENT16:
973 case GL_DEPTH_COMPONENT32_OES:
974 case GL_DEPTH_STENCIL_OES:
975 case GL_DEPTH24_STENCIL8_OES:
976 if (context->getExtensions().depthTextures)
977 {
978 context->handleError(Error(GL_INVALID_OPERATION));
979 return false;
980 }
981 else
982 {
983 context->handleError(Error(GL_INVALID_ENUM));
984 return false;
985 }
986 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400987 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 }
990 }
991
Geoff Lang784a8fd2013-09-24 12:33:16 -0400992 // If width or height is zero, it is a no-op. Return false without setting an error.
993 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400994}
995
He Yunchaoced53ae2016-11-29 15:00:51 +0800996bool ValidateES2TexStorageParameters(Context *context,
997 GLenum target,
998 GLsizei levels,
999 GLenum internalformat,
1000 GLsizei width,
1001 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002{
1003 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1004 {
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 if (width < 1 || height < 1 || levels < 1)
1010 {
Jamie Madill437fa652016-05-03 15:13:24 -04001011 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 }
1014
1015 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1016 {
Jamie Madill437fa652016-05-03 15:13:24 -04001017 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
1021 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1022 {
Jamie Madill437fa652016-05-03 15:13:24 -04001023 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026
Geoff Lang5d601382014-07-22 15:14:06 -04001027 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1028 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 {
Jamie Madill437fa652016-05-03 15:13:24 -04001030 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 }
1033
Geoff Langaae65a42014-05-26 12:43:44 -04001034 const gl::Caps &caps = context->getCaps();
1035
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 switch (target)
1037 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 case GL_TEXTURE_2D:
1039 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1040 static_cast<GLuint>(height) > caps.max2DTextureSize)
1041 {
1042 context->handleError(Error(GL_INVALID_VALUE));
1043 return false;
1044 }
1045 break;
1046 case GL_TEXTURE_CUBE_MAP:
1047 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1048 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1049 {
1050 context->handleError(Error(GL_INVALID_VALUE));
1051 return false;
1052 }
1053 break;
1054 default:
1055 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001056 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057 }
1058
Geoff Langc0b9ef42014-07-02 10:02:37 -04001059 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 {
1061 if (!gl::isPow2(width) || !gl::isPow2(height))
1062 {
Jamie Madill437fa652016-05-03 15:13:24 -04001063 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066 }
1067
1068 switch (internalformat)
1069 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001070 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1071 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1072 if (!context->getExtensions().textureCompressionDXT1)
1073 {
1074 context->handleError(Error(GL_INVALID_ENUM));
1075 return false;
1076 }
1077 break;
1078 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1079 if (!context->getExtensions().textureCompressionDXT3)
1080 {
1081 context->handleError(Error(GL_INVALID_ENUM));
1082 return false;
1083 }
1084 break;
1085 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1086 if (!context->getExtensions().textureCompressionDXT5)
1087 {
1088 context->handleError(Error(GL_INVALID_ENUM));
1089 return false;
1090 }
1091 break;
1092 case GL_ETC1_RGB8_OES:
1093 if (!context->getExtensions().compressedETC1RGB8Texture)
1094 {
1095 context->handleError(Error(GL_INVALID_ENUM));
1096 return false;
1097 }
1098 break;
1099 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1100 if (!context->getExtensions().lossyETCDecode)
1101 {
1102 context->handleError(
1103 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1104 return false;
1105 }
1106 break;
1107 case GL_RGBA32F_EXT:
1108 case GL_RGB32F_EXT:
1109 case GL_ALPHA32F_EXT:
1110 case GL_LUMINANCE32F_EXT:
1111 case GL_LUMINANCE_ALPHA32F_EXT:
1112 if (!context->getExtensions().textureFloat)
1113 {
1114 context->handleError(Error(GL_INVALID_ENUM));
1115 return false;
1116 }
1117 break;
1118 case GL_RGBA16F_EXT:
1119 case GL_RGB16F_EXT:
1120 case GL_ALPHA16F_EXT:
1121 case GL_LUMINANCE16F_EXT:
1122 case GL_LUMINANCE_ALPHA16F_EXT:
1123 if (!context->getExtensions().textureHalfFloat)
1124 {
1125 context->handleError(Error(GL_INVALID_ENUM));
1126 return false;
1127 }
1128 break;
1129 case GL_R8_EXT:
1130 case GL_RG8_EXT:
1131 case GL_R16F_EXT:
1132 case GL_RG16F_EXT:
1133 case GL_R32F_EXT:
1134 case GL_RG32F_EXT:
1135 if (!context->getExtensions().textureRG)
1136 {
1137 context->handleError(Error(GL_INVALID_ENUM));
1138 return false;
1139 }
1140 break;
1141 case GL_DEPTH_COMPONENT16:
1142 case GL_DEPTH_COMPONENT32_OES:
1143 case GL_DEPTH24_STENCIL8_OES:
1144 if (!context->getExtensions().depthTextures)
1145 {
1146 context->handleError(Error(GL_INVALID_ENUM));
1147 return false;
1148 }
1149 if (target != GL_TEXTURE_2D)
1150 {
1151 context->handleError(Error(GL_INVALID_OPERATION));
1152 return false;
1153 }
1154 // ANGLE_depth_texture only supports 1-level textures
1155 if (levels != 1)
1156 {
1157 context->handleError(Error(GL_INVALID_OPERATION));
1158 return false;
1159 }
1160 break;
1161 default:
1162 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 }
1164
Geoff Lang691e58c2014-12-19 17:03:25 -05001165 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001166 if (!texture || texture->id() == 0)
1167 {
Jamie Madill437fa652016-05-03 15:13:24 -04001168 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001169 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 }
1171
Geoff Lang69cce582015-09-17 13:20:36 -04001172 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 {
Jamie Madill437fa652016-05-03 15:13:24 -04001174 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 }
1177
1178 return true;
1179}
1180
He Yunchaoced53ae2016-11-29 15:00:51 +08001181bool ValidateDiscardFramebufferEXT(Context *context,
1182 GLenum target,
1183 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001184 const GLenum *attachments)
1185{
Jamie Madillc29968b2016-01-20 11:17:23 -05001186 if (!context->getExtensions().discardFramebuffer)
1187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001189 return false;
1190 }
1191
Austin Kinross08332632015-05-05 13:35:47 -07001192 bool defaultFramebuffer = false;
1193
1194 switch (target)
1195 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001196 case GL_FRAMEBUFFER:
1197 defaultFramebuffer =
1198 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1199 break;
1200 default:
1201 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1202 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001203 }
1204
He Yunchaoced53ae2016-11-29 15:00:51 +08001205 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1206 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001207}
1208
Austin Kinrossbc781f32015-10-26 09:27:38 -07001209bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1210{
1211 if (!context->getExtensions().vertexArrayObject)
1212 {
Jamie Madill437fa652016-05-03 15:13:24 -04001213 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001214 return false;
1215 }
1216
1217 return ValidateBindVertexArrayBase(context, array);
1218}
1219
1220bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1221{
1222 if (!context->getExtensions().vertexArrayObject)
1223 {
Jamie Madill437fa652016-05-03 15:13:24 -04001224 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001225 return false;
1226 }
1227
Olli Etuaho41997e72016-03-10 13:38:39 +02001228 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001229}
1230
1231bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1232{
1233 if (!context->getExtensions().vertexArrayObject)
1234 {
Jamie Madill437fa652016-05-03 15:13:24 -04001235 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001236 return false;
1237 }
1238
Olli Etuaho41997e72016-03-10 13:38:39 +02001239 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001240}
1241
1242bool ValidateIsVertexArrayOES(Context *context)
1243{
1244 if (!context->getExtensions().vertexArrayObject)
1245 {
Jamie Madill437fa652016-05-03 15:13:24 -04001246 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001247 return false;
1248 }
1249
1250 return true;
1251}
Geoff Langc5629752015-12-07 16:29:04 -05001252
1253bool ValidateProgramBinaryOES(Context *context,
1254 GLuint program,
1255 GLenum binaryFormat,
1256 const void *binary,
1257 GLint length)
1258{
1259 if (!context->getExtensions().getProgramBinary)
1260 {
Jamie Madill437fa652016-05-03 15:13:24 -04001261 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001262 return false;
1263 }
1264
1265 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1266}
1267
1268bool ValidateGetProgramBinaryOES(Context *context,
1269 GLuint program,
1270 GLsizei bufSize,
1271 GLsizei *length,
1272 GLenum *binaryFormat,
1273 void *binary)
1274{
1275 if (!context->getExtensions().getProgramBinary)
1276 {
Jamie Madill437fa652016-05-03 15:13:24 -04001277 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001278 return false;
1279 }
1280
1281 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1282}
Geoff Lange102fee2015-12-10 11:23:30 -05001283
Geoff Lang70d0f492015-12-10 17:45:46 -05001284static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1285{
1286 switch (source)
1287 {
1288 case GL_DEBUG_SOURCE_API:
1289 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1290 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1291 case GL_DEBUG_SOURCE_OTHER:
1292 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1293 return !mustBeThirdPartyOrApplication;
1294
1295 case GL_DEBUG_SOURCE_THIRD_PARTY:
1296 case GL_DEBUG_SOURCE_APPLICATION:
1297 return true;
1298
1299 default:
1300 return false;
1301 }
1302}
1303
1304static bool ValidDebugType(GLenum type)
1305{
1306 switch (type)
1307 {
1308 case GL_DEBUG_TYPE_ERROR:
1309 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1310 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1311 case GL_DEBUG_TYPE_PERFORMANCE:
1312 case GL_DEBUG_TYPE_PORTABILITY:
1313 case GL_DEBUG_TYPE_OTHER:
1314 case GL_DEBUG_TYPE_MARKER:
1315 case GL_DEBUG_TYPE_PUSH_GROUP:
1316 case GL_DEBUG_TYPE_POP_GROUP:
1317 return true;
1318
1319 default:
1320 return false;
1321 }
1322}
1323
1324static bool ValidDebugSeverity(GLenum severity)
1325{
1326 switch (severity)
1327 {
1328 case GL_DEBUG_SEVERITY_HIGH:
1329 case GL_DEBUG_SEVERITY_MEDIUM:
1330 case GL_DEBUG_SEVERITY_LOW:
1331 case GL_DEBUG_SEVERITY_NOTIFICATION:
1332 return true;
1333
1334 default:
1335 return false;
1336 }
1337}
1338
Geoff Lange102fee2015-12-10 11:23:30 -05001339bool ValidateDebugMessageControlKHR(Context *context,
1340 GLenum source,
1341 GLenum type,
1342 GLenum severity,
1343 GLsizei count,
1344 const GLuint *ids,
1345 GLboolean enabled)
1346{
1347 if (!context->getExtensions().debug)
1348 {
Jamie Madill437fa652016-05-03 15:13:24 -04001349 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001350 return false;
1351 }
1352
Geoff Lang70d0f492015-12-10 17:45:46 -05001353 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1354 {
Jamie Madill437fa652016-05-03 15:13:24 -04001355 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001356 return false;
1357 }
1358
1359 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001362 return false;
1363 }
1364
1365 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001368 return false;
1369 }
1370
1371 if (count > 0)
1372 {
1373 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1374 {
Jamie Madill437fa652016-05-03 15:13:24 -04001375 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001376 GL_INVALID_OPERATION,
1377 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1378 return false;
1379 }
1380
1381 if (severity != GL_DONT_CARE)
1382 {
Jamie Madill437fa652016-05-03 15:13:24 -04001383 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001384 Error(GL_INVALID_OPERATION,
1385 "If count is greater than zero, severity must be GL_DONT_CARE."));
1386 return false;
1387 }
1388 }
1389
Geoff Lange102fee2015-12-10 11:23:30 -05001390 return true;
1391}
1392
1393bool ValidateDebugMessageInsertKHR(Context *context,
1394 GLenum source,
1395 GLenum type,
1396 GLuint id,
1397 GLenum severity,
1398 GLsizei length,
1399 const GLchar *buf)
1400{
1401 if (!context->getExtensions().debug)
1402 {
Jamie Madill437fa652016-05-03 15:13:24 -04001403 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001404 return false;
1405 }
1406
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001407 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001408 {
1409 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1410 // not generate an error.
1411 return false;
1412 }
1413
1414 if (!ValidDebugSeverity(severity))
1415 {
Jamie Madill437fa652016-05-03 15:13:24 -04001416 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001417 return false;
1418 }
1419
1420 if (!ValidDebugType(type))
1421 {
Jamie Madill437fa652016-05-03 15:13:24 -04001422 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001423 return false;
1424 }
1425
1426 if (!ValidDebugSource(source, true))
1427 {
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001429 return false;
1430 }
1431
1432 size_t messageLength = (length < 0) ? strlen(buf) : length;
1433 if (messageLength > context->getExtensions().maxDebugMessageLength)
1434 {
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001436 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1437 return false;
1438 }
1439
Geoff Lange102fee2015-12-10 11:23:30 -05001440 return true;
1441}
1442
1443bool ValidateDebugMessageCallbackKHR(Context *context,
1444 GLDEBUGPROCKHR callback,
1445 const void *userParam)
1446{
1447 if (!context->getExtensions().debug)
1448 {
Jamie Madill437fa652016-05-03 15:13:24 -04001449 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001450 return false;
1451 }
1452
Geoff Lange102fee2015-12-10 11:23:30 -05001453 return true;
1454}
1455
1456bool ValidateGetDebugMessageLogKHR(Context *context,
1457 GLuint count,
1458 GLsizei bufSize,
1459 GLenum *sources,
1460 GLenum *types,
1461 GLuint *ids,
1462 GLenum *severities,
1463 GLsizei *lengths,
1464 GLchar *messageLog)
1465{
1466 if (!context->getExtensions().debug)
1467 {
Jamie Madill437fa652016-05-03 15:13:24 -04001468 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001469 return false;
1470 }
1471
Geoff Lang70d0f492015-12-10 17:45:46 -05001472 if (bufSize < 0 && messageLog != nullptr)
1473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001475 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1476 return false;
1477 }
1478
Geoff Lange102fee2015-12-10 11:23:30 -05001479 return true;
1480}
1481
1482bool ValidatePushDebugGroupKHR(Context *context,
1483 GLenum source,
1484 GLuint id,
1485 GLsizei length,
1486 const GLchar *message)
1487{
1488 if (!context->getExtensions().debug)
1489 {
Jamie Madill437fa652016-05-03 15:13:24 -04001490 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001491 return false;
1492 }
1493
Geoff Lang70d0f492015-12-10 17:45:46 -05001494 if (!ValidDebugSource(source, true))
1495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001497 return false;
1498 }
1499
1500 size_t messageLength = (length < 0) ? strlen(message) : length;
1501 if (messageLength > context->getExtensions().maxDebugMessageLength)
1502 {
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001504 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1505 return false;
1506 }
1507
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001508 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001509 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1510 {
Jamie Madill437fa652016-05-03 15:13:24 -04001511 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001512 Error(GL_STACK_OVERFLOW,
1513 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1514 return false;
1515 }
1516
Geoff Lange102fee2015-12-10 11:23:30 -05001517 return true;
1518}
1519
1520bool ValidatePopDebugGroupKHR(Context *context)
1521{
1522 if (!context->getExtensions().debug)
1523 {
Jamie Madill437fa652016-05-03 15:13:24 -04001524 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001525 return false;
1526 }
1527
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001528 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001529 if (currentStackSize <= 1)
1530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001532 return false;
1533 }
1534
1535 return true;
1536}
1537
1538static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1539{
1540 switch (identifier)
1541 {
1542 case GL_BUFFER:
1543 if (context->getBuffer(name) == nullptr)
1544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001546 return false;
1547 }
1548 return true;
1549
1550 case GL_SHADER:
1551 if (context->getShader(name) == nullptr)
1552 {
Jamie Madill437fa652016-05-03 15:13:24 -04001553 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001554 return false;
1555 }
1556 return true;
1557
1558 case GL_PROGRAM:
1559 if (context->getProgram(name) == nullptr)
1560 {
Jamie Madill437fa652016-05-03 15:13:24 -04001561 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001562 return false;
1563 }
1564 return true;
1565
1566 case GL_VERTEX_ARRAY:
1567 if (context->getVertexArray(name) == nullptr)
1568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001570 return false;
1571 }
1572 return true;
1573
1574 case GL_QUERY:
1575 if (context->getQuery(name) == nullptr)
1576 {
Jamie Madill437fa652016-05-03 15:13:24 -04001577 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001578 return false;
1579 }
1580 return true;
1581
1582 case GL_TRANSFORM_FEEDBACK:
1583 if (context->getTransformFeedback(name) == nullptr)
1584 {
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001586 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1587 return false;
1588 }
1589 return true;
1590
1591 case GL_SAMPLER:
1592 if (context->getSampler(name) == nullptr)
1593 {
Jamie Madill437fa652016-05-03 15:13:24 -04001594 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001595 return false;
1596 }
1597 return true;
1598
1599 case GL_TEXTURE:
1600 if (context->getTexture(name) == nullptr)
1601 {
Jamie Madill437fa652016-05-03 15:13:24 -04001602 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001603 return false;
1604 }
1605 return true;
1606
1607 case GL_RENDERBUFFER:
1608 if (context->getRenderbuffer(name) == nullptr)
1609 {
Jamie Madill437fa652016-05-03 15:13:24 -04001610 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001611 return false;
1612 }
1613 return true;
1614
1615 case GL_FRAMEBUFFER:
1616 if (context->getFramebuffer(name) == nullptr)
1617 {
Jamie Madill437fa652016-05-03 15:13:24 -04001618 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001619 return false;
1620 }
1621 return true;
1622
1623 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001625 return false;
1626 }
Geoff Lange102fee2015-12-10 11:23:30 -05001627}
1628
Martin Radev9d901792016-07-15 15:58:58 +03001629static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1630{
1631 size_t labelLength = 0;
1632
1633 if (length < 0)
1634 {
1635 if (label != nullptr)
1636 {
1637 labelLength = strlen(label);
1638 }
1639 }
1640 else
1641 {
1642 labelLength = static_cast<size_t>(length);
1643 }
1644
1645 if (labelLength > context->getExtensions().maxLabelLength)
1646 {
1647 context->handleError(
1648 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1649 return false;
1650 }
1651
1652 return true;
1653}
1654
Geoff Lange102fee2015-12-10 11:23:30 -05001655bool ValidateObjectLabelKHR(Context *context,
1656 GLenum identifier,
1657 GLuint name,
1658 GLsizei length,
1659 const GLchar *label)
1660{
1661 if (!context->getExtensions().debug)
1662 {
Jamie Madill437fa652016-05-03 15:13:24 -04001663 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001664 return false;
1665 }
1666
Geoff Lang70d0f492015-12-10 17:45:46 -05001667 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1668 {
1669 return false;
1670 }
1671
Martin Radev9d901792016-07-15 15:58:58 +03001672 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001673 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001674 return false;
1675 }
1676
Geoff Lange102fee2015-12-10 11:23:30 -05001677 return true;
1678}
1679
1680bool ValidateGetObjectLabelKHR(Context *context,
1681 GLenum identifier,
1682 GLuint name,
1683 GLsizei bufSize,
1684 GLsizei *length,
1685 GLchar *label)
1686{
1687 if (!context->getExtensions().debug)
1688 {
Jamie Madill437fa652016-05-03 15:13:24 -04001689 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001690 return false;
1691 }
1692
Geoff Lang70d0f492015-12-10 17:45:46 -05001693 if (bufSize < 0)
1694 {
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001696 return false;
1697 }
1698
1699 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1700 {
1701 return false;
1702 }
1703
Martin Radev9d901792016-07-15 15:58:58 +03001704 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001705}
1706
1707static bool ValidateObjectPtrName(Context *context, const void *ptr)
1708{
1709 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001712 return false;
1713 }
1714
Geoff Lange102fee2015-12-10 11:23:30 -05001715 return true;
1716}
1717
1718bool ValidateObjectPtrLabelKHR(Context *context,
1719 const void *ptr,
1720 GLsizei length,
1721 const GLchar *label)
1722{
1723 if (!context->getExtensions().debug)
1724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001726 return false;
1727 }
1728
Geoff Lang70d0f492015-12-10 17:45:46 -05001729 if (!ValidateObjectPtrName(context, ptr))
1730 {
1731 return false;
1732 }
1733
Martin Radev9d901792016-07-15 15:58:58 +03001734 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001735 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001736 return false;
1737 }
1738
Geoff Lange102fee2015-12-10 11:23:30 -05001739 return true;
1740}
1741
1742bool ValidateGetObjectPtrLabelKHR(Context *context,
1743 const void *ptr,
1744 GLsizei bufSize,
1745 GLsizei *length,
1746 GLchar *label)
1747{
1748 if (!context->getExtensions().debug)
1749 {
Jamie Madill437fa652016-05-03 15:13:24 -04001750 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001751 return false;
1752 }
1753
Geoff Lang70d0f492015-12-10 17:45:46 -05001754 if (bufSize < 0)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001757 return false;
1758 }
1759
1760 if (!ValidateObjectPtrName(context, ptr))
1761 {
1762 return false;
1763 }
1764
Martin Radev9d901792016-07-15 15:58:58 +03001765 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001766}
1767
1768bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1769{
1770 if (!context->getExtensions().debug)
1771 {
Jamie Madill437fa652016-05-03 15:13:24 -04001772 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001773 return false;
1774 }
1775
Geoff Lang70d0f492015-12-10 17:45:46 -05001776 // TODO: represent this in Context::getQueryParameterInfo.
1777 switch (pname)
1778 {
1779 case GL_DEBUG_CALLBACK_FUNCTION:
1780 case GL_DEBUG_CALLBACK_USER_PARAM:
1781 break;
1782
1783 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001785 return false;
1786 }
1787
Geoff Lange102fee2015-12-10 11:23:30 -05001788 return true;
1789}
Jamie Madillc29968b2016-01-20 11:17:23 -05001790
1791bool ValidateBlitFramebufferANGLE(Context *context,
1792 GLint srcX0,
1793 GLint srcY0,
1794 GLint srcX1,
1795 GLint srcY1,
1796 GLint dstX0,
1797 GLint dstY0,
1798 GLint dstX1,
1799 GLint dstY1,
1800 GLbitfield mask,
1801 GLenum filter)
1802{
1803 if (!context->getExtensions().framebufferBlit)
1804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001806 return false;
1807 }
1808
1809 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1810 {
1811 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001812 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 GL_INVALID_OPERATION,
1814 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1815 return false;
1816 }
1817
1818 if (filter == GL_LINEAR)
1819 {
Jamie Madill437fa652016-05-03 15:13:24 -04001820 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001821 return false;
1822 }
1823
Jamie Madill51f40ec2016-06-15 14:06:00 -04001824 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1825 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001826
1827 if (mask & GL_COLOR_BUFFER_BIT)
1828 {
1829 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1830 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1831
1832 if (readColorAttachment && drawColorAttachment)
1833 {
1834 if (!(readColorAttachment->type() == GL_TEXTURE &&
1835 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1836 readColorAttachment->type() != GL_RENDERBUFFER &&
1837 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1838 {
Jamie Madill437fa652016-05-03 15:13:24 -04001839 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001840 return false;
1841 }
1842
Geoff Langa15472a2015-08-11 11:48:03 -04001843 for (size_t drawbufferIdx = 0;
1844 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 {
Geoff Langa15472a2015-08-11 11:48:03 -04001846 const FramebufferAttachment *attachment =
1847 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1848 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 if (!(attachment->type() == GL_TEXTURE &&
1851 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1852 attachment->type() != GL_RENDERBUFFER &&
1853 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 return false;
1857 }
1858
1859 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001860 if (!Format::SameSized(attachment->getFormat(),
1861 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return false;
1865 }
1866 }
1867 }
1868
Jamie Madill51f40ec2016-06-15 14:06:00 -04001869 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1871 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
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 }
1878
1879 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1880 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1881 for (size_t i = 0; i < 2; i++)
1882 {
1883 if (mask & masks[i])
1884 {
1885 const FramebufferAttachment *readBuffer =
1886 readFramebuffer->getAttachment(attachments[i]);
1887 const FramebufferAttachment *drawBuffer =
1888 drawFramebuffer->getAttachment(attachments[i]);
1889
1890 if (readBuffer && drawBuffer)
1891 {
1892 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1893 dstX0, dstY0, dstX1, dstY1))
1894 {
1895 // only whole-buffer copies are permitted
He Yunchaoced53ae2016-11-29 15:00:51 +08001896 ERR("Only whole-buffer depth and stencil blits are supported by this "
Jamie Madillc29968b2016-01-20 11:17:23 -05001897 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001898 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001899 return false;
1900 }
1901
1902 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001905 return false;
1906 }
1907 }
1908 }
1909 }
1910
1911 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1912 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001913}
Jamie Madillc29968b2016-01-20 11:17:23 -05001914
1915bool ValidateClear(ValidationContext *context, GLbitfield mask)
1916{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001917 auto fbo = context->getGLState().getDrawFramebuffer();
1918 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001919 {
Jamie Madill437fa652016-05-03 15:13:24 -04001920 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001921 return false;
1922 }
1923
1924 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1925 {
Jamie Madill437fa652016-05-03 15:13:24 -04001926 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001927 return false;
1928 }
1929
1930 return true;
1931}
1932
1933bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1934{
1935 if (!context->getExtensions().drawBuffers)
1936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001938 return false;
1939 }
1940
1941 return ValidateDrawBuffersBase(context, n, bufs);
1942}
1943
Jamie Madill73a84962016-02-12 09:27:23 -05001944bool ValidateTexImage2D(Context *context,
1945 GLenum target,
1946 GLint level,
1947 GLint internalformat,
1948 GLsizei width,
1949 GLsizei height,
1950 GLint border,
1951 GLenum format,
1952 GLenum type,
1953 const GLvoid *pixels)
1954{
Martin Radev1be913c2016-07-11 17:59:16 +03001955 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001956 {
1957 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001958 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001959 }
1960
Martin Radev1be913c2016-07-11 17:59:16 +03001961 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001962 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001963 0, 0, width, height, 1, border, format, type, -1,
1964 pixels);
1965}
1966
1967bool ValidateTexImage2DRobust(Context *context,
1968 GLenum target,
1969 GLint level,
1970 GLint internalformat,
1971 GLsizei width,
1972 GLsizei height,
1973 GLint border,
1974 GLenum format,
1975 GLenum type,
1976 GLsizei bufSize,
1977 const GLvoid *pixels)
1978{
1979 if (!ValidateRobustEntryPoint(context, bufSize))
1980 {
1981 return false;
1982 }
1983
1984 if (context->getClientMajorVersion() < 3)
1985 {
1986 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1987 0, 0, width, height, border, format, type, bufSize,
1988 pixels);
1989 }
1990
1991 ASSERT(context->getClientMajorVersion() >= 3);
1992 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1993 0, 0, width, height, 1, border, format, type, bufSize,
1994 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001995}
1996
1997bool ValidateTexSubImage2D(Context *context,
1998 GLenum target,
1999 GLint level,
2000 GLint xoffset,
2001 GLint yoffset,
2002 GLsizei width,
2003 GLsizei height,
2004 GLenum format,
2005 GLenum type,
2006 const GLvoid *pixels)
2007{
2008
Martin Radev1be913c2016-07-11 17:59:16 +03002009 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002010 {
2011 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002012 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002013 }
2014
Martin Radev1be913c2016-07-11 17:59:16 +03002015 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002016 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002017 yoffset, 0, width, height, 1, 0, format, type, -1,
2018 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002019}
2020
Geoff Langc52f6f12016-10-14 10:18:00 -04002021bool ValidateTexSubImage2DRobustANGLE(Context *context,
2022 GLenum target,
2023 GLint level,
2024 GLint xoffset,
2025 GLint yoffset,
2026 GLsizei width,
2027 GLsizei height,
2028 GLenum format,
2029 GLenum type,
2030 GLsizei bufSize,
2031 const GLvoid *pixels)
2032{
2033 if (!ValidateRobustEntryPoint(context, bufSize))
2034 {
2035 return false;
2036 }
2037
2038 if (context->getClientMajorVersion() < 3)
2039 {
2040 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2041 yoffset, width, height, 0, format, type, bufSize,
2042 pixels);
2043 }
2044
2045 ASSERT(context->getClientMajorVersion() >= 3);
2046 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2047 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2048 pixels);
2049}
2050
Jamie Madill73a84962016-02-12 09:27:23 -05002051bool ValidateCompressedTexImage2D(Context *context,
2052 GLenum target,
2053 GLint level,
2054 GLenum internalformat,
2055 GLsizei width,
2056 GLsizei height,
2057 GLint border,
2058 GLsizei imageSize,
2059 const GLvoid *data)
2060{
Martin Radev1be913c2016-07-11 17:59:16 +03002061 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002062 {
2063 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002064 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002065 {
2066 return false;
2067 }
2068 }
2069 else
2070 {
Martin Radev1be913c2016-07-11 17:59:16 +03002071 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002072 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002073 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002074 data))
2075 {
2076 return false;
2077 }
2078 }
2079
2080 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002081 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002082 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002083 if (blockSizeOrErr.isError())
2084 {
2085 context->handleError(blockSizeOrErr.getError());
2086 return false;
2087 }
2088
2089 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002090 {
Jamie Madill437fa652016-05-03 15:13:24 -04002091 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002092 return false;
2093 }
2094
2095 return true;
2096}
2097
2098bool ValidateCompressedTexSubImage2D(Context *context,
2099 GLenum target,
2100 GLint level,
2101 GLint xoffset,
2102 GLint yoffset,
2103 GLsizei width,
2104 GLsizei height,
2105 GLenum format,
2106 GLsizei imageSize,
2107 const GLvoid *data)
2108{
Martin Radev1be913c2016-07-11 17:59:16 +03002109 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002110 {
2111 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002112 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002113 {
2114 return false;
2115 }
2116 }
2117 else
2118 {
Martin Radev1be913c2016-07-11 17:59:16 +03002119 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002120 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002121 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002122 data))
2123 {
2124 return false;
2125 }
2126 }
2127
2128 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002129 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002130 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002131 if (blockSizeOrErr.isError())
2132 {
2133 context->handleError(blockSizeOrErr.getError());
2134 return false;
2135 }
2136
2137 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002138 {
Jamie Madill437fa652016-05-03 15:13:24 -04002139 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002140 return false;
2141 }
2142
2143 return true;
2144}
2145
Olli Etuaho4f667482016-03-30 15:56:35 +03002146bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2147{
Geoff Lang496c02d2016-10-20 11:38:11 -07002148 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002149}
2150
2151bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2152{
2153 if (!context->getExtensions().mapBuffer)
2154 {
Jamie Madill437fa652016-05-03 15:13:24 -04002155 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002156 return false;
2157 }
2158
2159 if (!ValidBufferTarget(context, target))
2160 {
Jamie Madill437fa652016-05-03 15:13:24 -04002161 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002162 return false;
2163 }
2164
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002165 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002166
2167 if (buffer == nullptr)
2168 {
Jamie Madill437fa652016-05-03 15:13:24 -04002169 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002170 return false;
2171 }
2172
2173 if (access != GL_WRITE_ONLY_OES)
2174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002176 return false;
2177 }
2178
2179 if (buffer->isMapped())
2180 {
Jamie Madill437fa652016-05-03 15:13:24 -04002181 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002182 return false;
2183 }
2184
2185 return true;
2186}
2187
2188bool ValidateUnmapBufferOES(Context *context, GLenum target)
2189{
2190 if (!context->getExtensions().mapBuffer)
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002193 return false;
2194 }
2195
2196 return ValidateUnmapBufferBase(context, target);
2197}
2198
2199bool ValidateMapBufferRangeEXT(Context *context,
2200 GLenum target,
2201 GLintptr offset,
2202 GLsizeiptr length,
2203 GLbitfield access)
2204{
2205 if (!context->getExtensions().mapBufferRange)
2206 {
Jamie Madill437fa652016-05-03 15:13:24 -04002207 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002208 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2209 return false;
2210 }
2211
2212 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2213}
2214
2215bool ValidateFlushMappedBufferRangeEXT(Context *context,
2216 GLenum target,
2217 GLintptr offset,
2218 GLsizeiptr length)
2219{
2220 if (!context->getExtensions().mapBufferRange)
2221 {
Jamie Madill437fa652016-05-03 15:13:24 -04002222 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002223 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2224 return false;
2225 }
2226
2227 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2228}
2229
Ian Ewell54f87462016-03-10 13:47:21 -05002230bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2231{
2232 Texture *textureObject = context->getTexture(texture);
2233 if (textureObject && textureObject->getTarget() != target && texture != 0)
2234 {
Jamie Madill437fa652016-05-03 15:13:24 -04002235 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002236 return false;
2237 }
2238
Geoff Langf41a7152016-09-19 15:11:17 -04002239 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2240 !context->isTextureGenerated(texture))
2241 {
2242 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2243 return false;
2244 }
2245
Ian Ewell54f87462016-03-10 13:47:21 -05002246 switch (target)
2247 {
2248 case GL_TEXTURE_2D:
2249 case GL_TEXTURE_CUBE_MAP:
2250 break;
2251
2252 case GL_TEXTURE_3D:
2253 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002254 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002255 {
Jamie Madill437fa652016-05-03 15:13:24 -04002256 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002257 return false;
2258 }
2259 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002260
2261 case GL_TEXTURE_2D_MULTISAMPLE:
2262 if (context->getClientVersion() < Version(3, 1))
2263 {
2264 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2265 return false;
2266 }
2267 UNIMPLEMENTED();
2268 break;
2269
Ian Ewell54f87462016-03-10 13:47:21 -05002270 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002271 if (!context->getExtensions().eglImageExternal &&
2272 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002273 {
Jamie Madill437fa652016-05-03 15:13:24 -04002274 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002275 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2276 return false;
2277 }
2278 break;
2279 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002281 return false;
2282 }
2283
2284 return true;
2285}
2286
Geoff Langd8605522016-04-13 10:19:12 -04002287bool ValidateBindUniformLocationCHROMIUM(Context *context,
2288 GLuint program,
2289 GLint location,
2290 const GLchar *name)
2291{
2292 if (!context->getExtensions().bindUniformLocation)
2293 {
Jamie Madill437fa652016-05-03 15:13:24 -04002294 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002295 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2296 return false;
2297 }
2298
2299 Program *programObject = GetValidProgram(context, program);
2300 if (!programObject)
2301 {
2302 return false;
2303 }
2304
2305 if (location < 0)
2306 {
Jamie Madill437fa652016-05-03 15:13:24 -04002307 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002308 return false;
2309 }
2310
2311 const Caps &caps = context->getCaps();
2312 if (static_cast<size_t>(location) >=
2313 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2314 {
Jamie Madill437fa652016-05-03 15:13:24 -04002315 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002316 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2317 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2318 return false;
2319 }
2320
2321 if (strncmp(name, "gl_", 3) == 0)
2322 {
Jamie Madill437fa652016-05-03 15:13:24 -04002323 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002324 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2325 return false;
2326 }
2327
2328 return true;
2329}
2330
Jamie Madille2e406c2016-06-02 13:04:10 -04002331bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002332{
2333 if (!context->getExtensions().framebufferMixedSamples)
2334 {
2335 context->handleError(
2336 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2337 return false;
2338 }
2339 switch (components)
2340 {
2341 case GL_RGB:
2342 case GL_RGBA:
2343 case GL_ALPHA:
2344 case GL_NONE:
2345 break;
2346 default:
2347 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002348 Error(GL_INVALID_ENUM,
2349 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002350 return false;
2351 }
2352
2353 return true;
2354}
2355
Sami Väisänene45e53b2016-05-25 10:36:04 +03002356// CHROMIUM_path_rendering
2357
2358bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2359{
2360 if (!context->getExtensions().pathRendering)
2361 {
2362 context->handleError(
2363 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2364 return false;
2365 }
2366 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2367 {
2368 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2369 return false;
2370 }
2371 if (matrix == nullptr)
2372 {
2373 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2374 return false;
2375 }
2376 return true;
2377}
2378
2379bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2380{
2381 if (!context->getExtensions().pathRendering)
2382 {
2383 context->handleError(
2384 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2385 return false;
2386 }
2387 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2388 {
2389 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2390 return false;
2391 }
2392 return true;
2393}
2394
2395bool ValidateGenPaths(Context *context, GLsizei range)
2396{
2397 if (!context->getExtensions().pathRendering)
2398 {
2399 context->handleError(
2400 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2401 return false;
2402 }
2403
2404 // range = 0 is undefined in NV_path_rendering.
2405 // we add stricter semantic check here and require a non zero positive range.
2406 if (range <= 0)
2407 {
2408 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2409 return false;
2410 }
2411
2412 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2413 {
2414 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2415 return false;
2416 }
2417
2418 return true;
2419}
2420
2421bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2422{
2423 if (!context->getExtensions().pathRendering)
2424 {
2425 context->handleError(
2426 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2427 return false;
2428 }
2429
2430 // range = 0 is undefined in NV_path_rendering.
2431 // we add stricter semantic check here and require a non zero positive range.
2432 if (range <= 0)
2433 {
2434 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2435 return false;
2436 }
2437
2438 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2439 checkedRange += range;
2440
2441 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2442 {
2443 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2444 return false;
2445 }
2446 return true;
2447}
2448
2449bool ValidatePathCommands(Context *context,
2450 GLuint path,
2451 GLsizei numCommands,
2452 const GLubyte *commands,
2453 GLsizei numCoords,
2454 GLenum coordType,
2455 const void *coords)
2456{
2457 if (!context->getExtensions().pathRendering)
2458 {
2459 context->handleError(
2460 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2461 return false;
2462 }
2463 if (!context->hasPath(path))
2464 {
2465 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2466 return false;
2467 }
2468
2469 if (numCommands < 0)
2470 {
2471 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2472 return false;
2473 }
2474 else if (numCommands > 0)
2475 {
2476 if (!commands)
2477 {
2478 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2479 return false;
2480 }
2481 }
2482
2483 if (numCoords < 0)
2484 {
2485 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2486 return false;
2487 }
2488 else if (numCoords > 0)
2489 {
2490 if (!coords)
2491 {
2492 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2493 return false;
2494 }
2495 }
2496
2497 std::uint32_t coordTypeSize = 0;
2498 switch (coordType)
2499 {
2500 case GL_BYTE:
2501 coordTypeSize = sizeof(GLbyte);
2502 break;
2503
2504 case GL_UNSIGNED_BYTE:
2505 coordTypeSize = sizeof(GLubyte);
2506 break;
2507
2508 case GL_SHORT:
2509 coordTypeSize = sizeof(GLshort);
2510 break;
2511
2512 case GL_UNSIGNED_SHORT:
2513 coordTypeSize = sizeof(GLushort);
2514 break;
2515
2516 case GL_FLOAT:
2517 coordTypeSize = sizeof(GLfloat);
2518 break;
2519
2520 default:
2521 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2522 return false;
2523 }
2524
2525 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2526 checkedSize += (coordTypeSize * numCoords);
2527 if (!checkedSize.IsValid())
2528 {
2529 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2530 return false;
2531 }
2532
2533 // early return skips command data validation when it doesn't exist.
2534 if (!commands)
2535 return true;
2536
2537 GLsizei expectedNumCoords = 0;
2538 for (GLsizei i = 0; i < numCommands; ++i)
2539 {
2540 switch (commands[i])
2541 {
2542 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2543 break;
2544 case GL_MOVE_TO_CHROMIUM:
2545 case GL_LINE_TO_CHROMIUM:
2546 expectedNumCoords += 2;
2547 break;
2548 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2549 expectedNumCoords += 4;
2550 break;
2551 case GL_CUBIC_CURVE_TO_CHROMIUM:
2552 expectedNumCoords += 6;
2553 break;
2554 case GL_CONIC_CURVE_TO_CHROMIUM:
2555 expectedNumCoords += 5;
2556 break;
2557 default:
2558 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2559 return false;
2560 }
2561 }
2562 if (expectedNumCoords != numCoords)
2563 {
2564 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2565 return false;
2566 }
2567
2568 return true;
2569}
2570
2571bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2572{
2573 if (!context->getExtensions().pathRendering)
2574 {
2575 context->handleError(
2576 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2577 return false;
2578 }
2579 if (!context->hasPath(path))
2580 {
2581 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2582 return false;
2583 }
2584
2585 switch (pname)
2586 {
2587 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2588 if (value < 0.0f)
2589 {
2590 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2591 return false;
2592 }
2593 break;
2594 case GL_PATH_END_CAPS_CHROMIUM:
2595 switch (static_cast<GLenum>(value))
2596 {
2597 case GL_FLAT_CHROMIUM:
2598 case GL_SQUARE_CHROMIUM:
2599 case GL_ROUND_CHROMIUM:
2600 break;
2601 default:
2602 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2603 return false;
2604 }
2605 break;
2606 case GL_PATH_JOIN_STYLE_CHROMIUM:
2607 switch (static_cast<GLenum>(value))
2608 {
2609 case GL_MITER_REVERT_CHROMIUM:
2610 case GL_BEVEL_CHROMIUM:
2611 case GL_ROUND_CHROMIUM:
2612 break;
2613 default:
2614 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2615 return false;
2616 }
2617 case GL_PATH_MITER_LIMIT_CHROMIUM:
2618 if (value < 0.0f)
2619 {
2620 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2621 return false;
2622 }
2623 break;
2624
2625 case GL_PATH_STROKE_BOUND_CHROMIUM:
2626 // no errors, only clamping.
2627 break;
2628
2629 default:
2630 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2631 return false;
2632 }
2633 return true;
2634}
2635
2636bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2637{
2638 if (!context->getExtensions().pathRendering)
2639 {
2640 context->handleError(
2641 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2642 return false;
2643 }
2644
2645 if (!context->hasPath(path))
2646 {
2647 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2648 return false;
2649 }
2650 if (!value)
2651 {
2652 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2653 return false;
2654 }
2655
2656 switch (pname)
2657 {
2658 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2659 case GL_PATH_END_CAPS_CHROMIUM:
2660 case GL_PATH_JOIN_STYLE_CHROMIUM:
2661 case GL_PATH_MITER_LIMIT_CHROMIUM:
2662 case GL_PATH_STROKE_BOUND_CHROMIUM:
2663 break;
2664
2665 default:
2666 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2667 return false;
2668 }
2669
2670 return true;
2671}
2672
2673bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2674{
2675 if (!context->getExtensions().pathRendering)
2676 {
2677 context->handleError(
2678 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2679 return false;
2680 }
2681
2682 switch (func)
2683 {
2684 case GL_NEVER:
2685 case GL_ALWAYS:
2686 case GL_LESS:
2687 case GL_LEQUAL:
2688 case GL_EQUAL:
2689 case GL_GEQUAL:
2690 case GL_GREATER:
2691 case GL_NOTEQUAL:
2692 break;
2693 default:
2694 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2695 return false;
2696 }
2697
2698 return true;
2699}
2700
2701// Note that the spec specifies that for the path drawing commands
2702// if the path object is not an existing path object the command
2703// does nothing and no error is generated.
2704// However if the path object exists but has not been specified any
2705// commands then an error is generated.
2706
2707bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2708{
2709 if (!context->getExtensions().pathRendering)
2710 {
2711 context->handleError(
2712 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2713 return false;
2714 }
2715 if (context->hasPath(path) && !context->hasPathData(path))
2716 {
2717 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2718 return false;
2719 }
2720
2721 switch (fillMode)
2722 {
2723 case GL_COUNT_UP_CHROMIUM:
2724 case GL_COUNT_DOWN_CHROMIUM:
2725 break;
2726 default:
2727 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2728 return false;
2729 }
2730
2731 if (!isPow2(mask + 1))
2732 {
2733 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2734 return false;
2735 }
2736
2737 return true;
2738}
2739
2740bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2741{
2742 if (!context->getExtensions().pathRendering)
2743 {
2744 context->handleError(
2745 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2746 return false;
2747 }
2748 if (context->hasPath(path) && !context->hasPathData(path))
2749 {
2750 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2751 return false;
2752 }
2753
2754 return true;
2755}
2756
2757bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
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 object."));
2768 return false;
2769 }
2770
2771 switch (coverMode)
2772 {
2773 case GL_CONVEX_HULL_CHROMIUM:
2774 case GL_BOUNDING_BOX_CHROMIUM:
2775 break;
2776 default:
2777 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2778 return false;
2779 }
2780 return true;
2781}
2782
2783bool ValidateStencilThenCoverFillPath(Context *context,
2784 GLuint path,
2785 GLenum fillMode,
2786 GLuint mask,
2787 GLenum coverMode)
2788{
2789 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2790 ValidateCoverPath(context, path, coverMode);
2791}
2792
2793bool ValidateStencilThenCoverStrokePath(Context *context,
2794 GLuint path,
2795 GLint reference,
2796 GLuint mask,
2797 GLenum coverMode)
2798{
2799 return ValidateStencilStrokePath(context, path, reference, mask) &&
2800 ValidateCoverPath(context, path, coverMode);
2801}
2802
2803bool ValidateIsPath(Context *context)
2804{
2805 if (!context->getExtensions().pathRendering)
2806 {
2807 context->handleError(
2808 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2809 return false;
2810 }
2811 return true;
2812}
2813
Sami Väisänend59ca052016-06-21 16:10:00 +03002814bool ValidateCoverFillPathInstanced(Context *context,
2815 GLsizei numPaths,
2816 GLenum pathNameType,
2817 const void *paths,
2818 GLuint pathBase,
2819 GLenum coverMode,
2820 GLenum transformType,
2821 const GLfloat *transformValues)
2822{
2823 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2824 transformType, transformValues))
2825 return false;
2826
2827 switch (coverMode)
2828 {
2829 case GL_CONVEX_HULL_CHROMIUM:
2830 case GL_BOUNDING_BOX_CHROMIUM:
2831 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2832 break;
2833 default:
2834 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2835 return false;
2836 }
2837
2838 return true;
2839}
2840
2841bool ValidateCoverStrokePathInstanced(Context *context,
2842 GLsizei numPaths,
2843 GLenum pathNameType,
2844 const void *paths,
2845 GLuint pathBase,
2846 GLenum coverMode,
2847 GLenum transformType,
2848 const GLfloat *transformValues)
2849{
2850 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2851 transformType, transformValues))
2852 return false;
2853
2854 switch (coverMode)
2855 {
2856 case GL_CONVEX_HULL_CHROMIUM:
2857 case GL_BOUNDING_BOX_CHROMIUM:
2858 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2859 break;
2860 default:
2861 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2862 return false;
2863 }
2864
2865 return true;
2866}
2867
2868bool ValidateStencilFillPathInstanced(Context *context,
2869 GLsizei numPaths,
2870 GLenum pathNameType,
2871 const void *paths,
2872 GLuint pathBase,
2873 GLenum fillMode,
2874 GLuint mask,
2875 GLenum transformType,
2876 const GLfloat *transformValues)
2877{
2878
2879 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2880 transformType, transformValues))
2881 return false;
2882
2883 switch (fillMode)
2884 {
2885 case GL_COUNT_UP_CHROMIUM:
2886 case GL_COUNT_DOWN_CHROMIUM:
2887 break;
2888 default:
2889 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2890 return false;
2891 }
2892 if (!isPow2(mask + 1))
2893 {
2894 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2895 return false;
2896 }
2897 return true;
2898}
2899
2900bool ValidateStencilStrokePathInstanced(Context *context,
2901 GLsizei numPaths,
2902 GLenum pathNameType,
2903 const void *paths,
2904 GLuint pathBase,
2905 GLint reference,
2906 GLuint mask,
2907 GLenum transformType,
2908 const GLfloat *transformValues)
2909{
2910 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2911 transformType, transformValues))
2912 return false;
2913
2914 // no more validation here.
2915
2916 return true;
2917}
2918
2919bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2920 GLsizei numPaths,
2921 GLenum pathNameType,
2922 const void *paths,
2923 GLuint pathBase,
2924 GLenum fillMode,
2925 GLuint mask,
2926 GLenum coverMode,
2927 GLenum transformType,
2928 const GLfloat *transformValues)
2929{
2930 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2931 transformType, transformValues))
2932 return false;
2933
2934 switch (coverMode)
2935 {
2936 case GL_CONVEX_HULL_CHROMIUM:
2937 case GL_BOUNDING_BOX_CHROMIUM:
2938 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2939 break;
2940 default:
2941 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2942 return false;
2943 }
2944
2945 switch (fillMode)
2946 {
2947 case GL_COUNT_UP_CHROMIUM:
2948 case GL_COUNT_DOWN_CHROMIUM:
2949 break;
2950 default:
2951 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2952 return false;
2953 }
2954 if (!isPow2(mask + 1))
2955 {
2956 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2957 return false;
2958 }
2959
2960 return true;
2961}
2962
2963bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2964 GLsizei numPaths,
2965 GLenum pathNameType,
2966 const void *paths,
2967 GLuint pathBase,
2968 GLint reference,
2969 GLuint mask,
2970 GLenum coverMode,
2971 GLenum transformType,
2972 const GLfloat *transformValues)
2973{
2974 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2975 transformType, transformValues))
2976 return false;
2977
2978 switch (coverMode)
2979 {
2980 case GL_CONVEX_HULL_CHROMIUM:
2981 case GL_BOUNDING_BOX_CHROMIUM:
2982 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2983 break;
2984 default:
2985 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2986 return false;
2987 }
2988
2989 return true;
2990}
2991
Sami Väisänen46eaa942016-06-29 10:26:37 +03002992bool ValidateBindFragmentInputLocation(Context *context,
2993 GLuint program,
2994 GLint location,
2995 const GLchar *name)
2996{
2997 if (!context->getExtensions().pathRendering)
2998 {
2999 context->handleError(
3000 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3001 return false;
3002 }
3003
3004 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3005 if (location >= MaxLocation)
3006 {
3007 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3008 return false;
3009 }
3010
3011 const auto *programObject = context->getProgram(program);
3012 if (!programObject)
3013 {
3014 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3015 return false;
3016 }
3017
3018 if (!name)
3019 {
3020 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3021 return false;
3022 }
3023
3024 if (angle::BeginsWith(name, "gl_"))
3025 {
3026 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3027 return false;
3028 }
3029
3030 return true;
3031}
3032
3033bool ValidateProgramPathFragmentInputGen(Context *context,
3034 GLuint program,
3035 GLint location,
3036 GLenum genMode,
3037 GLint components,
3038 const GLfloat *coeffs)
3039{
3040 if (!context->getExtensions().pathRendering)
3041 {
3042 context->handleError(
3043 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3044 return false;
3045 }
3046
3047 const auto *programObject = context->getProgram(program);
3048 if (!programObject || programObject->isFlaggedForDeletion())
3049 {
3050 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3051 return false;
3052 }
3053
3054 if (!programObject->isLinked())
3055 {
3056 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3057 return false;
3058 }
3059
3060 switch (genMode)
3061 {
3062 case GL_NONE:
3063 if (components != 0)
3064 {
3065 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3066 return false;
3067 }
3068 break;
3069
3070 case GL_OBJECT_LINEAR_CHROMIUM:
3071 case GL_EYE_LINEAR_CHROMIUM:
3072 case GL_CONSTANT_CHROMIUM:
3073 if (components < 1 || components > 4)
3074 {
3075 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3076 return false;
3077 }
3078 if (!coeffs)
3079 {
3080 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3081 return false;
3082 }
3083 break;
3084
3085 default:
3086 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3087 return false;
3088 }
3089
3090 // If the location is -1 then the command is silently ignored
3091 // and no further validation is needed.
3092 if (location == -1)
3093 return true;
3094
3095 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3096
3097 if (!binding.valid)
3098 {
3099 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3100 return false;
3101 }
3102
3103 if (binding.type != GL_NONE)
3104 {
3105 GLint expectedComponents = 0;
3106 switch (binding.type)
3107 {
3108 case GL_FLOAT:
3109 expectedComponents = 1;
3110 break;
3111 case GL_FLOAT_VEC2:
3112 expectedComponents = 2;
3113 break;
3114 case GL_FLOAT_VEC3:
3115 expectedComponents = 3;
3116 break;
3117 case GL_FLOAT_VEC4:
3118 expectedComponents = 4;
3119 break;
3120 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003121 context->handleError(
3122 Error(GL_INVALID_OPERATION,
3123 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003124 return false;
3125 }
3126 if (expectedComponents != components && genMode != GL_NONE)
3127 {
3128 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3129 return false;
3130 }
3131 }
3132 return true;
3133}
3134
Geoff Lang97073d12016-04-20 10:42:34 -07003135bool ValidateCopyTextureCHROMIUM(Context *context,
3136 GLuint sourceId,
3137 GLuint destId,
3138 GLint internalFormat,
3139 GLenum destType,
3140 GLboolean unpackFlipY,
3141 GLboolean unpackPremultiplyAlpha,
3142 GLboolean unpackUnmultiplyAlpha)
3143{
3144 if (!context->getExtensions().copyTexture)
3145 {
3146 context->handleError(
3147 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3148 return false;
3149 }
3150
3151 const gl::Texture *source = context->getTexture(sourceId);
3152 if (source == nullptr)
3153 {
3154 context->handleError(
3155 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3156 return false;
3157 }
3158
3159 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3160 {
3161 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3162 return false;
3163 }
3164
3165 GLenum sourceTarget = source->getTarget();
3166 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3167 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3168 {
3169 context->handleError(
3170 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3171 return false;
3172 }
3173
3174 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3175 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3176 {
3177 context->handleError(
3178 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3179 return false;
3180 }
3181
3182 const gl::Texture *dest = context->getTexture(destId);
3183 if (dest == nullptr)
3184 {
3185 context->handleError(
3186 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3187 return false;
3188 }
3189
3190 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3191 {
3192 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3193 return false;
3194 }
3195
3196 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3197 {
3198 context->handleError(
3199 Error(GL_INVALID_OPERATION,
3200 "Destination internal format and type combination is not valid."));
3201 return false;
3202 }
3203
3204 if (dest->getImmutableFormat())
3205 {
3206 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3207 return false;
3208 }
3209
3210 return true;
3211}
3212
3213bool ValidateCopySubTextureCHROMIUM(Context *context,
3214 GLuint sourceId,
3215 GLuint destId,
3216 GLint xoffset,
3217 GLint yoffset,
3218 GLint x,
3219 GLint y,
3220 GLsizei width,
3221 GLsizei height,
3222 GLboolean unpackFlipY,
3223 GLboolean unpackPremultiplyAlpha,
3224 GLboolean unpackUnmultiplyAlpha)
3225{
3226 if (!context->getExtensions().copyTexture)
3227 {
3228 context->handleError(
3229 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3230 return false;
3231 }
3232
3233 const gl::Texture *source = context->getTexture(sourceId);
3234 if (source == nullptr)
3235 {
3236 context->handleError(
3237 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3238 return false;
3239 }
3240
3241 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3242 {
3243 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3244 return false;
3245 }
3246
3247 GLenum sourceTarget = source->getTarget();
3248 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3249 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3250 {
3251 context->handleError(
3252 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3253 return false;
3254 }
3255
3256 if (x < 0 || y < 0)
3257 {
3258 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3259 return false;
3260 }
3261
3262 if (width < 0 || height < 0)
3263 {
3264 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3265 return false;
3266 }
3267
3268 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3269 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3270 {
3271 context->handleError(
3272 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3273 return false;
3274 }
3275
3276 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3277 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3278 {
3279 context->handleError(
3280 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3281 return false;
3282 }
3283
3284 const gl::Texture *dest = context->getTexture(destId);
3285 if (dest == nullptr)
3286 {
3287 context->handleError(
3288 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3289 return false;
3290 }
3291
3292 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3293 {
3294 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3295 return false;
3296 }
3297
3298 GLenum destTarget = dest->getTarget();
3299 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3300 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3301 {
3302 context->handleError(
3303 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3304 return false;
3305 }
3306
3307 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3308 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3309 {
3310 context->handleError(
3311 Error(GL_INVALID_OPERATION,
3312 "Destination internal format and type combination is not valid."));
3313 return false;
3314 }
3315
3316 if (xoffset < 0 || yoffset < 0)
3317 {
3318 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3319 return false;
3320 }
3321
3322 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3323 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3324 {
3325 context->handleError(
3326 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3327 return false;
3328 }
3329
3330 return true;
3331}
3332
Geoff Lang47110bf2016-04-20 11:13:22 -07003333bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3334{
3335 if (!context->getExtensions().copyCompressedTexture)
3336 {
3337 context->handleError(Error(GL_INVALID_OPERATION,
3338 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3339 return false;
3340 }
3341
3342 const gl::Texture *source = context->getTexture(sourceId);
3343 if (source == nullptr)
3344 {
3345 context->handleError(
3346 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3347 return false;
3348 }
3349
3350 if (source->getTarget() != GL_TEXTURE_2D)
3351 {
3352 context->handleError(
3353 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3354 return false;
3355 }
3356
3357 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3358 {
3359 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3360 return false;
3361 }
3362
3363 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3364 if (!sourceFormat.info->compressed)
3365 {
3366 context->handleError(
3367 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3368 return false;
3369 }
3370
3371 const gl::Texture *dest = context->getTexture(destId);
3372 if (dest == nullptr)
3373 {
3374 context->handleError(
3375 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3376 return false;
3377 }
3378
3379 if (dest->getTarget() != GL_TEXTURE_2D)
3380 {
3381 context->handleError(
3382 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3383 return false;
3384 }
3385
3386 if (dest->getImmutableFormat())
3387 {
3388 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3389 return false;
3390 }
3391
3392 return true;
3393}
3394
Martin Radev4c4c8e72016-08-04 12:25:34 +03003395bool ValidateCreateShader(Context *context, GLenum type)
3396{
3397 switch (type)
3398 {
3399 case GL_VERTEX_SHADER:
3400 case GL_FRAGMENT_SHADER:
3401 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003402
Martin Radev4c4c8e72016-08-04 12:25:34 +03003403 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003404 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003405 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003406 context->handleError(
3407 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3408 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003409 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003410 break;
3411
Martin Radev4c4c8e72016-08-04 12:25:34 +03003412 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003413 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003414 return false;
3415 }
Jamie Madill29639852016-09-02 15:00:09 -04003416
3417 return true;
3418}
3419
3420bool ValidateBufferData(ValidationContext *context,
3421 GLenum target,
3422 GLsizeiptr size,
3423 const GLvoid *data,
3424 GLenum usage)
3425{
3426 if (size < 0)
3427 {
3428 context->handleError(Error(GL_INVALID_VALUE));
3429 return false;
3430 }
3431
3432 switch (usage)
3433 {
3434 case GL_STREAM_DRAW:
3435 case GL_STATIC_DRAW:
3436 case GL_DYNAMIC_DRAW:
3437 break;
3438
3439 case GL_STREAM_READ:
3440 case GL_STREAM_COPY:
3441 case GL_STATIC_READ:
3442 case GL_STATIC_COPY:
3443 case GL_DYNAMIC_READ:
3444 case GL_DYNAMIC_COPY:
3445 if (context->getClientMajorVersion() < 3)
3446 {
3447 context->handleError(Error(GL_INVALID_ENUM));
3448 return false;
3449 }
3450 break;
3451
3452 default:
3453 context->handleError(Error(GL_INVALID_ENUM));
3454 return false;
3455 }
3456
3457 if (!ValidBufferTarget(context, target))
3458 {
3459 context->handleError(Error(GL_INVALID_ENUM));
3460 return false;
3461 }
3462
3463 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3464
3465 if (!buffer)
3466 {
3467 context->handleError(Error(GL_INVALID_OPERATION));
3468 return false;
3469 }
3470
3471 return true;
3472}
3473
3474bool ValidateBufferSubData(ValidationContext *context,
3475 GLenum target,
3476 GLintptr offset,
3477 GLsizeiptr size,
3478 const GLvoid *data)
3479{
3480 if (size < 0 || offset < 0)
3481 {
3482 context->handleError(Error(GL_INVALID_VALUE));
3483 return false;
3484 }
3485
3486 if (!ValidBufferTarget(context, target))
3487 {
3488 context->handleError(Error(GL_INVALID_ENUM));
3489 return false;
3490 }
3491
3492 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3493
3494 if (!buffer)
3495 {
3496 context->handleError(Error(GL_INVALID_OPERATION));
3497 return false;
3498 }
3499
3500 if (buffer->isMapped())
3501 {
3502 context->handleError(Error(GL_INVALID_OPERATION));
3503 return false;
3504 }
3505
3506 // Check for possible overflow of size + offset
3507 angle::CheckedNumeric<size_t> checkedSize(size);
3508 checkedSize += offset;
3509 if (!checkedSize.IsValid())
3510 {
3511 context->handleError(Error(GL_OUT_OF_MEMORY));
3512 return false;
3513 }
3514
3515 if (size + offset > buffer->getSize())
3516 {
3517 context->handleError(Error(GL_INVALID_VALUE));
3518 return false;
3519 }
3520
Martin Radev4c4c8e72016-08-04 12:25:34 +03003521 return true;
3522}
3523
Geoff Langc287ea62016-09-16 14:46:51 -04003524bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3525{
3526 if (!context->getExtensions().webglCompatibility)
3527 {
3528 context->handleError(
3529 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3530 return false;
3531 }
3532
3533 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3534 auto extension = extensionInfos.find(name);
3535 if (extension == extensionInfos.end() || !extension->second.Enableable)
3536 {
3537 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3538 return false;
3539 }
3540
3541 return true;
3542}
3543
Jamie Madillef300b12016-10-07 15:12:09 -04003544bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3545{
3546 if (texture < GL_TEXTURE0 ||
3547 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3548 {
3549 context->handleError(Error(GL_INVALID_ENUM));
3550 return false;
3551 }
3552
3553 return true;
3554}
3555
3556bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3557{
3558 Program *programObject = GetValidProgram(context, program);
3559 if (!programObject)
3560 {
3561 return false;
3562 }
3563
3564 Shader *shaderObject = GetValidShader(context, shader);
3565 if (!shaderObject)
3566 {
3567 return false;
3568 }
3569
3570 switch (shaderObject->getType())
3571 {
3572 case GL_VERTEX_SHADER:
3573 {
3574 if (programObject->getAttachedVertexShader())
3575 {
3576 context->handleError(Error(GL_INVALID_OPERATION));
3577 return false;
3578 }
3579 break;
3580 }
3581 case GL_FRAGMENT_SHADER:
3582 {
3583 if (programObject->getAttachedFragmentShader())
3584 {
3585 context->handleError(Error(GL_INVALID_OPERATION));
3586 return false;
3587 }
3588 break;
3589 }
3590 case GL_COMPUTE_SHADER:
3591 {
3592 if (programObject->getAttachedComputeShader())
3593 {
3594 context->handleError(Error(GL_INVALID_OPERATION));
3595 return false;
3596 }
3597 break;
3598 }
3599 default:
3600 UNREACHABLE();
3601 break;
3602 }
3603
3604 return true;
3605}
3606
Jamie Madill01a80ee2016-11-07 12:06:18 -05003607bool ValidateBindAttribLocation(ValidationContext *context,
3608 GLuint program,
3609 GLuint index,
3610 const GLchar *name)
3611{
3612 if (index >= MAX_VERTEX_ATTRIBS)
3613 {
3614 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3615 return false;
3616 }
3617
3618 if (strncmp(name, "gl_", 3) == 0)
3619 {
3620 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3621 return false;
3622 }
3623
3624 return GetValidProgram(context, program) != nullptr;
3625}
3626
3627bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3628{
3629 if (!ValidBufferTarget(context, target))
3630 {
3631 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3632 return false;
3633 }
3634
3635 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3636 !context->isBufferGenerated(buffer))
3637 {
3638 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3639 return false;
3640 }
3641
3642 return true;
3643}
3644
3645bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3646{
3647 if (!ValidFramebufferTarget(target))
3648 {
3649 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3650 return false;
3651 }
3652
3653 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3654 !context->isFramebufferGenerated(framebuffer))
3655 {
3656 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3657 return false;
3658 }
3659
3660 return true;
3661}
3662
3663bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3664{
3665 if (target != GL_RENDERBUFFER)
3666 {
3667 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3668 return false;
3669 }
3670
3671 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3672 !context->isRenderbufferGenerated(renderbuffer))
3673 {
3674 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3675 return false;
3676 }
3677
3678 return true;
3679}
3680
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003681static bool ValidBlendEquationMode(GLenum mode)
3682{
3683 switch (mode)
3684 {
3685 case GL_FUNC_ADD:
3686 case GL_FUNC_SUBTRACT:
3687 case GL_FUNC_REVERSE_SUBTRACT:
3688 case GL_MIN:
3689 case GL_MAX:
3690 return true;
3691
3692 default:
3693 return false;
3694 }
3695}
3696
3697bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3698{
3699 if (!ValidBlendEquationMode(mode))
3700 {
3701 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3702 return false;
3703 }
3704
3705 return true;
3706}
3707
3708bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3709{
3710 if (!ValidBlendEquationMode(modeRGB))
3711 {
3712 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3713 return false;
3714 }
3715
3716 if (!ValidBlendEquationMode(modeAlpha))
3717 {
3718 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3719 return false;
3720 }
3721
3722 return true;
3723}
3724
3725bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3726{
3727 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3728}
3729
3730static bool ValidSrcBlendFunc(GLenum srcBlend)
3731{
3732 switch (srcBlend)
3733 {
3734 case GL_ZERO:
3735 case GL_ONE:
3736 case GL_SRC_COLOR:
3737 case GL_ONE_MINUS_SRC_COLOR:
3738 case GL_DST_COLOR:
3739 case GL_ONE_MINUS_DST_COLOR:
3740 case GL_SRC_ALPHA:
3741 case GL_ONE_MINUS_SRC_ALPHA:
3742 case GL_DST_ALPHA:
3743 case GL_ONE_MINUS_DST_ALPHA:
3744 case GL_CONSTANT_COLOR:
3745 case GL_ONE_MINUS_CONSTANT_COLOR:
3746 case GL_CONSTANT_ALPHA:
3747 case GL_ONE_MINUS_CONSTANT_ALPHA:
3748 case GL_SRC_ALPHA_SATURATE:
3749 return true;
3750
3751 default:
3752 return false;
3753 }
3754}
3755
3756static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3757{
3758 switch (dstBlend)
3759 {
3760 case GL_ZERO:
3761 case GL_ONE:
3762 case GL_SRC_COLOR:
3763 case GL_ONE_MINUS_SRC_COLOR:
3764 case GL_DST_COLOR:
3765 case GL_ONE_MINUS_DST_COLOR:
3766 case GL_SRC_ALPHA:
3767 case GL_ONE_MINUS_SRC_ALPHA:
3768 case GL_DST_ALPHA:
3769 case GL_ONE_MINUS_DST_ALPHA:
3770 case GL_CONSTANT_COLOR:
3771 case GL_ONE_MINUS_CONSTANT_COLOR:
3772 case GL_CONSTANT_ALPHA:
3773 case GL_ONE_MINUS_CONSTANT_ALPHA:
3774 return true;
3775
3776 case GL_SRC_ALPHA_SATURATE:
3777 return (contextMajorVersion >= 3);
3778
3779 default:
3780 return false;
3781 }
3782}
3783
3784bool ValidateBlendFuncSeparate(ValidationContext *context,
3785 GLenum srcRGB,
3786 GLenum dstRGB,
3787 GLenum srcAlpha,
3788 GLenum dstAlpha)
3789{
3790 if (!ValidSrcBlendFunc(srcRGB))
3791 {
3792 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3793 return false;
3794 }
3795
3796 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3797 {
3798 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3799 return false;
3800 }
3801
3802 if (!ValidSrcBlendFunc(srcAlpha))
3803 {
3804 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3805 return false;
3806 }
3807
3808 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3809 {
3810 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3811 return false;
3812 }
3813
3814 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3815 {
3816 bool constantColorUsed =
3817 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3818 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3819
3820 bool constantAlphaUsed =
3821 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3822 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3823
3824 if (constantColorUsed && constantAlphaUsed)
3825 {
3826 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3827 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3828 "implementation.");
3829 context->handleError(Error(GL_INVALID_OPERATION,
3830 "Simultaneous use of "
3831 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3832 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3833 "supported by this implementation."));
3834 return false;
3835 }
3836 }
3837
3838 return true;
3839}
3840
Jamie Madillc29968b2016-01-20 11:17:23 -05003841} // namespace gl