blob: ea3bbf9e955072f360630092eed81f504c52c6da [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 }
Geoff Lang3b573612016-10-31 14:08:10 -04002267 break;
2268
Ian Ewell54f87462016-03-10 13:47:21 -05002269 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002270 if (!context->getExtensions().eglImageExternal &&
2271 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002272 {
Jamie Madill437fa652016-05-03 15:13:24 -04002273 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002274 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2275 return false;
2276 }
2277 break;
2278 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002279 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002280 return false;
2281 }
2282
2283 return true;
2284}
2285
Geoff Langd8605522016-04-13 10:19:12 -04002286bool ValidateBindUniformLocationCHROMIUM(Context *context,
2287 GLuint program,
2288 GLint location,
2289 const GLchar *name)
2290{
2291 if (!context->getExtensions().bindUniformLocation)
2292 {
Jamie Madill437fa652016-05-03 15:13:24 -04002293 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002294 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2295 return false;
2296 }
2297
2298 Program *programObject = GetValidProgram(context, program);
2299 if (!programObject)
2300 {
2301 return false;
2302 }
2303
2304 if (location < 0)
2305 {
Jamie Madill437fa652016-05-03 15:13:24 -04002306 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002307 return false;
2308 }
2309
2310 const Caps &caps = context->getCaps();
2311 if (static_cast<size_t>(location) >=
2312 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2313 {
Jamie Madill437fa652016-05-03 15:13:24 -04002314 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002315 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2316 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2317 return false;
2318 }
2319
2320 if (strncmp(name, "gl_", 3) == 0)
2321 {
Jamie Madill437fa652016-05-03 15:13:24 -04002322 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002323 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2324 return false;
2325 }
2326
2327 return true;
2328}
2329
Jamie Madille2e406c2016-06-02 13:04:10 -04002330bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002331{
2332 if (!context->getExtensions().framebufferMixedSamples)
2333 {
2334 context->handleError(
2335 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2336 return false;
2337 }
2338 switch (components)
2339 {
2340 case GL_RGB:
2341 case GL_RGBA:
2342 case GL_ALPHA:
2343 case GL_NONE:
2344 break;
2345 default:
2346 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002347 Error(GL_INVALID_ENUM,
2348 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002349 return false;
2350 }
2351
2352 return true;
2353}
2354
Sami Väisänene45e53b2016-05-25 10:36:04 +03002355// CHROMIUM_path_rendering
2356
2357bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2358{
2359 if (!context->getExtensions().pathRendering)
2360 {
2361 context->handleError(
2362 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2363 return false;
2364 }
2365 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2366 {
2367 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2368 return false;
2369 }
2370 if (matrix == nullptr)
2371 {
2372 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2373 return false;
2374 }
2375 return true;
2376}
2377
2378bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2379{
2380 if (!context->getExtensions().pathRendering)
2381 {
2382 context->handleError(
2383 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2384 return false;
2385 }
2386 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2387 {
2388 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2389 return false;
2390 }
2391 return true;
2392}
2393
2394bool ValidateGenPaths(Context *context, GLsizei range)
2395{
2396 if (!context->getExtensions().pathRendering)
2397 {
2398 context->handleError(
2399 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2400 return false;
2401 }
2402
2403 // range = 0 is undefined in NV_path_rendering.
2404 // we add stricter semantic check here and require a non zero positive range.
2405 if (range <= 0)
2406 {
2407 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2408 return false;
2409 }
2410
2411 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2412 {
2413 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2414 return false;
2415 }
2416
2417 return true;
2418}
2419
2420bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2421{
2422 if (!context->getExtensions().pathRendering)
2423 {
2424 context->handleError(
2425 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2426 return false;
2427 }
2428
2429 // range = 0 is undefined in NV_path_rendering.
2430 // we add stricter semantic check here and require a non zero positive range.
2431 if (range <= 0)
2432 {
2433 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2434 return false;
2435 }
2436
2437 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2438 checkedRange += range;
2439
2440 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2441 {
2442 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2443 return false;
2444 }
2445 return true;
2446}
2447
2448bool ValidatePathCommands(Context *context,
2449 GLuint path,
2450 GLsizei numCommands,
2451 const GLubyte *commands,
2452 GLsizei numCoords,
2453 GLenum coordType,
2454 const void *coords)
2455{
2456 if (!context->getExtensions().pathRendering)
2457 {
2458 context->handleError(
2459 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2460 return false;
2461 }
2462 if (!context->hasPath(path))
2463 {
2464 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2465 return false;
2466 }
2467
2468 if (numCommands < 0)
2469 {
2470 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2471 return false;
2472 }
2473 else if (numCommands > 0)
2474 {
2475 if (!commands)
2476 {
2477 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2478 return false;
2479 }
2480 }
2481
2482 if (numCoords < 0)
2483 {
2484 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2485 return false;
2486 }
2487 else if (numCoords > 0)
2488 {
2489 if (!coords)
2490 {
2491 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2492 return false;
2493 }
2494 }
2495
2496 std::uint32_t coordTypeSize = 0;
2497 switch (coordType)
2498 {
2499 case GL_BYTE:
2500 coordTypeSize = sizeof(GLbyte);
2501 break;
2502
2503 case GL_UNSIGNED_BYTE:
2504 coordTypeSize = sizeof(GLubyte);
2505 break;
2506
2507 case GL_SHORT:
2508 coordTypeSize = sizeof(GLshort);
2509 break;
2510
2511 case GL_UNSIGNED_SHORT:
2512 coordTypeSize = sizeof(GLushort);
2513 break;
2514
2515 case GL_FLOAT:
2516 coordTypeSize = sizeof(GLfloat);
2517 break;
2518
2519 default:
2520 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2521 return false;
2522 }
2523
2524 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2525 checkedSize += (coordTypeSize * numCoords);
2526 if (!checkedSize.IsValid())
2527 {
2528 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2529 return false;
2530 }
2531
2532 // early return skips command data validation when it doesn't exist.
2533 if (!commands)
2534 return true;
2535
2536 GLsizei expectedNumCoords = 0;
2537 for (GLsizei i = 0; i < numCommands; ++i)
2538 {
2539 switch (commands[i])
2540 {
2541 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2542 break;
2543 case GL_MOVE_TO_CHROMIUM:
2544 case GL_LINE_TO_CHROMIUM:
2545 expectedNumCoords += 2;
2546 break;
2547 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2548 expectedNumCoords += 4;
2549 break;
2550 case GL_CUBIC_CURVE_TO_CHROMIUM:
2551 expectedNumCoords += 6;
2552 break;
2553 case GL_CONIC_CURVE_TO_CHROMIUM:
2554 expectedNumCoords += 5;
2555 break;
2556 default:
2557 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2558 return false;
2559 }
2560 }
2561 if (expectedNumCoords != numCoords)
2562 {
2563 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2564 return false;
2565 }
2566
2567 return true;
2568}
2569
2570bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2571{
2572 if (!context->getExtensions().pathRendering)
2573 {
2574 context->handleError(
2575 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2576 return false;
2577 }
2578 if (!context->hasPath(path))
2579 {
2580 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2581 return false;
2582 }
2583
2584 switch (pname)
2585 {
2586 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2587 if (value < 0.0f)
2588 {
2589 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2590 return false;
2591 }
2592 break;
2593 case GL_PATH_END_CAPS_CHROMIUM:
2594 switch (static_cast<GLenum>(value))
2595 {
2596 case GL_FLAT_CHROMIUM:
2597 case GL_SQUARE_CHROMIUM:
2598 case GL_ROUND_CHROMIUM:
2599 break;
2600 default:
2601 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2602 return false;
2603 }
2604 break;
2605 case GL_PATH_JOIN_STYLE_CHROMIUM:
2606 switch (static_cast<GLenum>(value))
2607 {
2608 case GL_MITER_REVERT_CHROMIUM:
2609 case GL_BEVEL_CHROMIUM:
2610 case GL_ROUND_CHROMIUM:
2611 break;
2612 default:
2613 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2614 return false;
2615 }
2616 case GL_PATH_MITER_LIMIT_CHROMIUM:
2617 if (value < 0.0f)
2618 {
2619 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2620 return false;
2621 }
2622 break;
2623
2624 case GL_PATH_STROKE_BOUND_CHROMIUM:
2625 // no errors, only clamping.
2626 break;
2627
2628 default:
2629 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2630 return false;
2631 }
2632 return true;
2633}
2634
2635bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2636{
2637 if (!context->getExtensions().pathRendering)
2638 {
2639 context->handleError(
2640 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2641 return false;
2642 }
2643
2644 if (!context->hasPath(path))
2645 {
2646 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2647 return false;
2648 }
2649 if (!value)
2650 {
2651 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2652 return false;
2653 }
2654
2655 switch (pname)
2656 {
2657 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2658 case GL_PATH_END_CAPS_CHROMIUM:
2659 case GL_PATH_JOIN_STYLE_CHROMIUM:
2660 case GL_PATH_MITER_LIMIT_CHROMIUM:
2661 case GL_PATH_STROKE_BOUND_CHROMIUM:
2662 break;
2663
2664 default:
2665 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2666 return false;
2667 }
2668
2669 return true;
2670}
2671
2672bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2673{
2674 if (!context->getExtensions().pathRendering)
2675 {
2676 context->handleError(
2677 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2678 return false;
2679 }
2680
2681 switch (func)
2682 {
2683 case GL_NEVER:
2684 case GL_ALWAYS:
2685 case GL_LESS:
2686 case GL_LEQUAL:
2687 case GL_EQUAL:
2688 case GL_GEQUAL:
2689 case GL_GREATER:
2690 case GL_NOTEQUAL:
2691 break;
2692 default:
2693 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2694 return false;
2695 }
2696
2697 return true;
2698}
2699
2700// Note that the spec specifies that for the path drawing commands
2701// if the path object is not an existing path object the command
2702// does nothing and no error is generated.
2703// However if the path object exists but has not been specified any
2704// commands then an error is generated.
2705
2706bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2707{
2708 if (!context->getExtensions().pathRendering)
2709 {
2710 context->handleError(
2711 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2712 return false;
2713 }
2714 if (context->hasPath(path) && !context->hasPathData(path))
2715 {
2716 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2717 return false;
2718 }
2719
2720 switch (fillMode)
2721 {
2722 case GL_COUNT_UP_CHROMIUM:
2723 case GL_COUNT_DOWN_CHROMIUM:
2724 break;
2725 default:
2726 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2727 return false;
2728 }
2729
2730 if (!isPow2(mask + 1))
2731 {
2732 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2733 return false;
2734 }
2735
2736 return true;
2737}
2738
2739bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2740{
2741 if (!context->getExtensions().pathRendering)
2742 {
2743 context->handleError(
2744 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2745 return false;
2746 }
2747 if (context->hasPath(path) && !context->hasPathData(path))
2748 {
2749 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2750 return false;
2751 }
2752
2753 return true;
2754}
2755
2756bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2757{
2758 if (!context->getExtensions().pathRendering)
2759 {
2760 context->handleError(
2761 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2762 return false;
2763 }
2764 if (context->hasPath(path) && !context->hasPathData(path))
2765 {
2766 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2767 return false;
2768 }
2769
2770 switch (coverMode)
2771 {
2772 case GL_CONVEX_HULL_CHROMIUM:
2773 case GL_BOUNDING_BOX_CHROMIUM:
2774 break;
2775 default:
2776 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2777 return false;
2778 }
2779 return true;
2780}
2781
2782bool ValidateStencilThenCoverFillPath(Context *context,
2783 GLuint path,
2784 GLenum fillMode,
2785 GLuint mask,
2786 GLenum coverMode)
2787{
2788 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2789 ValidateCoverPath(context, path, coverMode);
2790}
2791
2792bool ValidateStencilThenCoverStrokePath(Context *context,
2793 GLuint path,
2794 GLint reference,
2795 GLuint mask,
2796 GLenum coverMode)
2797{
2798 return ValidateStencilStrokePath(context, path, reference, mask) &&
2799 ValidateCoverPath(context, path, coverMode);
2800}
2801
2802bool ValidateIsPath(Context *context)
2803{
2804 if (!context->getExtensions().pathRendering)
2805 {
2806 context->handleError(
2807 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2808 return false;
2809 }
2810 return true;
2811}
2812
Sami Väisänend59ca052016-06-21 16:10:00 +03002813bool ValidateCoverFillPathInstanced(Context *context,
2814 GLsizei numPaths,
2815 GLenum pathNameType,
2816 const void *paths,
2817 GLuint pathBase,
2818 GLenum coverMode,
2819 GLenum transformType,
2820 const GLfloat *transformValues)
2821{
2822 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2823 transformType, transformValues))
2824 return false;
2825
2826 switch (coverMode)
2827 {
2828 case GL_CONVEX_HULL_CHROMIUM:
2829 case GL_BOUNDING_BOX_CHROMIUM:
2830 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2831 break;
2832 default:
2833 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2834 return false;
2835 }
2836
2837 return true;
2838}
2839
2840bool ValidateCoverStrokePathInstanced(Context *context,
2841 GLsizei numPaths,
2842 GLenum pathNameType,
2843 const void *paths,
2844 GLuint pathBase,
2845 GLenum coverMode,
2846 GLenum transformType,
2847 const GLfloat *transformValues)
2848{
2849 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2850 transformType, transformValues))
2851 return false;
2852
2853 switch (coverMode)
2854 {
2855 case GL_CONVEX_HULL_CHROMIUM:
2856 case GL_BOUNDING_BOX_CHROMIUM:
2857 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2858 break;
2859 default:
2860 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2861 return false;
2862 }
2863
2864 return true;
2865}
2866
2867bool ValidateStencilFillPathInstanced(Context *context,
2868 GLsizei numPaths,
2869 GLenum pathNameType,
2870 const void *paths,
2871 GLuint pathBase,
2872 GLenum fillMode,
2873 GLuint mask,
2874 GLenum transformType,
2875 const GLfloat *transformValues)
2876{
2877
2878 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2879 transformType, transformValues))
2880 return false;
2881
2882 switch (fillMode)
2883 {
2884 case GL_COUNT_UP_CHROMIUM:
2885 case GL_COUNT_DOWN_CHROMIUM:
2886 break;
2887 default:
2888 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2889 return false;
2890 }
2891 if (!isPow2(mask + 1))
2892 {
2893 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2894 return false;
2895 }
2896 return true;
2897}
2898
2899bool ValidateStencilStrokePathInstanced(Context *context,
2900 GLsizei numPaths,
2901 GLenum pathNameType,
2902 const void *paths,
2903 GLuint pathBase,
2904 GLint reference,
2905 GLuint mask,
2906 GLenum transformType,
2907 const GLfloat *transformValues)
2908{
2909 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2910 transformType, transformValues))
2911 return false;
2912
2913 // no more validation here.
2914
2915 return true;
2916}
2917
2918bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2919 GLsizei numPaths,
2920 GLenum pathNameType,
2921 const void *paths,
2922 GLuint pathBase,
2923 GLenum fillMode,
2924 GLuint mask,
2925 GLenum coverMode,
2926 GLenum transformType,
2927 const GLfloat *transformValues)
2928{
2929 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2930 transformType, transformValues))
2931 return false;
2932
2933 switch (coverMode)
2934 {
2935 case GL_CONVEX_HULL_CHROMIUM:
2936 case GL_BOUNDING_BOX_CHROMIUM:
2937 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2938 break;
2939 default:
2940 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2941 return false;
2942 }
2943
2944 switch (fillMode)
2945 {
2946 case GL_COUNT_UP_CHROMIUM:
2947 case GL_COUNT_DOWN_CHROMIUM:
2948 break;
2949 default:
2950 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2951 return false;
2952 }
2953 if (!isPow2(mask + 1))
2954 {
2955 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2956 return false;
2957 }
2958
2959 return true;
2960}
2961
2962bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2963 GLsizei numPaths,
2964 GLenum pathNameType,
2965 const void *paths,
2966 GLuint pathBase,
2967 GLint reference,
2968 GLuint mask,
2969 GLenum coverMode,
2970 GLenum transformType,
2971 const GLfloat *transformValues)
2972{
2973 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2974 transformType, transformValues))
2975 return false;
2976
2977 switch (coverMode)
2978 {
2979 case GL_CONVEX_HULL_CHROMIUM:
2980 case GL_BOUNDING_BOX_CHROMIUM:
2981 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2982 break;
2983 default:
2984 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2985 return false;
2986 }
2987
2988 return true;
2989}
2990
Sami Väisänen46eaa942016-06-29 10:26:37 +03002991bool ValidateBindFragmentInputLocation(Context *context,
2992 GLuint program,
2993 GLint location,
2994 const GLchar *name)
2995{
2996 if (!context->getExtensions().pathRendering)
2997 {
2998 context->handleError(
2999 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3000 return false;
3001 }
3002
3003 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3004 if (location >= MaxLocation)
3005 {
3006 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3007 return false;
3008 }
3009
3010 const auto *programObject = context->getProgram(program);
3011 if (!programObject)
3012 {
3013 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3014 return false;
3015 }
3016
3017 if (!name)
3018 {
3019 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3020 return false;
3021 }
3022
3023 if (angle::BeginsWith(name, "gl_"))
3024 {
3025 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3026 return false;
3027 }
3028
3029 return true;
3030}
3031
3032bool ValidateProgramPathFragmentInputGen(Context *context,
3033 GLuint program,
3034 GLint location,
3035 GLenum genMode,
3036 GLint components,
3037 const GLfloat *coeffs)
3038{
3039 if (!context->getExtensions().pathRendering)
3040 {
3041 context->handleError(
3042 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3043 return false;
3044 }
3045
3046 const auto *programObject = context->getProgram(program);
3047 if (!programObject || programObject->isFlaggedForDeletion())
3048 {
3049 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3050 return false;
3051 }
3052
3053 if (!programObject->isLinked())
3054 {
3055 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3056 return false;
3057 }
3058
3059 switch (genMode)
3060 {
3061 case GL_NONE:
3062 if (components != 0)
3063 {
3064 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3065 return false;
3066 }
3067 break;
3068
3069 case GL_OBJECT_LINEAR_CHROMIUM:
3070 case GL_EYE_LINEAR_CHROMIUM:
3071 case GL_CONSTANT_CHROMIUM:
3072 if (components < 1 || components > 4)
3073 {
3074 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3075 return false;
3076 }
3077 if (!coeffs)
3078 {
3079 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3080 return false;
3081 }
3082 break;
3083
3084 default:
3085 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3086 return false;
3087 }
3088
3089 // If the location is -1 then the command is silently ignored
3090 // and no further validation is needed.
3091 if (location == -1)
3092 return true;
3093
3094 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3095
3096 if (!binding.valid)
3097 {
3098 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3099 return false;
3100 }
3101
3102 if (binding.type != GL_NONE)
3103 {
3104 GLint expectedComponents = 0;
3105 switch (binding.type)
3106 {
3107 case GL_FLOAT:
3108 expectedComponents = 1;
3109 break;
3110 case GL_FLOAT_VEC2:
3111 expectedComponents = 2;
3112 break;
3113 case GL_FLOAT_VEC3:
3114 expectedComponents = 3;
3115 break;
3116 case GL_FLOAT_VEC4:
3117 expectedComponents = 4;
3118 break;
3119 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003120 context->handleError(
3121 Error(GL_INVALID_OPERATION,
3122 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003123 return false;
3124 }
3125 if (expectedComponents != components && genMode != GL_NONE)
3126 {
3127 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3128 return false;
3129 }
3130 }
3131 return true;
3132}
3133
Geoff Lang97073d12016-04-20 10:42:34 -07003134bool ValidateCopyTextureCHROMIUM(Context *context,
3135 GLuint sourceId,
3136 GLuint destId,
3137 GLint internalFormat,
3138 GLenum destType,
3139 GLboolean unpackFlipY,
3140 GLboolean unpackPremultiplyAlpha,
3141 GLboolean unpackUnmultiplyAlpha)
3142{
3143 if (!context->getExtensions().copyTexture)
3144 {
3145 context->handleError(
3146 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3147 return false;
3148 }
3149
3150 const gl::Texture *source = context->getTexture(sourceId);
3151 if (source == nullptr)
3152 {
3153 context->handleError(
3154 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3155 return false;
3156 }
3157
3158 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3159 {
3160 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3161 return false;
3162 }
3163
3164 GLenum sourceTarget = source->getTarget();
3165 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3166 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3167 {
3168 context->handleError(
3169 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3170 return false;
3171 }
3172
3173 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3174 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3175 {
3176 context->handleError(
3177 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3178 return false;
3179 }
3180
3181 const gl::Texture *dest = context->getTexture(destId);
3182 if (dest == nullptr)
3183 {
3184 context->handleError(
3185 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3186 return false;
3187 }
3188
3189 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3190 {
3191 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3192 return false;
3193 }
3194
3195 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3196 {
3197 context->handleError(
3198 Error(GL_INVALID_OPERATION,
3199 "Destination internal format and type combination is not valid."));
3200 return false;
3201 }
3202
3203 if (dest->getImmutableFormat())
3204 {
3205 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3206 return false;
3207 }
3208
3209 return true;
3210}
3211
3212bool ValidateCopySubTextureCHROMIUM(Context *context,
3213 GLuint sourceId,
3214 GLuint destId,
3215 GLint xoffset,
3216 GLint yoffset,
3217 GLint x,
3218 GLint y,
3219 GLsizei width,
3220 GLsizei height,
3221 GLboolean unpackFlipY,
3222 GLboolean unpackPremultiplyAlpha,
3223 GLboolean unpackUnmultiplyAlpha)
3224{
3225 if (!context->getExtensions().copyTexture)
3226 {
3227 context->handleError(
3228 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3229 return false;
3230 }
3231
3232 const gl::Texture *source = context->getTexture(sourceId);
3233 if (source == nullptr)
3234 {
3235 context->handleError(
3236 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3237 return false;
3238 }
3239
3240 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3241 {
3242 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3243 return false;
3244 }
3245
3246 GLenum sourceTarget = source->getTarget();
3247 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3248 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3249 {
3250 context->handleError(
3251 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3252 return false;
3253 }
3254
3255 if (x < 0 || y < 0)
3256 {
3257 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3258 return false;
3259 }
3260
3261 if (width < 0 || height < 0)
3262 {
3263 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3264 return false;
3265 }
3266
3267 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3268 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3269 {
3270 context->handleError(
3271 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3272 return false;
3273 }
3274
3275 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3276 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3277 {
3278 context->handleError(
3279 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3280 return false;
3281 }
3282
3283 const gl::Texture *dest = context->getTexture(destId);
3284 if (dest == nullptr)
3285 {
3286 context->handleError(
3287 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3288 return false;
3289 }
3290
3291 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3292 {
3293 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3294 return false;
3295 }
3296
3297 GLenum destTarget = dest->getTarget();
3298 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3299 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3300 {
3301 context->handleError(
3302 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3303 return false;
3304 }
3305
3306 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3307 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3308 {
3309 context->handleError(
3310 Error(GL_INVALID_OPERATION,
3311 "Destination internal format and type combination is not valid."));
3312 return false;
3313 }
3314
3315 if (xoffset < 0 || yoffset < 0)
3316 {
3317 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3318 return false;
3319 }
3320
3321 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3322 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3323 {
3324 context->handleError(
3325 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3326 return false;
3327 }
3328
3329 return true;
3330}
3331
Geoff Lang47110bf2016-04-20 11:13:22 -07003332bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3333{
3334 if (!context->getExtensions().copyCompressedTexture)
3335 {
3336 context->handleError(Error(GL_INVALID_OPERATION,
3337 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3338 return false;
3339 }
3340
3341 const gl::Texture *source = context->getTexture(sourceId);
3342 if (source == nullptr)
3343 {
3344 context->handleError(
3345 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3346 return false;
3347 }
3348
3349 if (source->getTarget() != GL_TEXTURE_2D)
3350 {
3351 context->handleError(
3352 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3353 return false;
3354 }
3355
3356 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3357 {
3358 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3359 return false;
3360 }
3361
3362 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3363 if (!sourceFormat.info->compressed)
3364 {
3365 context->handleError(
3366 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3367 return false;
3368 }
3369
3370 const gl::Texture *dest = context->getTexture(destId);
3371 if (dest == nullptr)
3372 {
3373 context->handleError(
3374 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3375 return false;
3376 }
3377
3378 if (dest->getTarget() != GL_TEXTURE_2D)
3379 {
3380 context->handleError(
3381 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3382 return false;
3383 }
3384
3385 if (dest->getImmutableFormat())
3386 {
3387 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3388 return false;
3389 }
3390
3391 return true;
3392}
3393
Martin Radev4c4c8e72016-08-04 12:25:34 +03003394bool ValidateCreateShader(Context *context, GLenum type)
3395{
3396 switch (type)
3397 {
3398 case GL_VERTEX_SHADER:
3399 case GL_FRAGMENT_SHADER:
3400 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003401
Martin Radev4c4c8e72016-08-04 12:25:34 +03003402 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003403 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003404 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003405 context->handleError(
3406 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3407 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003408 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003409 break;
3410
Martin Radev4c4c8e72016-08-04 12:25:34 +03003411 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003412 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003413 return false;
3414 }
Jamie Madill29639852016-09-02 15:00:09 -04003415
3416 return true;
3417}
3418
3419bool ValidateBufferData(ValidationContext *context,
3420 GLenum target,
3421 GLsizeiptr size,
3422 const GLvoid *data,
3423 GLenum usage)
3424{
3425 if (size < 0)
3426 {
3427 context->handleError(Error(GL_INVALID_VALUE));
3428 return false;
3429 }
3430
3431 switch (usage)
3432 {
3433 case GL_STREAM_DRAW:
3434 case GL_STATIC_DRAW:
3435 case GL_DYNAMIC_DRAW:
3436 break;
3437
3438 case GL_STREAM_READ:
3439 case GL_STREAM_COPY:
3440 case GL_STATIC_READ:
3441 case GL_STATIC_COPY:
3442 case GL_DYNAMIC_READ:
3443 case GL_DYNAMIC_COPY:
3444 if (context->getClientMajorVersion() < 3)
3445 {
3446 context->handleError(Error(GL_INVALID_ENUM));
3447 return false;
3448 }
3449 break;
3450
3451 default:
3452 context->handleError(Error(GL_INVALID_ENUM));
3453 return false;
3454 }
3455
3456 if (!ValidBufferTarget(context, target))
3457 {
3458 context->handleError(Error(GL_INVALID_ENUM));
3459 return false;
3460 }
3461
3462 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3463
3464 if (!buffer)
3465 {
3466 context->handleError(Error(GL_INVALID_OPERATION));
3467 return false;
3468 }
3469
3470 return true;
3471}
3472
3473bool ValidateBufferSubData(ValidationContext *context,
3474 GLenum target,
3475 GLintptr offset,
3476 GLsizeiptr size,
3477 const GLvoid *data)
3478{
3479 if (size < 0 || offset < 0)
3480 {
3481 context->handleError(Error(GL_INVALID_VALUE));
3482 return false;
3483 }
3484
3485 if (!ValidBufferTarget(context, target))
3486 {
3487 context->handleError(Error(GL_INVALID_ENUM));
3488 return false;
3489 }
3490
3491 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3492
3493 if (!buffer)
3494 {
3495 context->handleError(Error(GL_INVALID_OPERATION));
3496 return false;
3497 }
3498
3499 if (buffer->isMapped())
3500 {
3501 context->handleError(Error(GL_INVALID_OPERATION));
3502 return false;
3503 }
3504
3505 // Check for possible overflow of size + offset
3506 angle::CheckedNumeric<size_t> checkedSize(size);
3507 checkedSize += offset;
3508 if (!checkedSize.IsValid())
3509 {
3510 context->handleError(Error(GL_OUT_OF_MEMORY));
3511 return false;
3512 }
3513
3514 if (size + offset > buffer->getSize())
3515 {
3516 context->handleError(Error(GL_INVALID_VALUE));
3517 return false;
3518 }
3519
Martin Radev4c4c8e72016-08-04 12:25:34 +03003520 return true;
3521}
3522
Geoff Langc339c4e2016-11-29 10:37:36 -05003523bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003524{
Geoff Langc339c4e2016-11-29 10:37:36 -05003525 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003526 {
3527 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003528 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003529 return false;
3530 }
3531
3532 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3533 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003534 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003535 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003536 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003537 return false;
3538 }
3539
3540 return true;
3541}
3542
Jamie Madillef300b12016-10-07 15:12:09 -04003543bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3544{
3545 if (texture < GL_TEXTURE0 ||
3546 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3547 {
3548 context->handleError(Error(GL_INVALID_ENUM));
3549 return false;
3550 }
3551
3552 return true;
3553}
3554
3555bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3556{
3557 Program *programObject = GetValidProgram(context, program);
3558 if (!programObject)
3559 {
3560 return false;
3561 }
3562
3563 Shader *shaderObject = GetValidShader(context, shader);
3564 if (!shaderObject)
3565 {
3566 return false;
3567 }
3568
3569 switch (shaderObject->getType())
3570 {
3571 case GL_VERTEX_SHADER:
3572 {
3573 if (programObject->getAttachedVertexShader())
3574 {
3575 context->handleError(Error(GL_INVALID_OPERATION));
3576 return false;
3577 }
3578 break;
3579 }
3580 case GL_FRAGMENT_SHADER:
3581 {
3582 if (programObject->getAttachedFragmentShader())
3583 {
3584 context->handleError(Error(GL_INVALID_OPERATION));
3585 return false;
3586 }
3587 break;
3588 }
3589 case GL_COMPUTE_SHADER:
3590 {
3591 if (programObject->getAttachedComputeShader())
3592 {
3593 context->handleError(Error(GL_INVALID_OPERATION));
3594 return false;
3595 }
3596 break;
3597 }
3598 default:
3599 UNREACHABLE();
3600 break;
3601 }
3602
3603 return true;
3604}
3605
Jamie Madill01a80ee2016-11-07 12:06:18 -05003606bool ValidateBindAttribLocation(ValidationContext *context,
3607 GLuint program,
3608 GLuint index,
3609 const GLchar *name)
3610{
3611 if (index >= MAX_VERTEX_ATTRIBS)
3612 {
3613 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3614 return false;
3615 }
3616
3617 if (strncmp(name, "gl_", 3) == 0)
3618 {
3619 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3620 return false;
3621 }
3622
3623 return GetValidProgram(context, program) != nullptr;
3624}
3625
3626bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3627{
3628 if (!ValidBufferTarget(context, target))
3629 {
3630 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3631 return false;
3632 }
3633
3634 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3635 !context->isBufferGenerated(buffer))
3636 {
3637 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3638 return false;
3639 }
3640
3641 return true;
3642}
3643
3644bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3645{
3646 if (!ValidFramebufferTarget(target))
3647 {
3648 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3649 return false;
3650 }
3651
3652 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3653 !context->isFramebufferGenerated(framebuffer))
3654 {
3655 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3656 return false;
3657 }
3658
3659 return true;
3660}
3661
3662bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3663{
3664 if (target != GL_RENDERBUFFER)
3665 {
3666 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3667 return false;
3668 }
3669
3670 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3671 !context->isRenderbufferGenerated(renderbuffer))
3672 {
3673 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3674 return false;
3675 }
3676
3677 return true;
3678}
3679
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003680static bool ValidBlendEquationMode(GLenum mode)
3681{
3682 switch (mode)
3683 {
3684 case GL_FUNC_ADD:
3685 case GL_FUNC_SUBTRACT:
3686 case GL_FUNC_REVERSE_SUBTRACT:
3687 case GL_MIN:
3688 case GL_MAX:
3689 return true;
3690
3691 default:
3692 return false;
3693 }
3694}
3695
3696bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3697{
3698 if (!ValidBlendEquationMode(mode))
3699 {
3700 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3701 return false;
3702 }
3703
3704 return true;
3705}
3706
3707bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3708{
3709 if (!ValidBlendEquationMode(modeRGB))
3710 {
3711 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3712 return false;
3713 }
3714
3715 if (!ValidBlendEquationMode(modeAlpha))
3716 {
3717 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3718 return false;
3719 }
3720
3721 return true;
3722}
3723
3724bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3725{
3726 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3727}
3728
3729static bool ValidSrcBlendFunc(GLenum srcBlend)
3730{
3731 switch (srcBlend)
3732 {
3733 case GL_ZERO:
3734 case GL_ONE:
3735 case GL_SRC_COLOR:
3736 case GL_ONE_MINUS_SRC_COLOR:
3737 case GL_DST_COLOR:
3738 case GL_ONE_MINUS_DST_COLOR:
3739 case GL_SRC_ALPHA:
3740 case GL_ONE_MINUS_SRC_ALPHA:
3741 case GL_DST_ALPHA:
3742 case GL_ONE_MINUS_DST_ALPHA:
3743 case GL_CONSTANT_COLOR:
3744 case GL_ONE_MINUS_CONSTANT_COLOR:
3745 case GL_CONSTANT_ALPHA:
3746 case GL_ONE_MINUS_CONSTANT_ALPHA:
3747 case GL_SRC_ALPHA_SATURATE:
3748 return true;
3749
3750 default:
3751 return false;
3752 }
3753}
3754
3755static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3756{
3757 switch (dstBlend)
3758 {
3759 case GL_ZERO:
3760 case GL_ONE:
3761 case GL_SRC_COLOR:
3762 case GL_ONE_MINUS_SRC_COLOR:
3763 case GL_DST_COLOR:
3764 case GL_ONE_MINUS_DST_COLOR:
3765 case GL_SRC_ALPHA:
3766 case GL_ONE_MINUS_SRC_ALPHA:
3767 case GL_DST_ALPHA:
3768 case GL_ONE_MINUS_DST_ALPHA:
3769 case GL_CONSTANT_COLOR:
3770 case GL_ONE_MINUS_CONSTANT_COLOR:
3771 case GL_CONSTANT_ALPHA:
3772 case GL_ONE_MINUS_CONSTANT_ALPHA:
3773 return true;
3774
3775 case GL_SRC_ALPHA_SATURATE:
3776 return (contextMajorVersion >= 3);
3777
3778 default:
3779 return false;
3780 }
3781}
3782
3783bool ValidateBlendFuncSeparate(ValidationContext *context,
3784 GLenum srcRGB,
3785 GLenum dstRGB,
3786 GLenum srcAlpha,
3787 GLenum dstAlpha)
3788{
3789 if (!ValidSrcBlendFunc(srcRGB))
3790 {
3791 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3792 return false;
3793 }
3794
3795 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3796 {
3797 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3798 return false;
3799 }
3800
3801 if (!ValidSrcBlendFunc(srcAlpha))
3802 {
3803 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3804 return false;
3805 }
3806
3807 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3808 {
3809 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3810 return false;
3811 }
3812
3813 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3814 {
3815 bool constantColorUsed =
3816 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3817 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3818
3819 bool constantAlphaUsed =
3820 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3821 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3822
3823 if (constantColorUsed && constantAlphaUsed)
3824 {
3825 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3826 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3827 "implementation.");
3828 context->handleError(Error(GL_INVALID_OPERATION,
3829 "Simultaneous use of "
3830 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3831 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3832 "supported by this implementation."));
3833 return false;
3834 }
3835 }
3836
3837 return true;
3838}
3839
Geoff Langc339c4e2016-11-29 10:37:36 -05003840bool ValidateGetString(Context *context, GLenum name)
3841{
3842 switch (name)
3843 {
3844 case GL_VENDOR:
3845 case GL_RENDERER:
3846 case GL_VERSION:
3847 case GL_SHADING_LANGUAGE_VERSION:
3848 case GL_EXTENSIONS:
3849 break;
3850
3851 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3852 if (!context->getExtensions().requestExtension)
3853 {
3854 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3855 return false;
3856 }
3857 break;
3858
3859 default:
3860 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3861 return false;
3862 }
3863
3864 return true;
3865}
3866
Geoff Lang47c48082016-12-07 15:38:13 -05003867bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3868{
3869 if (width <= 0.0f || isNaN(width))
3870 {
3871 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3872 return false;
3873 }
3874
3875 return true;
3876}
3877
Jamie Madillc29968b2016-01-20 11:17:23 -05003878} // namespace gl