blob: f60959af759a28d37fa7374bf8047ec565424ca4 [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
Geoff Langcc507aa2016-12-12 10:09:52 -0500743 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
744 {
745 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
746 return false;
747 }
748
Jamie Madill0c8abca2016-07-22 20:21:26 -0400749 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400750 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400751 xoffset, yoffset, 0, x, y, width, height, border,
752 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400754 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 }
756
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700757 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400758 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400759 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760
761 // [OpenGL ES 2.0.24] table 3.9
762 if (isSubImage)
763 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400764 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400765 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800766 case GL_ALPHA:
767 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
768 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
769 {
770 context->handleError(Error(GL_INVALID_OPERATION));
771 return false;
772 }
773 break;
774 case GL_LUMINANCE:
775 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
776 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
777 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
778 colorbufferFormat != GL_RGBA8_OES)
779 {
780 context->handleError(Error(GL_INVALID_OPERATION));
781 return false;
782 }
783 break;
784 case GL_RED_EXT:
785 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
786 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
787 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
788 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
789 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
790 colorbufferFormat != GL_RGBA32F)
791 {
792 context->handleError(Error(GL_INVALID_OPERATION));
793 return false;
794 }
795 break;
796 case GL_RG_EXT:
797 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
798 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
799 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
800 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
801 colorbufferFormat != GL_RGBA32F)
802 {
803 context->handleError(Error(GL_INVALID_OPERATION));
804 return false;
805 }
806 break;
807 case GL_RGB:
808 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
809 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
810 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
811 colorbufferFormat != GL_RGBA32F)
812 {
813 context->handleError(Error(GL_INVALID_OPERATION));
814 return false;
815 }
816 break;
817 case GL_LUMINANCE_ALPHA:
818 case GL_RGBA:
819 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
820 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
821 {
822 context->handleError(Error(GL_INVALID_OPERATION));
823 return false;
824 }
825 break;
826 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
827 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
828 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
829 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
830 case GL_ETC1_RGB8_OES:
831 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400832 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400833 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800834 case GL_DEPTH_COMPONENT:
835 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400836 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
He Yunchaoced53ae2016-11-29 15:00:51 +0800838 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500842
Jamie Madill0c8abca2016-07-22 20:21:26 -0400843 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500844 {
Jamie Madill437fa652016-05-03 15:13:24 -0400845 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500846 return false;
847 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848 }
849 else
850 {
851 switch (internalformat)
852 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800853 case GL_ALPHA:
854 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
855 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
856 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
857 {
858 context->handleError(Error(GL_INVALID_OPERATION));
859 return false;
860 }
861 break;
862 case GL_LUMINANCE:
863 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
864 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
865 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
866 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
867 colorbufferFormat != GL_BGR5_A1_ANGLEX)
868 {
869 context->handleError(Error(GL_INVALID_OPERATION));
870 return false;
871 }
872 break;
873 case GL_RED_EXT:
874 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
875 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
876 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
877 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
878 colorbufferFormat != GL_BGR5_A1_ANGLEX)
879 {
880 context->handleError(Error(GL_INVALID_OPERATION));
881 return false;
882 }
883 break;
884 case GL_RG_EXT:
885 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
886 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
887 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
888 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
889 {
890 context->handleError(Error(GL_INVALID_OPERATION));
891 return false;
892 }
893 break;
894 case GL_RGB:
895 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
896 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
897 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
898 colorbufferFormat != GL_BGR5_A1_ANGLEX)
899 {
900 context->handleError(Error(GL_INVALID_OPERATION));
901 return false;
902 }
903 break;
904 case GL_LUMINANCE_ALPHA:
905 case GL_RGBA:
906 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
907 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
908 colorbufferFormat != GL_BGR5_A1_ANGLEX)
909 {
910 context->handleError(Error(GL_INVALID_OPERATION));
911 return false;
912 }
913 break;
914 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
915 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
916 if (context->getExtensions().textureCompressionDXT1)
917 {
918 context->handleError(Error(GL_INVALID_OPERATION));
919 return false;
920 }
921 else
922 {
923 context->handleError(Error(GL_INVALID_ENUM));
924 return false;
925 }
926 break;
927 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
928 if (context->getExtensions().textureCompressionDXT3)
929 {
930 context->handleError(Error(GL_INVALID_OPERATION));
931 return false;
932 }
933 else
934 {
935 context->handleError(Error(GL_INVALID_ENUM));
936 return false;
937 }
938 break;
939 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
940 if (context->getExtensions().textureCompressionDXT5)
941 {
942 context->handleError(Error(GL_INVALID_OPERATION));
943 return false;
944 }
945 else
946 {
947 context->handleError(Error(GL_INVALID_ENUM));
948 return false;
949 }
950 break;
951 case GL_ETC1_RGB8_OES:
952 if (context->getExtensions().compressedETC1RGB8Texture)
953 {
954 context->handleError(Error(GL_INVALID_OPERATION));
955 return false;
956 }
957 else
958 {
959 context->handleError(Error(GL_INVALID_ENUM));
960 return false;
961 }
962 break;
963 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
964 if (context->getExtensions().lossyETCDecode)
965 {
966 context->handleError(Error(GL_INVALID_OPERATION,
967 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
968 return false;
969 }
970 else
971 {
972 context->handleError(Error(
973 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
974 return false;
975 }
976 break;
977 case GL_DEPTH_COMPONENT:
978 case GL_DEPTH_COMPONENT16:
979 case GL_DEPTH_COMPONENT32_OES:
980 case GL_DEPTH_STENCIL_OES:
981 case GL_DEPTH24_STENCIL8_OES:
982 if (context->getExtensions().depthTextures)
983 {
984 context->handleError(Error(GL_INVALID_OPERATION));
985 return false;
986 }
987 else
988 {
989 context->handleError(Error(GL_INVALID_ENUM));
990 return false;
991 }
992 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400993 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400995 }
996 }
997
Geoff Lang784a8fd2013-09-24 12:33:16 -0400998 // If width or height is zero, it is a no-op. Return false without setting an error.
999 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000}
1001
He Yunchaoced53ae2016-11-29 15:00:51 +08001002bool ValidateES2TexStorageParameters(Context *context,
1003 GLenum target,
1004 GLsizei levels,
1005 GLenum internalformat,
1006 GLsizei width,
1007 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008{
1009 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1010 {
Jamie Madill437fa652016-05-03 15:13:24 -04001011 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 }
1014
1015 if (width < 1 || height < 1 || levels < 1)
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 (target == GL_TEXTURE_CUBE_MAP && width != height)
1022 {
Jamie Madill437fa652016-05-03 15:13:24 -04001023 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001024 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025 }
1026
1027 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1028 {
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001030 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 }
1032
Geoff Lang5d601382014-07-22 15:14:06 -04001033 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1034 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 {
Jamie Madill437fa652016-05-03 15:13:24 -04001036 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001037 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001038 }
1039
Geoff Langaae65a42014-05-26 12:43:44 -04001040 const gl::Caps &caps = context->getCaps();
1041
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 switch (target)
1043 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001044 case GL_TEXTURE_2D:
1045 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1046 static_cast<GLuint>(height) > caps.max2DTextureSize)
1047 {
1048 context->handleError(Error(GL_INVALID_VALUE));
1049 return false;
1050 }
1051 break;
1052 case GL_TEXTURE_CUBE_MAP:
1053 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1054 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1055 {
1056 context->handleError(Error(GL_INVALID_VALUE));
1057 return false;
1058 }
1059 break;
1060 default:
1061 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001062 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 }
1064
Geoff Langc0b9ef42014-07-02 10:02:37 -04001065 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001066 {
1067 if (!gl::isPow2(width) || !gl::isPow2(height))
1068 {
Jamie Madill437fa652016-05-03 15:13:24 -04001069 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 }
1072 }
1073
1074 switch (internalformat)
1075 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001076 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1077 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1078 if (!context->getExtensions().textureCompressionDXT1)
1079 {
1080 context->handleError(Error(GL_INVALID_ENUM));
1081 return false;
1082 }
1083 break;
1084 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1085 if (!context->getExtensions().textureCompressionDXT3)
1086 {
1087 context->handleError(Error(GL_INVALID_ENUM));
1088 return false;
1089 }
1090 break;
1091 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1092 if (!context->getExtensions().textureCompressionDXT5)
1093 {
1094 context->handleError(Error(GL_INVALID_ENUM));
1095 return false;
1096 }
1097 break;
1098 case GL_ETC1_RGB8_OES:
1099 if (!context->getExtensions().compressedETC1RGB8Texture)
1100 {
1101 context->handleError(Error(GL_INVALID_ENUM));
1102 return false;
1103 }
1104 break;
1105 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1106 if (!context->getExtensions().lossyETCDecode)
1107 {
1108 context->handleError(
1109 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1110 return false;
1111 }
1112 break;
1113 case GL_RGBA32F_EXT:
1114 case GL_RGB32F_EXT:
1115 case GL_ALPHA32F_EXT:
1116 case GL_LUMINANCE32F_EXT:
1117 case GL_LUMINANCE_ALPHA32F_EXT:
1118 if (!context->getExtensions().textureFloat)
1119 {
1120 context->handleError(Error(GL_INVALID_ENUM));
1121 return false;
1122 }
1123 break;
1124 case GL_RGBA16F_EXT:
1125 case GL_RGB16F_EXT:
1126 case GL_ALPHA16F_EXT:
1127 case GL_LUMINANCE16F_EXT:
1128 case GL_LUMINANCE_ALPHA16F_EXT:
1129 if (!context->getExtensions().textureHalfFloat)
1130 {
1131 context->handleError(Error(GL_INVALID_ENUM));
1132 return false;
1133 }
1134 break;
1135 case GL_R8_EXT:
1136 case GL_RG8_EXT:
1137 case GL_R16F_EXT:
1138 case GL_RG16F_EXT:
1139 case GL_R32F_EXT:
1140 case GL_RG32F_EXT:
1141 if (!context->getExtensions().textureRG)
1142 {
1143 context->handleError(Error(GL_INVALID_ENUM));
1144 return false;
1145 }
1146 break;
1147 case GL_DEPTH_COMPONENT16:
1148 case GL_DEPTH_COMPONENT32_OES:
1149 case GL_DEPTH24_STENCIL8_OES:
1150 if (!context->getExtensions().depthTextures)
1151 {
1152 context->handleError(Error(GL_INVALID_ENUM));
1153 return false;
1154 }
1155 if (target != GL_TEXTURE_2D)
1156 {
1157 context->handleError(Error(GL_INVALID_OPERATION));
1158 return false;
1159 }
1160 // ANGLE_depth_texture only supports 1-level textures
1161 if (levels != 1)
1162 {
1163 context->handleError(Error(GL_INVALID_OPERATION));
1164 return false;
1165 }
1166 break;
1167 default:
1168 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001169 }
1170
Geoff Lang691e58c2014-12-19 17:03:25 -05001171 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 if (!texture || texture->id() == 0)
1173 {
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
Geoff Lang69cce582015-09-17 13:20:36 -04001178 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 {
Jamie Madill437fa652016-05-03 15:13:24 -04001180 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 }
1183
1184 return true;
1185}
1186
He Yunchaoced53ae2016-11-29 15:00:51 +08001187bool ValidateDiscardFramebufferEXT(Context *context,
1188 GLenum target,
1189 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001190 const GLenum *attachments)
1191{
Jamie Madillc29968b2016-01-20 11:17:23 -05001192 if (!context->getExtensions().discardFramebuffer)
1193 {
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001195 return false;
1196 }
1197
Austin Kinross08332632015-05-05 13:35:47 -07001198 bool defaultFramebuffer = false;
1199
1200 switch (target)
1201 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 case GL_FRAMEBUFFER:
1203 defaultFramebuffer =
1204 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1205 break;
1206 default:
1207 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1208 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001209 }
1210
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1212 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001213}
1214
Austin Kinrossbc781f32015-10-26 09:27:38 -07001215bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1216{
1217 if (!context->getExtensions().vertexArrayObject)
1218 {
Jamie Madill437fa652016-05-03 15:13:24 -04001219 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001220 return false;
1221 }
1222
1223 return ValidateBindVertexArrayBase(context, array);
1224}
1225
1226bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1227{
1228 if (!context->getExtensions().vertexArrayObject)
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001231 return false;
1232 }
1233
Olli Etuaho41997e72016-03-10 13:38:39 +02001234 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001235}
1236
1237bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1238{
1239 if (!context->getExtensions().vertexArrayObject)
1240 {
Jamie Madill437fa652016-05-03 15:13:24 -04001241 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001242 return false;
1243 }
1244
Olli Etuaho41997e72016-03-10 13:38:39 +02001245 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001246}
1247
1248bool ValidateIsVertexArrayOES(Context *context)
1249{
1250 if (!context->getExtensions().vertexArrayObject)
1251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253 return false;
1254 }
1255
1256 return true;
1257}
Geoff Langc5629752015-12-07 16:29:04 -05001258
1259bool ValidateProgramBinaryOES(Context *context,
1260 GLuint program,
1261 GLenum binaryFormat,
1262 const void *binary,
1263 GLint length)
1264{
1265 if (!context->getExtensions().getProgramBinary)
1266 {
Jamie Madill437fa652016-05-03 15:13:24 -04001267 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001268 return false;
1269 }
1270
1271 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1272}
1273
1274bool ValidateGetProgramBinaryOES(Context *context,
1275 GLuint program,
1276 GLsizei bufSize,
1277 GLsizei *length,
1278 GLenum *binaryFormat,
1279 void *binary)
1280{
1281 if (!context->getExtensions().getProgramBinary)
1282 {
Jamie Madill437fa652016-05-03 15:13:24 -04001283 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001284 return false;
1285 }
1286
1287 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1288}
Geoff Lange102fee2015-12-10 11:23:30 -05001289
Geoff Lang70d0f492015-12-10 17:45:46 -05001290static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1291{
1292 switch (source)
1293 {
1294 case GL_DEBUG_SOURCE_API:
1295 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1296 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1297 case GL_DEBUG_SOURCE_OTHER:
1298 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1299 return !mustBeThirdPartyOrApplication;
1300
1301 case GL_DEBUG_SOURCE_THIRD_PARTY:
1302 case GL_DEBUG_SOURCE_APPLICATION:
1303 return true;
1304
1305 default:
1306 return false;
1307 }
1308}
1309
1310static bool ValidDebugType(GLenum type)
1311{
1312 switch (type)
1313 {
1314 case GL_DEBUG_TYPE_ERROR:
1315 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1316 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1317 case GL_DEBUG_TYPE_PERFORMANCE:
1318 case GL_DEBUG_TYPE_PORTABILITY:
1319 case GL_DEBUG_TYPE_OTHER:
1320 case GL_DEBUG_TYPE_MARKER:
1321 case GL_DEBUG_TYPE_PUSH_GROUP:
1322 case GL_DEBUG_TYPE_POP_GROUP:
1323 return true;
1324
1325 default:
1326 return false;
1327 }
1328}
1329
1330static bool ValidDebugSeverity(GLenum severity)
1331{
1332 switch (severity)
1333 {
1334 case GL_DEBUG_SEVERITY_HIGH:
1335 case GL_DEBUG_SEVERITY_MEDIUM:
1336 case GL_DEBUG_SEVERITY_LOW:
1337 case GL_DEBUG_SEVERITY_NOTIFICATION:
1338 return true;
1339
1340 default:
1341 return false;
1342 }
1343}
1344
Geoff Lange102fee2015-12-10 11:23:30 -05001345bool ValidateDebugMessageControlKHR(Context *context,
1346 GLenum source,
1347 GLenum type,
1348 GLenum severity,
1349 GLsizei count,
1350 const GLuint *ids,
1351 GLboolean enabled)
1352{
1353 if (!context->getExtensions().debug)
1354 {
Jamie Madill437fa652016-05-03 15:13:24 -04001355 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001356 return false;
1357 }
1358
Geoff Lang70d0f492015-12-10 17:45:46 -05001359 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001362 return false;
1363 }
1364
1365 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001368 return false;
1369 }
1370
1371 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001374 return false;
1375 }
1376
1377 if (count > 0)
1378 {
1379 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001382 GL_INVALID_OPERATION,
1383 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1384 return false;
1385 }
1386
1387 if (severity != GL_DONT_CARE)
1388 {
Jamie Madill437fa652016-05-03 15:13:24 -04001389 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001390 Error(GL_INVALID_OPERATION,
1391 "If count is greater than zero, severity must be GL_DONT_CARE."));
1392 return false;
1393 }
1394 }
1395
Geoff Lange102fee2015-12-10 11:23:30 -05001396 return true;
1397}
1398
1399bool ValidateDebugMessageInsertKHR(Context *context,
1400 GLenum source,
1401 GLenum type,
1402 GLuint id,
1403 GLenum severity,
1404 GLsizei length,
1405 const GLchar *buf)
1406{
1407 if (!context->getExtensions().debug)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001410 return false;
1411 }
1412
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001413 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001414 {
1415 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1416 // not generate an error.
1417 return false;
1418 }
1419
1420 if (!ValidDebugSeverity(severity))
1421 {
Jamie Madill437fa652016-05-03 15:13:24 -04001422 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001423 return false;
1424 }
1425
1426 if (!ValidDebugType(type))
1427 {
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001429 return false;
1430 }
1431
1432 if (!ValidDebugSource(source, true))
1433 {
Jamie Madill437fa652016-05-03 15:13:24 -04001434 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001435 return false;
1436 }
1437
1438 size_t messageLength = (length < 0) ? strlen(buf) : length;
1439 if (messageLength > context->getExtensions().maxDebugMessageLength)
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001442 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1443 return false;
1444 }
1445
Geoff Lange102fee2015-12-10 11:23:30 -05001446 return true;
1447}
1448
1449bool ValidateDebugMessageCallbackKHR(Context *context,
1450 GLDEBUGPROCKHR callback,
1451 const void *userParam)
1452{
1453 if (!context->getExtensions().debug)
1454 {
Jamie Madill437fa652016-05-03 15:13:24 -04001455 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001456 return false;
1457 }
1458
Geoff Lange102fee2015-12-10 11:23:30 -05001459 return true;
1460}
1461
1462bool ValidateGetDebugMessageLogKHR(Context *context,
1463 GLuint count,
1464 GLsizei bufSize,
1465 GLenum *sources,
1466 GLenum *types,
1467 GLuint *ids,
1468 GLenum *severities,
1469 GLsizei *lengths,
1470 GLchar *messageLog)
1471{
1472 if (!context->getExtensions().debug)
1473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001475 return false;
1476 }
1477
Geoff Lang70d0f492015-12-10 17:45:46 -05001478 if (bufSize < 0 && messageLog != nullptr)
1479 {
Jamie Madill437fa652016-05-03 15:13:24 -04001480 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001481 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1482 return false;
1483 }
1484
Geoff Lange102fee2015-12-10 11:23:30 -05001485 return true;
1486}
1487
1488bool ValidatePushDebugGroupKHR(Context *context,
1489 GLenum source,
1490 GLuint id,
1491 GLsizei length,
1492 const GLchar *message)
1493{
1494 if (!context->getExtensions().debug)
1495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001497 return false;
1498 }
1499
Geoff Lang70d0f492015-12-10 17:45:46 -05001500 if (!ValidDebugSource(source, true))
1501 {
Jamie Madill437fa652016-05-03 15:13:24 -04001502 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001503 return false;
1504 }
1505
1506 size_t messageLength = (length < 0) ? strlen(message) : length;
1507 if (messageLength > context->getExtensions().maxDebugMessageLength)
1508 {
Jamie Madill437fa652016-05-03 15:13:24 -04001509 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001510 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1511 return false;
1512 }
1513
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001514 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001515 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1516 {
Jamie Madill437fa652016-05-03 15:13:24 -04001517 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001518 Error(GL_STACK_OVERFLOW,
1519 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1520 return false;
1521 }
1522
Geoff Lange102fee2015-12-10 11:23:30 -05001523 return true;
1524}
1525
1526bool ValidatePopDebugGroupKHR(Context *context)
1527{
1528 if (!context->getExtensions().debug)
1529 {
Jamie Madill437fa652016-05-03 15:13:24 -04001530 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001531 return false;
1532 }
1533
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001534 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001535 if (currentStackSize <= 1)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001538 return false;
1539 }
1540
1541 return true;
1542}
1543
1544static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1545{
1546 switch (identifier)
1547 {
1548 case GL_BUFFER:
1549 if (context->getBuffer(name) == nullptr)
1550 {
Jamie Madill437fa652016-05-03 15:13:24 -04001551 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001552 return false;
1553 }
1554 return true;
1555
1556 case GL_SHADER:
1557 if (context->getShader(name) == nullptr)
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001560 return false;
1561 }
1562 return true;
1563
1564 case GL_PROGRAM:
1565 if (context->getProgram(name) == nullptr)
1566 {
Jamie Madill437fa652016-05-03 15:13:24 -04001567 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001568 return false;
1569 }
1570 return true;
1571
1572 case GL_VERTEX_ARRAY:
1573 if (context->getVertexArray(name) == nullptr)
1574 {
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001576 return false;
1577 }
1578 return true;
1579
1580 case GL_QUERY:
1581 if (context->getQuery(name) == nullptr)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 return false;
1585 }
1586 return true;
1587
1588 case GL_TRANSFORM_FEEDBACK:
1589 if (context->getTransformFeedback(name) == nullptr)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001592 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1593 return false;
1594 }
1595 return true;
1596
1597 case GL_SAMPLER:
1598 if (context->getSampler(name) == nullptr)
1599 {
Jamie Madill437fa652016-05-03 15:13:24 -04001600 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001601 return false;
1602 }
1603 return true;
1604
1605 case GL_TEXTURE:
1606 if (context->getTexture(name) == nullptr)
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001609 return false;
1610 }
1611 return true;
1612
1613 case GL_RENDERBUFFER:
1614 if (context->getRenderbuffer(name) == nullptr)
1615 {
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001617 return false;
1618 }
1619 return true;
1620
1621 case GL_FRAMEBUFFER:
1622 if (context->getFramebuffer(name) == nullptr)
1623 {
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001625 return false;
1626 }
1627 return true;
1628
1629 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001630 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001631 return false;
1632 }
Geoff Lange102fee2015-12-10 11:23:30 -05001633}
1634
Martin Radev9d901792016-07-15 15:58:58 +03001635static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1636{
1637 size_t labelLength = 0;
1638
1639 if (length < 0)
1640 {
1641 if (label != nullptr)
1642 {
1643 labelLength = strlen(label);
1644 }
1645 }
1646 else
1647 {
1648 labelLength = static_cast<size_t>(length);
1649 }
1650
1651 if (labelLength > context->getExtensions().maxLabelLength)
1652 {
1653 context->handleError(
1654 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1655 return false;
1656 }
1657
1658 return true;
1659}
1660
Geoff Lange102fee2015-12-10 11:23:30 -05001661bool ValidateObjectLabelKHR(Context *context,
1662 GLenum identifier,
1663 GLuint name,
1664 GLsizei length,
1665 const GLchar *label)
1666{
1667 if (!context->getExtensions().debug)
1668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001670 return false;
1671 }
1672
Geoff Lang70d0f492015-12-10 17:45:46 -05001673 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1674 {
1675 return false;
1676 }
1677
Martin Radev9d901792016-07-15 15:58:58 +03001678 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001679 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001680 return false;
1681 }
1682
Geoff Lange102fee2015-12-10 11:23:30 -05001683 return true;
1684}
1685
1686bool ValidateGetObjectLabelKHR(Context *context,
1687 GLenum identifier,
1688 GLuint name,
1689 GLsizei bufSize,
1690 GLsizei *length,
1691 GLchar *label)
1692{
1693 if (!context->getExtensions().debug)
1694 {
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001696 return false;
1697 }
1698
Geoff Lang70d0f492015-12-10 17:45:46 -05001699 if (bufSize < 0)
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001702 return false;
1703 }
1704
1705 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1706 {
1707 return false;
1708 }
1709
Martin Radev9d901792016-07-15 15:58:58 +03001710 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001711}
1712
1713static bool ValidateObjectPtrName(Context *context, const void *ptr)
1714{
1715 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1716 {
Jamie Madill437fa652016-05-03 15:13:24 -04001717 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001718 return false;
1719 }
1720
Geoff Lange102fee2015-12-10 11:23:30 -05001721 return true;
1722}
1723
1724bool ValidateObjectPtrLabelKHR(Context *context,
1725 const void *ptr,
1726 GLsizei length,
1727 const GLchar *label)
1728{
1729 if (!context->getExtensions().debug)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001732 return false;
1733 }
1734
Geoff Lang70d0f492015-12-10 17:45:46 -05001735 if (!ValidateObjectPtrName(context, ptr))
1736 {
1737 return false;
1738 }
1739
Martin Radev9d901792016-07-15 15:58:58 +03001740 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001741 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 return false;
1743 }
1744
Geoff Lange102fee2015-12-10 11:23:30 -05001745 return true;
1746}
1747
1748bool ValidateGetObjectPtrLabelKHR(Context *context,
1749 const void *ptr,
1750 GLsizei bufSize,
1751 GLsizei *length,
1752 GLchar *label)
1753{
1754 if (!context->getExtensions().debug)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001757 return false;
1758 }
1759
Geoff Lang70d0f492015-12-10 17:45:46 -05001760 if (bufSize < 0)
1761 {
Jamie Madill437fa652016-05-03 15:13:24 -04001762 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001763 return false;
1764 }
1765
1766 if (!ValidateObjectPtrName(context, ptr))
1767 {
1768 return false;
1769 }
1770
Martin Radev9d901792016-07-15 15:58:58 +03001771 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001772}
1773
1774bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1775{
1776 if (!context->getExtensions().debug)
1777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001779 return false;
1780 }
1781
Geoff Lang70d0f492015-12-10 17:45:46 -05001782 // TODO: represent this in Context::getQueryParameterInfo.
1783 switch (pname)
1784 {
1785 case GL_DEBUG_CALLBACK_FUNCTION:
1786 case GL_DEBUG_CALLBACK_USER_PARAM:
1787 break;
1788
1789 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001791 return false;
1792 }
1793
Geoff Lange102fee2015-12-10 11:23:30 -05001794 return true;
1795}
Jamie Madillc29968b2016-01-20 11:17:23 -05001796
1797bool ValidateBlitFramebufferANGLE(Context *context,
1798 GLint srcX0,
1799 GLint srcY0,
1800 GLint srcX1,
1801 GLint srcY1,
1802 GLint dstX0,
1803 GLint dstY0,
1804 GLint dstX1,
1805 GLint dstY1,
1806 GLbitfield mask,
1807 GLenum filter)
1808{
1809 if (!context->getExtensions().framebufferBlit)
1810 {
Jamie Madill437fa652016-05-03 15:13:24 -04001811 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001812 return false;
1813 }
1814
1815 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1816 {
1817 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001818 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001819 GL_INVALID_OPERATION,
1820 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1821 return false;
1822 }
1823
1824 if (filter == GL_LINEAR)
1825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001827 return false;
1828 }
1829
Jamie Madill51f40ec2016-06-15 14:06:00 -04001830 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1831 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001832
1833 if (mask & GL_COLOR_BUFFER_BIT)
1834 {
1835 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1836 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1837
1838 if (readColorAttachment && drawColorAttachment)
1839 {
1840 if (!(readColorAttachment->type() == GL_TEXTURE &&
1841 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1842 readColorAttachment->type() != GL_RENDERBUFFER &&
1843 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001846 return false;
1847 }
1848
Geoff Langa15472a2015-08-11 11:48:03 -04001849 for (size_t drawbufferIdx = 0;
1850 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 {
Geoff Langa15472a2015-08-11 11:48:03 -04001852 const FramebufferAttachment *attachment =
1853 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1854 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001855 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 if (!(attachment->type() == GL_TEXTURE &&
1857 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1858 attachment->type() != GL_RENDERBUFFER &&
1859 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001862 return false;
1863 }
1864
1865 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001866 if (!Format::SameSized(attachment->getFormat(),
1867 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 return false;
1871 }
1872 }
1873 }
1874
Jamie Madill51f40ec2016-06-15 14:06:00 -04001875 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1877 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882 }
1883 }
1884
1885 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1886 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1887 for (size_t i = 0; i < 2; i++)
1888 {
1889 if (mask & masks[i])
1890 {
1891 const FramebufferAttachment *readBuffer =
1892 readFramebuffer->getAttachment(attachments[i]);
1893 const FramebufferAttachment *drawBuffer =
1894 drawFramebuffer->getAttachment(attachments[i]);
1895
1896 if (readBuffer && drawBuffer)
1897 {
1898 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1899 dstX0, dstY0, dstX1, dstY1))
1900 {
1901 // only whole-buffer copies are permitted
He Yunchaoced53ae2016-11-29 15:00:51 +08001902 ERR("Only whole-buffer depth and stencil blits are supported by this "
Jamie Madillc29968b2016-01-20 11:17:23 -05001903 "implementation.");
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 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001911 return false;
1912 }
1913 }
1914 }
1915 }
1916
1917 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1918 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001919}
Jamie Madillc29968b2016-01-20 11:17:23 -05001920
1921bool ValidateClear(ValidationContext *context, GLbitfield mask)
1922{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001923 auto fbo = context->getGLState().getDrawFramebuffer();
1924 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001925 {
Jamie Madill437fa652016-05-03 15:13:24 -04001926 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001927 return false;
1928 }
1929
1930 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1931 {
Jamie Madill437fa652016-05-03 15:13:24 -04001932 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001933 return false;
1934 }
1935
1936 return true;
1937}
1938
1939bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1940{
1941 if (!context->getExtensions().drawBuffers)
1942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001944 return false;
1945 }
1946
1947 return ValidateDrawBuffersBase(context, n, bufs);
1948}
1949
Jamie Madill73a84962016-02-12 09:27:23 -05001950bool ValidateTexImage2D(Context *context,
1951 GLenum target,
1952 GLint level,
1953 GLint internalformat,
1954 GLsizei width,
1955 GLsizei height,
1956 GLint border,
1957 GLenum format,
1958 GLenum type,
1959 const GLvoid *pixels)
1960{
Martin Radev1be913c2016-07-11 17:59:16 +03001961 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001962 {
1963 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001964 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001965 }
1966
Martin Radev1be913c2016-07-11 17:59:16 +03001967 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001968 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001969 0, 0, width, height, 1, border, format, type, -1,
1970 pixels);
1971}
1972
1973bool ValidateTexImage2DRobust(Context *context,
1974 GLenum target,
1975 GLint level,
1976 GLint internalformat,
1977 GLsizei width,
1978 GLsizei height,
1979 GLint border,
1980 GLenum format,
1981 GLenum type,
1982 GLsizei bufSize,
1983 const GLvoid *pixels)
1984{
1985 if (!ValidateRobustEntryPoint(context, bufSize))
1986 {
1987 return false;
1988 }
1989
1990 if (context->getClientMajorVersion() < 3)
1991 {
1992 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1993 0, 0, width, height, border, format, type, bufSize,
1994 pixels);
1995 }
1996
1997 ASSERT(context->getClientMajorVersion() >= 3);
1998 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1999 0, 0, width, height, 1, border, format, type, bufSize,
2000 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002001}
2002
2003bool ValidateTexSubImage2D(Context *context,
2004 GLenum target,
2005 GLint level,
2006 GLint xoffset,
2007 GLint yoffset,
2008 GLsizei width,
2009 GLsizei height,
2010 GLenum format,
2011 GLenum type,
2012 const GLvoid *pixels)
2013{
2014
Martin Radev1be913c2016-07-11 17:59:16 +03002015 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002016 {
2017 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002018 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002019 }
2020
Martin Radev1be913c2016-07-11 17:59:16 +03002021 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002022 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002023 yoffset, 0, width, height, 1, 0, format, type, -1,
2024 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002025}
2026
Geoff Langc52f6f12016-10-14 10:18:00 -04002027bool ValidateTexSubImage2DRobustANGLE(Context *context,
2028 GLenum target,
2029 GLint level,
2030 GLint xoffset,
2031 GLint yoffset,
2032 GLsizei width,
2033 GLsizei height,
2034 GLenum format,
2035 GLenum type,
2036 GLsizei bufSize,
2037 const GLvoid *pixels)
2038{
2039 if (!ValidateRobustEntryPoint(context, bufSize))
2040 {
2041 return false;
2042 }
2043
2044 if (context->getClientMajorVersion() < 3)
2045 {
2046 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2047 yoffset, width, height, 0, format, type, bufSize,
2048 pixels);
2049 }
2050
2051 ASSERT(context->getClientMajorVersion() >= 3);
2052 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2053 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2054 pixels);
2055}
2056
Jamie Madill73a84962016-02-12 09:27:23 -05002057bool ValidateCompressedTexImage2D(Context *context,
2058 GLenum target,
2059 GLint level,
2060 GLenum internalformat,
2061 GLsizei width,
2062 GLsizei height,
2063 GLint border,
2064 GLsizei imageSize,
2065 const GLvoid *data)
2066{
Martin Radev1be913c2016-07-11 17:59:16 +03002067 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002068 {
2069 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002070 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002071 {
2072 return false;
2073 }
2074 }
2075 else
2076 {
Martin Radev1be913c2016-07-11 17:59:16 +03002077 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002078 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002079 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002080 data))
2081 {
2082 return false;
2083 }
2084 }
2085
2086 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002087 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002088 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002089 if (blockSizeOrErr.isError())
2090 {
2091 context->handleError(blockSizeOrErr.getError());
2092 return false;
2093 }
2094
2095 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002096 {
Jamie Madill437fa652016-05-03 15:13:24 -04002097 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002098 return false;
2099 }
2100
2101 return true;
2102}
2103
2104bool ValidateCompressedTexSubImage2D(Context *context,
2105 GLenum target,
2106 GLint level,
2107 GLint xoffset,
2108 GLint yoffset,
2109 GLsizei width,
2110 GLsizei height,
2111 GLenum format,
2112 GLsizei imageSize,
2113 const GLvoid *data)
2114{
Martin Radev1be913c2016-07-11 17:59:16 +03002115 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002116 {
2117 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002118 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002119 {
2120 return false;
2121 }
2122 }
2123 else
2124 {
Martin Radev1be913c2016-07-11 17:59:16 +03002125 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002126 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002127 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002128 data))
2129 {
2130 return false;
2131 }
2132 }
2133
2134 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002135 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002136 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002137 if (blockSizeOrErr.isError())
2138 {
2139 context->handleError(blockSizeOrErr.getError());
2140 return false;
2141 }
2142
2143 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002144 {
Jamie Madill437fa652016-05-03 15:13:24 -04002145 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002146 return false;
2147 }
2148
2149 return true;
2150}
2151
Olli Etuaho4f667482016-03-30 15:56:35 +03002152bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2153{
Geoff Lang496c02d2016-10-20 11:38:11 -07002154 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002155}
2156
2157bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2158{
2159 if (!context->getExtensions().mapBuffer)
2160 {
Jamie Madill437fa652016-05-03 15:13:24 -04002161 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002162 return false;
2163 }
2164
2165 if (!ValidBufferTarget(context, target))
2166 {
Jamie Madill437fa652016-05-03 15:13:24 -04002167 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002168 return false;
2169 }
2170
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002171 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002172
2173 if (buffer == nullptr)
2174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002176 return false;
2177 }
2178
2179 if (access != GL_WRITE_ONLY_OES)
2180 {
Jamie Madill437fa652016-05-03 15:13:24 -04002181 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002182 return false;
2183 }
2184
2185 if (buffer->isMapped())
2186 {
Jamie Madill437fa652016-05-03 15:13:24 -04002187 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002188 return false;
2189 }
2190
2191 return true;
2192}
2193
2194bool ValidateUnmapBufferOES(Context *context, GLenum target)
2195{
2196 if (!context->getExtensions().mapBuffer)
2197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002199 return false;
2200 }
2201
2202 return ValidateUnmapBufferBase(context, target);
2203}
2204
2205bool ValidateMapBufferRangeEXT(Context *context,
2206 GLenum target,
2207 GLintptr offset,
2208 GLsizeiptr length,
2209 GLbitfield access)
2210{
2211 if (!context->getExtensions().mapBufferRange)
2212 {
Jamie Madill437fa652016-05-03 15:13:24 -04002213 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002214 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2215 return false;
2216 }
2217
2218 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2219}
2220
2221bool ValidateFlushMappedBufferRangeEXT(Context *context,
2222 GLenum target,
2223 GLintptr offset,
2224 GLsizeiptr length)
2225{
2226 if (!context->getExtensions().mapBufferRange)
2227 {
Jamie Madill437fa652016-05-03 15:13:24 -04002228 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002229 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2230 return false;
2231 }
2232
2233 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2234}
2235
Ian Ewell54f87462016-03-10 13:47:21 -05002236bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2237{
2238 Texture *textureObject = context->getTexture(texture);
2239 if (textureObject && textureObject->getTarget() != target && texture != 0)
2240 {
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002242 return false;
2243 }
2244
Geoff Langf41a7152016-09-19 15:11:17 -04002245 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2246 !context->isTextureGenerated(texture))
2247 {
2248 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2249 return false;
2250 }
2251
Ian Ewell54f87462016-03-10 13:47:21 -05002252 switch (target)
2253 {
2254 case GL_TEXTURE_2D:
2255 case GL_TEXTURE_CUBE_MAP:
2256 break;
2257
2258 case GL_TEXTURE_3D:
2259 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002260 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002261 {
Jamie Madill437fa652016-05-03 15:13:24 -04002262 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002263 return false;
2264 }
2265 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002266
2267 case GL_TEXTURE_2D_MULTISAMPLE:
2268 if (context->getClientVersion() < Version(3, 1))
2269 {
2270 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2271 return false;
2272 }
Geoff Lang3b573612016-10-31 14:08:10 -04002273 break;
2274
Ian Ewell54f87462016-03-10 13:47:21 -05002275 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002276 if (!context->getExtensions().eglImageExternal &&
2277 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002278 {
Jamie Madill437fa652016-05-03 15:13:24 -04002279 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002280 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2281 return false;
2282 }
2283 break;
2284 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002285 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002286 return false;
2287 }
2288
2289 return true;
2290}
2291
Geoff Langd8605522016-04-13 10:19:12 -04002292bool ValidateBindUniformLocationCHROMIUM(Context *context,
2293 GLuint program,
2294 GLint location,
2295 const GLchar *name)
2296{
2297 if (!context->getExtensions().bindUniformLocation)
2298 {
Jamie Madill437fa652016-05-03 15:13:24 -04002299 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002300 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2301 return false;
2302 }
2303
2304 Program *programObject = GetValidProgram(context, program);
2305 if (!programObject)
2306 {
2307 return false;
2308 }
2309
2310 if (location < 0)
2311 {
Jamie Madill437fa652016-05-03 15:13:24 -04002312 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002313 return false;
2314 }
2315
2316 const Caps &caps = context->getCaps();
2317 if (static_cast<size_t>(location) >=
2318 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2319 {
Jamie Madill437fa652016-05-03 15:13:24 -04002320 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002321 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2322 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2323 return false;
2324 }
2325
2326 if (strncmp(name, "gl_", 3) == 0)
2327 {
Jamie Madill437fa652016-05-03 15:13:24 -04002328 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002329 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2330 return false;
2331 }
2332
2333 return true;
2334}
2335
Jamie Madille2e406c2016-06-02 13:04:10 -04002336bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002337{
2338 if (!context->getExtensions().framebufferMixedSamples)
2339 {
2340 context->handleError(
2341 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2342 return false;
2343 }
2344 switch (components)
2345 {
2346 case GL_RGB:
2347 case GL_RGBA:
2348 case GL_ALPHA:
2349 case GL_NONE:
2350 break;
2351 default:
2352 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002353 Error(GL_INVALID_ENUM,
2354 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002355 return false;
2356 }
2357
2358 return true;
2359}
2360
Sami Väisänene45e53b2016-05-25 10:36:04 +03002361// CHROMIUM_path_rendering
2362
2363bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2364{
2365 if (!context->getExtensions().pathRendering)
2366 {
2367 context->handleError(
2368 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2369 return false;
2370 }
2371 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2372 {
2373 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2374 return false;
2375 }
2376 if (matrix == nullptr)
2377 {
2378 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2379 return false;
2380 }
2381 return true;
2382}
2383
2384bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2385{
2386 if (!context->getExtensions().pathRendering)
2387 {
2388 context->handleError(
2389 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2390 return false;
2391 }
2392 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2393 {
2394 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2395 return false;
2396 }
2397 return true;
2398}
2399
2400bool ValidateGenPaths(Context *context, GLsizei range)
2401{
2402 if (!context->getExtensions().pathRendering)
2403 {
2404 context->handleError(
2405 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2406 return false;
2407 }
2408
2409 // range = 0 is undefined in NV_path_rendering.
2410 // we add stricter semantic check here and require a non zero positive range.
2411 if (range <= 0)
2412 {
2413 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2414 return false;
2415 }
2416
2417 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2418 {
2419 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2420 return false;
2421 }
2422
2423 return true;
2424}
2425
2426bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2427{
2428 if (!context->getExtensions().pathRendering)
2429 {
2430 context->handleError(
2431 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2432 return false;
2433 }
2434
2435 // range = 0 is undefined in NV_path_rendering.
2436 // we add stricter semantic check here and require a non zero positive range.
2437 if (range <= 0)
2438 {
2439 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2440 return false;
2441 }
2442
2443 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2444 checkedRange += range;
2445
2446 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2447 {
2448 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2449 return false;
2450 }
2451 return true;
2452}
2453
2454bool ValidatePathCommands(Context *context,
2455 GLuint path,
2456 GLsizei numCommands,
2457 const GLubyte *commands,
2458 GLsizei numCoords,
2459 GLenum coordType,
2460 const void *coords)
2461{
2462 if (!context->getExtensions().pathRendering)
2463 {
2464 context->handleError(
2465 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2466 return false;
2467 }
2468 if (!context->hasPath(path))
2469 {
2470 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2471 return false;
2472 }
2473
2474 if (numCommands < 0)
2475 {
2476 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2477 return false;
2478 }
2479 else if (numCommands > 0)
2480 {
2481 if (!commands)
2482 {
2483 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2484 return false;
2485 }
2486 }
2487
2488 if (numCoords < 0)
2489 {
2490 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2491 return false;
2492 }
2493 else if (numCoords > 0)
2494 {
2495 if (!coords)
2496 {
2497 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2498 return false;
2499 }
2500 }
2501
2502 std::uint32_t coordTypeSize = 0;
2503 switch (coordType)
2504 {
2505 case GL_BYTE:
2506 coordTypeSize = sizeof(GLbyte);
2507 break;
2508
2509 case GL_UNSIGNED_BYTE:
2510 coordTypeSize = sizeof(GLubyte);
2511 break;
2512
2513 case GL_SHORT:
2514 coordTypeSize = sizeof(GLshort);
2515 break;
2516
2517 case GL_UNSIGNED_SHORT:
2518 coordTypeSize = sizeof(GLushort);
2519 break;
2520
2521 case GL_FLOAT:
2522 coordTypeSize = sizeof(GLfloat);
2523 break;
2524
2525 default:
2526 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2527 return false;
2528 }
2529
2530 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2531 checkedSize += (coordTypeSize * numCoords);
2532 if (!checkedSize.IsValid())
2533 {
2534 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2535 return false;
2536 }
2537
2538 // early return skips command data validation when it doesn't exist.
2539 if (!commands)
2540 return true;
2541
2542 GLsizei expectedNumCoords = 0;
2543 for (GLsizei i = 0; i < numCommands; ++i)
2544 {
2545 switch (commands[i])
2546 {
2547 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2548 break;
2549 case GL_MOVE_TO_CHROMIUM:
2550 case GL_LINE_TO_CHROMIUM:
2551 expectedNumCoords += 2;
2552 break;
2553 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2554 expectedNumCoords += 4;
2555 break;
2556 case GL_CUBIC_CURVE_TO_CHROMIUM:
2557 expectedNumCoords += 6;
2558 break;
2559 case GL_CONIC_CURVE_TO_CHROMIUM:
2560 expectedNumCoords += 5;
2561 break;
2562 default:
2563 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2564 return false;
2565 }
2566 }
2567 if (expectedNumCoords != numCoords)
2568 {
2569 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2570 return false;
2571 }
2572
2573 return true;
2574}
2575
2576bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2577{
2578 if (!context->getExtensions().pathRendering)
2579 {
2580 context->handleError(
2581 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2582 return false;
2583 }
2584 if (!context->hasPath(path))
2585 {
2586 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2587 return false;
2588 }
2589
2590 switch (pname)
2591 {
2592 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2593 if (value < 0.0f)
2594 {
2595 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2596 return false;
2597 }
2598 break;
2599 case GL_PATH_END_CAPS_CHROMIUM:
2600 switch (static_cast<GLenum>(value))
2601 {
2602 case GL_FLAT_CHROMIUM:
2603 case GL_SQUARE_CHROMIUM:
2604 case GL_ROUND_CHROMIUM:
2605 break;
2606 default:
2607 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2608 return false;
2609 }
2610 break;
2611 case GL_PATH_JOIN_STYLE_CHROMIUM:
2612 switch (static_cast<GLenum>(value))
2613 {
2614 case GL_MITER_REVERT_CHROMIUM:
2615 case GL_BEVEL_CHROMIUM:
2616 case GL_ROUND_CHROMIUM:
2617 break;
2618 default:
2619 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2620 return false;
2621 }
2622 case GL_PATH_MITER_LIMIT_CHROMIUM:
2623 if (value < 0.0f)
2624 {
2625 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2626 return false;
2627 }
2628 break;
2629
2630 case GL_PATH_STROKE_BOUND_CHROMIUM:
2631 // no errors, only clamping.
2632 break;
2633
2634 default:
2635 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2636 return false;
2637 }
2638 return true;
2639}
2640
2641bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2642{
2643 if (!context->getExtensions().pathRendering)
2644 {
2645 context->handleError(
2646 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2647 return false;
2648 }
2649
2650 if (!context->hasPath(path))
2651 {
2652 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2653 return false;
2654 }
2655 if (!value)
2656 {
2657 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2658 return false;
2659 }
2660
2661 switch (pname)
2662 {
2663 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2664 case GL_PATH_END_CAPS_CHROMIUM:
2665 case GL_PATH_JOIN_STYLE_CHROMIUM:
2666 case GL_PATH_MITER_LIMIT_CHROMIUM:
2667 case GL_PATH_STROKE_BOUND_CHROMIUM:
2668 break;
2669
2670 default:
2671 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2672 return false;
2673 }
2674
2675 return true;
2676}
2677
2678bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2679{
2680 if (!context->getExtensions().pathRendering)
2681 {
2682 context->handleError(
2683 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2684 return false;
2685 }
2686
2687 switch (func)
2688 {
2689 case GL_NEVER:
2690 case GL_ALWAYS:
2691 case GL_LESS:
2692 case GL_LEQUAL:
2693 case GL_EQUAL:
2694 case GL_GEQUAL:
2695 case GL_GREATER:
2696 case GL_NOTEQUAL:
2697 break;
2698 default:
2699 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2700 return false;
2701 }
2702
2703 return true;
2704}
2705
2706// Note that the spec specifies that for the path drawing commands
2707// if the path object is not an existing path object the command
2708// does nothing and no error is generated.
2709// However if the path object exists but has not been specified any
2710// commands then an error is generated.
2711
2712bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2713{
2714 if (!context->getExtensions().pathRendering)
2715 {
2716 context->handleError(
2717 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2718 return false;
2719 }
2720 if (context->hasPath(path) && !context->hasPathData(path))
2721 {
2722 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2723 return false;
2724 }
2725
2726 switch (fillMode)
2727 {
2728 case GL_COUNT_UP_CHROMIUM:
2729 case GL_COUNT_DOWN_CHROMIUM:
2730 break;
2731 default:
2732 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2733 return false;
2734 }
2735
2736 if (!isPow2(mask + 1))
2737 {
2738 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2739 return false;
2740 }
2741
2742 return true;
2743}
2744
2745bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2746{
2747 if (!context->getExtensions().pathRendering)
2748 {
2749 context->handleError(
2750 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2751 return false;
2752 }
2753 if (context->hasPath(path) && !context->hasPathData(path))
2754 {
2755 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2756 return false;
2757 }
2758
2759 return true;
2760}
2761
2762bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2763{
2764 if (!context->getExtensions().pathRendering)
2765 {
2766 context->handleError(
2767 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2768 return false;
2769 }
2770 if (context->hasPath(path) && !context->hasPathData(path))
2771 {
2772 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2773 return false;
2774 }
2775
2776 switch (coverMode)
2777 {
2778 case GL_CONVEX_HULL_CHROMIUM:
2779 case GL_BOUNDING_BOX_CHROMIUM:
2780 break;
2781 default:
2782 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2783 return false;
2784 }
2785 return true;
2786}
2787
2788bool ValidateStencilThenCoverFillPath(Context *context,
2789 GLuint path,
2790 GLenum fillMode,
2791 GLuint mask,
2792 GLenum coverMode)
2793{
2794 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2795 ValidateCoverPath(context, path, coverMode);
2796}
2797
2798bool ValidateStencilThenCoverStrokePath(Context *context,
2799 GLuint path,
2800 GLint reference,
2801 GLuint mask,
2802 GLenum coverMode)
2803{
2804 return ValidateStencilStrokePath(context, path, reference, mask) &&
2805 ValidateCoverPath(context, path, coverMode);
2806}
2807
2808bool ValidateIsPath(Context *context)
2809{
2810 if (!context->getExtensions().pathRendering)
2811 {
2812 context->handleError(
2813 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2814 return false;
2815 }
2816 return true;
2817}
2818
Sami Väisänend59ca052016-06-21 16:10:00 +03002819bool ValidateCoverFillPathInstanced(Context *context,
2820 GLsizei numPaths,
2821 GLenum pathNameType,
2822 const void *paths,
2823 GLuint pathBase,
2824 GLenum coverMode,
2825 GLenum transformType,
2826 const GLfloat *transformValues)
2827{
2828 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2829 transformType, transformValues))
2830 return false;
2831
2832 switch (coverMode)
2833 {
2834 case GL_CONVEX_HULL_CHROMIUM:
2835 case GL_BOUNDING_BOX_CHROMIUM:
2836 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2837 break;
2838 default:
2839 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2840 return false;
2841 }
2842
2843 return true;
2844}
2845
2846bool ValidateCoverStrokePathInstanced(Context *context,
2847 GLsizei numPaths,
2848 GLenum pathNameType,
2849 const void *paths,
2850 GLuint pathBase,
2851 GLenum coverMode,
2852 GLenum transformType,
2853 const GLfloat *transformValues)
2854{
2855 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2856 transformType, transformValues))
2857 return false;
2858
2859 switch (coverMode)
2860 {
2861 case GL_CONVEX_HULL_CHROMIUM:
2862 case GL_BOUNDING_BOX_CHROMIUM:
2863 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2864 break;
2865 default:
2866 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2867 return false;
2868 }
2869
2870 return true;
2871}
2872
2873bool ValidateStencilFillPathInstanced(Context *context,
2874 GLsizei numPaths,
2875 GLenum pathNameType,
2876 const void *paths,
2877 GLuint pathBase,
2878 GLenum fillMode,
2879 GLuint mask,
2880 GLenum transformType,
2881 const GLfloat *transformValues)
2882{
2883
2884 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2885 transformType, transformValues))
2886 return false;
2887
2888 switch (fillMode)
2889 {
2890 case GL_COUNT_UP_CHROMIUM:
2891 case GL_COUNT_DOWN_CHROMIUM:
2892 break;
2893 default:
2894 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2895 return false;
2896 }
2897 if (!isPow2(mask + 1))
2898 {
2899 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2900 return false;
2901 }
2902 return true;
2903}
2904
2905bool ValidateStencilStrokePathInstanced(Context *context,
2906 GLsizei numPaths,
2907 GLenum pathNameType,
2908 const void *paths,
2909 GLuint pathBase,
2910 GLint reference,
2911 GLuint mask,
2912 GLenum transformType,
2913 const GLfloat *transformValues)
2914{
2915 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2916 transformType, transformValues))
2917 return false;
2918
2919 // no more validation here.
2920
2921 return true;
2922}
2923
2924bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2925 GLsizei numPaths,
2926 GLenum pathNameType,
2927 const void *paths,
2928 GLuint pathBase,
2929 GLenum fillMode,
2930 GLuint mask,
2931 GLenum coverMode,
2932 GLenum transformType,
2933 const GLfloat *transformValues)
2934{
2935 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2936 transformType, transformValues))
2937 return false;
2938
2939 switch (coverMode)
2940 {
2941 case GL_CONVEX_HULL_CHROMIUM:
2942 case GL_BOUNDING_BOX_CHROMIUM:
2943 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2944 break;
2945 default:
2946 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2947 return false;
2948 }
2949
2950 switch (fillMode)
2951 {
2952 case GL_COUNT_UP_CHROMIUM:
2953 case GL_COUNT_DOWN_CHROMIUM:
2954 break;
2955 default:
2956 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2957 return false;
2958 }
2959 if (!isPow2(mask + 1))
2960 {
2961 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2962 return false;
2963 }
2964
2965 return true;
2966}
2967
2968bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2969 GLsizei numPaths,
2970 GLenum pathNameType,
2971 const void *paths,
2972 GLuint pathBase,
2973 GLint reference,
2974 GLuint mask,
2975 GLenum coverMode,
2976 GLenum transformType,
2977 const GLfloat *transformValues)
2978{
2979 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2980 transformType, transformValues))
2981 return false;
2982
2983 switch (coverMode)
2984 {
2985 case GL_CONVEX_HULL_CHROMIUM:
2986 case GL_BOUNDING_BOX_CHROMIUM:
2987 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2988 break;
2989 default:
2990 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2991 return false;
2992 }
2993
2994 return true;
2995}
2996
Sami Väisänen46eaa942016-06-29 10:26:37 +03002997bool ValidateBindFragmentInputLocation(Context *context,
2998 GLuint program,
2999 GLint location,
3000 const GLchar *name)
3001{
3002 if (!context->getExtensions().pathRendering)
3003 {
3004 context->handleError(
3005 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3006 return false;
3007 }
3008
3009 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3010 if (location >= MaxLocation)
3011 {
3012 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3013 return false;
3014 }
3015
3016 const auto *programObject = context->getProgram(program);
3017 if (!programObject)
3018 {
3019 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3020 return false;
3021 }
3022
3023 if (!name)
3024 {
3025 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3026 return false;
3027 }
3028
3029 if (angle::BeginsWith(name, "gl_"))
3030 {
3031 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3032 return false;
3033 }
3034
3035 return true;
3036}
3037
3038bool ValidateProgramPathFragmentInputGen(Context *context,
3039 GLuint program,
3040 GLint location,
3041 GLenum genMode,
3042 GLint components,
3043 const GLfloat *coeffs)
3044{
3045 if (!context->getExtensions().pathRendering)
3046 {
3047 context->handleError(
3048 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3049 return false;
3050 }
3051
3052 const auto *programObject = context->getProgram(program);
3053 if (!programObject || programObject->isFlaggedForDeletion())
3054 {
3055 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3056 return false;
3057 }
3058
3059 if (!programObject->isLinked())
3060 {
3061 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3062 return false;
3063 }
3064
3065 switch (genMode)
3066 {
3067 case GL_NONE:
3068 if (components != 0)
3069 {
3070 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3071 return false;
3072 }
3073 break;
3074
3075 case GL_OBJECT_LINEAR_CHROMIUM:
3076 case GL_EYE_LINEAR_CHROMIUM:
3077 case GL_CONSTANT_CHROMIUM:
3078 if (components < 1 || components > 4)
3079 {
3080 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3081 return false;
3082 }
3083 if (!coeffs)
3084 {
3085 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3086 return false;
3087 }
3088 break;
3089
3090 default:
3091 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3092 return false;
3093 }
3094
3095 // If the location is -1 then the command is silently ignored
3096 // and no further validation is needed.
3097 if (location == -1)
3098 return true;
3099
3100 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3101
3102 if (!binding.valid)
3103 {
3104 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3105 return false;
3106 }
3107
3108 if (binding.type != GL_NONE)
3109 {
3110 GLint expectedComponents = 0;
3111 switch (binding.type)
3112 {
3113 case GL_FLOAT:
3114 expectedComponents = 1;
3115 break;
3116 case GL_FLOAT_VEC2:
3117 expectedComponents = 2;
3118 break;
3119 case GL_FLOAT_VEC3:
3120 expectedComponents = 3;
3121 break;
3122 case GL_FLOAT_VEC4:
3123 expectedComponents = 4;
3124 break;
3125 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003126 context->handleError(
3127 Error(GL_INVALID_OPERATION,
3128 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003129 return false;
3130 }
3131 if (expectedComponents != components && genMode != GL_NONE)
3132 {
3133 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3134 return false;
3135 }
3136 }
3137 return true;
3138}
3139
Geoff Lang97073d12016-04-20 10:42:34 -07003140bool ValidateCopyTextureCHROMIUM(Context *context,
3141 GLuint sourceId,
3142 GLuint destId,
3143 GLint internalFormat,
3144 GLenum destType,
3145 GLboolean unpackFlipY,
3146 GLboolean unpackPremultiplyAlpha,
3147 GLboolean unpackUnmultiplyAlpha)
3148{
3149 if (!context->getExtensions().copyTexture)
3150 {
3151 context->handleError(
3152 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3153 return false;
3154 }
3155
3156 const gl::Texture *source = context->getTexture(sourceId);
3157 if (source == nullptr)
3158 {
3159 context->handleError(
3160 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3161 return false;
3162 }
3163
3164 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3165 {
3166 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3167 return false;
3168 }
3169
3170 GLenum sourceTarget = source->getTarget();
3171 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3172 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3173 {
3174 context->handleError(
3175 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3176 return false;
3177 }
3178
3179 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3180 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3181 {
3182 context->handleError(
3183 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3184 return false;
3185 }
3186
3187 const gl::Texture *dest = context->getTexture(destId);
3188 if (dest == nullptr)
3189 {
3190 context->handleError(
3191 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3192 return false;
3193 }
3194
3195 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3196 {
3197 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3198 return false;
3199 }
3200
3201 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3202 {
3203 context->handleError(
3204 Error(GL_INVALID_OPERATION,
3205 "Destination internal format and type combination is not valid."));
3206 return false;
3207 }
3208
3209 if (dest->getImmutableFormat())
3210 {
3211 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3212 return false;
3213 }
3214
3215 return true;
3216}
3217
3218bool ValidateCopySubTextureCHROMIUM(Context *context,
3219 GLuint sourceId,
3220 GLuint destId,
3221 GLint xoffset,
3222 GLint yoffset,
3223 GLint x,
3224 GLint y,
3225 GLsizei width,
3226 GLsizei height,
3227 GLboolean unpackFlipY,
3228 GLboolean unpackPremultiplyAlpha,
3229 GLboolean unpackUnmultiplyAlpha)
3230{
3231 if (!context->getExtensions().copyTexture)
3232 {
3233 context->handleError(
3234 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3235 return false;
3236 }
3237
3238 const gl::Texture *source = context->getTexture(sourceId);
3239 if (source == nullptr)
3240 {
3241 context->handleError(
3242 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3243 return false;
3244 }
3245
3246 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3247 {
3248 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3249 return false;
3250 }
3251
3252 GLenum sourceTarget = source->getTarget();
3253 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3254 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3255 {
3256 context->handleError(
3257 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3258 return false;
3259 }
3260
3261 if (x < 0 || y < 0)
3262 {
3263 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3264 return false;
3265 }
3266
3267 if (width < 0 || height < 0)
3268 {
3269 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3270 return false;
3271 }
3272
3273 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3274 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3275 {
3276 context->handleError(
3277 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3278 return false;
3279 }
3280
3281 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3282 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3283 {
3284 context->handleError(
3285 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3286 return false;
3287 }
3288
3289 const gl::Texture *dest = context->getTexture(destId);
3290 if (dest == nullptr)
3291 {
3292 context->handleError(
3293 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3294 return false;
3295 }
3296
3297 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3298 {
3299 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3300 return false;
3301 }
3302
3303 GLenum destTarget = dest->getTarget();
3304 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3305 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3306 {
3307 context->handleError(
3308 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3309 return false;
3310 }
3311
3312 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3313 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3314 {
3315 context->handleError(
3316 Error(GL_INVALID_OPERATION,
3317 "Destination internal format and type combination is not valid."));
3318 return false;
3319 }
3320
3321 if (xoffset < 0 || yoffset < 0)
3322 {
3323 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3324 return false;
3325 }
3326
3327 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3328 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3329 {
3330 context->handleError(
3331 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3332 return false;
3333 }
3334
3335 return true;
3336}
3337
Geoff Lang47110bf2016-04-20 11:13:22 -07003338bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3339{
3340 if (!context->getExtensions().copyCompressedTexture)
3341 {
3342 context->handleError(Error(GL_INVALID_OPERATION,
3343 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3344 return false;
3345 }
3346
3347 const gl::Texture *source = context->getTexture(sourceId);
3348 if (source == nullptr)
3349 {
3350 context->handleError(
3351 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3352 return false;
3353 }
3354
3355 if (source->getTarget() != GL_TEXTURE_2D)
3356 {
3357 context->handleError(
3358 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3359 return false;
3360 }
3361
3362 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3363 {
3364 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3365 return false;
3366 }
3367
3368 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3369 if (!sourceFormat.info->compressed)
3370 {
3371 context->handleError(
3372 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3373 return false;
3374 }
3375
3376 const gl::Texture *dest = context->getTexture(destId);
3377 if (dest == nullptr)
3378 {
3379 context->handleError(
3380 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3381 return false;
3382 }
3383
3384 if (dest->getTarget() != GL_TEXTURE_2D)
3385 {
3386 context->handleError(
3387 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3388 return false;
3389 }
3390
3391 if (dest->getImmutableFormat())
3392 {
3393 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3394 return false;
3395 }
3396
3397 return true;
3398}
3399
Martin Radev4c4c8e72016-08-04 12:25:34 +03003400bool ValidateCreateShader(Context *context, GLenum type)
3401{
3402 switch (type)
3403 {
3404 case GL_VERTEX_SHADER:
3405 case GL_FRAGMENT_SHADER:
3406 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003407
Martin Radev4c4c8e72016-08-04 12:25:34 +03003408 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003409 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003410 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003411 context->handleError(
3412 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3413 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003414 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003415 break;
3416
Martin Radev4c4c8e72016-08-04 12:25:34 +03003417 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003418 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003419 return false;
3420 }
Jamie Madill29639852016-09-02 15:00:09 -04003421
3422 return true;
3423}
3424
3425bool ValidateBufferData(ValidationContext *context,
3426 GLenum target,
3427 GLsizeiptr size,
3428 const GLvoid *data,
3429 GLenum usage)
3430{
3431 if (size < 0)
3432 {
3433 context->handleError(Error(GL_INVALID_VALUE));
3434 return false;
3435 }
3436
3437 switch (usage)
3438 {
3439 case GL_STREAM_DRAW:
3440 case GL_STATIC_DRAW:
3441 case GL_DYNAMIC_DRAW:
3442 break;
3443
3444 case GL_STREAM_READ:
3445 case GL_STREAM_COPY:
3446 case GL_STATIC_READ:
3447 case GL_STATIC_COPY:
3448 case GL_DYNAMIC_READ:
3449 case GL_DYNAMIC_COPY:
3450 if (context->getClientMajorVersion() < 3)
3451 {
3452 context->handleError(Error(GL_INVALID_ENUM));
3453 return false;
3454 }
3455 break;
3456
3457 default:
3458 context->handleError(Error(GL_INVALID_ENUM));
3459 return false;
3460 }
3461
3462 if (!ValidBufferTarget(context, target))
3463 {
3464 context->handleError(Error(GL_INVALID_ENUM));
3465 return false;
3466 }
3467
3468 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3469
3470 if (!buffer)
3471 {
3472 context->handleError(Error(GL_INVALID_OPERATION));
3473 return false;
3474 }
3475
3476 return true;
3477}
3478
3479bool ValidateBufferSubData(ValidationContext *context,
3480 GLenum target,
3481 GLintptr offset,
3482 GLsizeiptr size,
3483 const GLvoid *data)
3484{
3485 if (size < 0 || offset < 0)
3486 {
3487 context->handleError(Error(GL_INVALID_VALUE));
3488 return false;
3489 }
3490
3491 if (!ValidBufferTarget(context, target))
3492 {
3493 context->handleError(Error(GL_INVALID_ENUM));
3494 return false;
3495 }
3496
3497 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3498
3499 if (!buffer)
3500 {
3501 context->handleError(Error(GL_INVALID_OPERATION));
3502 return false;
3503 }
3504
3505 if (buffer->isMapped())
3506 {
3507 context->handleError(Error(GL_INVALID_OPERATION));
3508 return false;
3509 }
3510
3511 // Check for possible overflow of size + offset
3512 angle::CheckedNumeric<size_t> checkedSize(size);
3513 checkedSize += offset;
3514 if (!checkedSize.IsValid())
3515 {
3516 context->handleError(Error(GL_OUT_OF_MEMORY));
3517 return false;
3518 }
3519
3520 if (size + offset > buffer->getSize())
3521 {
3522 context->handleError(Error(GL_INVALID_VALUE));
3523 return false;
3524 }
3525
Martin Radev4c4c8e72016-08-04 12:25:34 +03003526 return true;
3527}
3528
Geoff Langc339c4e2016-11-29 10:37:36 -05003529bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003530{
Geoff Langc339c4e2016-11-29 10:37:36 -05003531 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003532 {
3533 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003534 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003535 return false;
3536 }
3537
3538 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3539 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003540 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003541 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003542 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003543 return false;
3544 }
3545
3546 return true;
3547}
3548
Jamie Madillef300b12016-10-07 15:12:09 -04003549bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3550{
3551 if (texture < GL_TEXTURE0 ||
3552 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3553 {
3554 context->handleError(Error(GL_INVALID_ENUM));
3555 return false;
3556 }
3557
3558 return true;
3559}
3560
3561bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3562{
3563 Program *programObject = GetValidProgram(context, program);
3564 if (!programObject)
3565 {
3566 return false;
3567 }
3568
3569 Shader *shaderObject = GetValidShader(context, shader);
3570 if (!shaderObject)
3571 {
3572 return false;
3573 }
3574
3575 switch (shaderObject->getType())
3576 {
3577 case GL_VERTEX_SHADER:
3578 {
3579 if (programObject->getAttachedVertexShader())
3580 {
3581 context->handleError(Error(GL_INVALID_OPERATION));
3582 return false;
3583 }
3584 break;
3585 }
3586 case GL_FRAGMENT_SHADER:
3587 {
3588 if (programObject->getAttachedFragmentShader())
3589 {
3590 context->handleError(Error(GL_INVALID_OPERATION));
3591 return false;
3592 }
3593 break;
3594 }
3595 case GL_COMPUTE_SHADER:
3596 {
3597 if (programObject->getAttachedComputeShader())
3598 {
3599 context->handleError(Error(GL_INVALID_OPERATION));
3600 return false;
3601 }
3602 break;
3603 }
3604 default:
3605 UNREACHABLE();
3606 break;
3607 }
3608
3609 return true;
3610}
3611
Jamie Madill01a80ee2016-11-07 12:06:18 -05003612bool ValidateBindAttribLocation(ValidationContext *context,
3613 GLuint program,
3614 GLuint index,
3615 const GLchar *name)
3616{
3617 if (index >= MAX_VERTEX_ATTRIBS)
3618 {
3619 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3620 return false;
3621 }
3622
3623 if (strncmp(name, "gl_", 3) == 0)
3624 {
3625 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3626 return false;
3627 }
3628
3629 return GetValidProgram(context, program) != nullptr;
3630}
3631
3632bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3633{
3634 if (!ValidBufferTarget(context, target))
3635 {
3636 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3637 return false;
3638 }
3639
3640 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3641 !context->isBufferGenerated(buffer))
3642 {
3643 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3644 return false;
3645 }
3646
3647 return true;
3648}
3649
3650bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3651{
3652 if (!ValidFramebufferTarget(target))
3653 {
3654 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3655 return false;
3656 }
3657
3658 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3659 !context->isFramebufferGenerated(framebuffer))
3660 {
3661 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3662 return false;
3663 }
3664
3665 return true;
3666}
3667
3668bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3669{
3670 if (target != GL_RENDERBUFFER)
3671 {
3672 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3673 return false;
3674 }
3675
3676 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3677 !context->isRenderbufferGenerated(renderbuffer))
3678 {
3679 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3680 return false;
3681 }
3682
3683 return true;
3684}
3685
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003686static bool ValidBlendEquationMode(GLenum mode)
3687{
3688 switch (mode)
3689 {
3690 case GL_FUNC_ADD:
3691 case GL_FUNC_SUBTRACT:
3692 case GL_FUNC_REVERSE_SUBTRACT:
3693 case GL_MIN:
3694 case GL_MAX:
3695 return true;
3696
3697 default:
3698 return false;
3699 }
3700}
3701
3702bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3703{
3704 if (!ValidBlendEquationMode(mode))
3705 {
3706 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3707 return false;
3708 }
3709
3710 return true;
3711}
3712
3713bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3714{
3715 if (!ValidBlendEquationMode(modeRGB))
3716 {
3717 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3718 return false;
3719 }
3720
3721 if (!ValidBlendEquationMode(modeAlpha))
3722 {
3723 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3724 return false;
3725 }
3726
3727 return true;
3728}
3729
3730bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3731{
3732 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3733}
3734
3735static bool ValidSrcBlendFunc(GLenum srcBlend)
3736{
3737 switch (srcBlend)
3738 {
3739 case GL_ZERO:
3740 case GL_ONE:
3741 case GL_SRC_COLOR:
3742 case GL_ONE_MINUS_SRC_COLOR:
3743 case GL_DST_COLOR:
3744 case GL_ONE_MINUS_DST_COLOR:
3745 case GL_SRC_ALPHA:
3746 case GL_ONE_MINUS_SRC_ALPHA:
3747 case GL_DST_ALPHA:
3748 case GL_ONE_MINUS_DST_ALPHA:
3749 case GL_CONSTANT_COLOR:
3750 case GL_ONE_MINUS_CONSTANT_COLOR:
3751 case GL_CONSTANT_ALPHA:
3752 case GL_ONE_MINUS_CONSTANT_ALPHA:
3753 case GL_SRC_ALPHA_SATURATE:
3754 return true;
3755
3756 default:
3757 return false;
3758 }
3759}
3760
3761static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3762{
3763 switch (dstBlend)
3764 {
3765 case GL_ZERO:
3766 case GL_ONE:
3767 case GL_SRC_COLOR:
3768 case GL_ONE_MINUS_SRC_COLOR:
3769 case GL_DST_COLOR:
3770 case GL_ONE_MINUS_DST_COLOR:
3771 case GL_SRC_ALPHA:
3772 case GL_ONE_MINUS_SRC_ALPHA:
3773 case GL_DST_ALPHA:
3774 case GL_ONE_MINUS_DST_ALPHA:
3775 case GL_CONSTANT_COLOR:
3776 case GL_ONE_MINUS_CONSTANT_COLOR:
3777 case GL_CONSTANT_ALPHA:
3778 case GL_ONE_MINUS_CONSTANT_ALPHA:
3779 return true;
3780
3781 case GL_SRC_ALPHA_SATURATE:
3782 return (contextMajorVersion >= 3);
3783
3784 default:
3785 return false;
3786 }
3787}
3788
3789bool ValidateBlendFuncSeparate(ValidationContext *context,
3790 GLenum srcRGB,
3791 GLenum dstRGB,
3792 GLenum srcAlpha,
3793 GLenum dstAlpha)
3794{
3795 if (!ValidSrcBlendFunc(srcRGB))
3796 {
3797 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3798 return false;
3799 }
3800
3801 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3802 {
3803 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3804 return false;
3805 }
3806
3807 if (!ValidSrcBlendFunc(srcAlpha))
3808 {
3809 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3810 return false;
3811 }
3812
3813 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3814 {
3815 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3816 return false;
3817 }
3818
3819 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3820 {
3821 bool constantColorUsed =
3822 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3823 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3824
3825 bool constantAlphaUsed =
3826 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3827 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3828
3829 if (constantColorUsed && constantAlphaUsed)
3830 {
3831 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3832 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3833 "implementation.");
3834 context->handleError(Error(GL_INVALID_OPERATION,
3835 "Simultaneous use of "
3836 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3837 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3838 "supported by this implementation."));
3839 return false;
3840 }
3841 }
3842
3843 return true;
3844}
3845
Geoff Langc339c4e2016-11-29 10:37:36 -05003846bool ValidateGetString(Context *context, GLenum name)
3847{
3848 switch (name)
3849 {
3850 case GL_VENDOR:
3851 case GL_RENDERER:
3852 case GL_VERSION:
3853 case GL_SHADING_LANGUAGE_VERSION:
3854 case GL_EXTENSIONS:
3855 break;
3856
3857 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3858 if (!context->getExtensions().requestExtension)
3859 {
3860 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3861 return false;
3862 }
3863 break;
3864
3865 default:
3866 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3867 return false;
3868 }
3869
3870 return true;
3871}
3872
Geoff Lang47c48082016-12-07 15:38:13 -05003873bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3874{
3875 if (width <= 0.0f || isNaN(width))
3876 {
3877 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3878 return false;
3879 }
3880
3881 return true;
3882}
3883
Jamie Madillc29968b2016-01-20 11:17:23 -05003884} // namespace gl