blob: af93da2d593cec8ca0f3edba6d2b5e42cf896dd2 [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"
Brandon Jones6cad5662017-06-14 13:25:13 -070017#include "libANGLE/ErrorStrings.h"
Jamie Madillef300b12016-10-07 15:12:09 -040018#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/Texture.h"
Jamie Madillef300b12016-10-07 15:12:09 -040023#include "libANGLE/Uniform.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/VertexArray.h"
Jamie Madillef300b12016-10-07 15:12:09 -040025#include "libANGLE/formatutils.h"
26#include "libANGLE/validationES.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29namespace gl
30{
31
Jamie Madillc29968b2016-01-20 11:17:23 -050032namespace
33{
34
35bool IsPartialBlit(gl::Context *context,
36 const FramebufferAttachment *readBuffer,
37 const FramebufferAttachment *writeBuffer,
38 GLint srcX0,
39 GLint srcY0,
40 GLint srcX1,
41 GLint srcY1,
42 GLint dstX0,
43 GLint dstY0,
44 GLint dstX1,
45 GLint dstY1)
46{
47 const Extents &writeSize = writeBuffer->getSize();
48 const Extents &readSize = readBuffer->getSize();
49
50 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
51 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
52 {
53 return true;
54 }
55
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050057 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070058 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050059 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
60 scissor.height < writeSize.height;
61 }
62
63 return false;
64}
65
Sami Väisänend59ca052016-06-21 16:10:00 +030066template <typename T>
67bool ValidatePathInstances(gl::Context *context,
68 GLsizei numPaths,
69 const void *paths,
70 GLuint pathBase)
71{
72 const auto *array = static_cast<const T *>(paths);
73
74 for (GLsizei i = 0; i < numPaths; ++i)
75 {
76 const GLuint pathName = array[i] + pathBase;
77 if (context->hasPath(pathName) && !context->hasPathData(pathName))
78 {
Brandon Jonesafa75152017-07-21 13:11:29 -070079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänend59ca052016-06-21 16:10:00 +030080 return false;
81 }
82 }
83 return true;
84}
85
86bool ValidateInstancedPathParameters(gl::Context *context,
87 GLsizei numPaths,
88 GLenum pathNameType,
89 const void *paths,
90 GLuint pathBase,
91 GLenum transformType,
92 const GLfloat *transformValues)
93{
94 if (!context->getExtensions().pathRendering)
95 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050096 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänend59ca052016-06-21 16:10:00 +030097 return false;
98 }
99
100 if (paths == nullptr)
101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500102 context->handleError(InvalidValue() << "No path name array.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300103 return false;
104 }
105
106 if (numPaths < 0)
107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500108 context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500160 context->handleError(InvalidEnum() << "Invalid path name type.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500188 context->handleError(InvalidEnum() << "Invalid transformation.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidValue() << "No transform array given.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang4f0e0032017-05-01 16:04:35 -0400209bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700210{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400211 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400212 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700213 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400214 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700215 case GL_ALPHA:
216 case GL_LUMINANCE:
217 case GL_LUMINANCE_ALPHA:
218 case GL_RGB:
219 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400220 case GL_RGB8:
221 case GL_RGBA8:
222 case GL_BGRA_EXT:
223 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700224 return true;
225
Geoff Lang4f0e0032017-05-01 16:04:35 -0400226 default:
227 return false;
228 }
229}
Geoff Lang97073d12016-04-20 10:42:34 -0700230
Geoff Lang4f0e0032017-05-01 16:04:35 -0400231bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
232{
233 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
234}
235
Geoff Lang4f0e0032017-05-01 16:04:35 -0400236bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
237{
238 // Table 1.0 from the CHROMIUM_copy_texture spec
239 switch (internalFormat)
240 {
241 case GL_RGB:
242 case GL_RGBA:
243 case GL_RGB8:
244 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700245 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400246 case GL_BGRA8_EXT:
247 case GL_SRGB_EXT:
248 case GL_SRGB_ALPHA_EXT:
249 case GL_R8:
250 case GL_R8UI:
251 case GL_RG8:
252 case GL_RG8UI:
253 case GL_SRGB8:
254 case GL_RGB565:
255 case GL_RGB8UI:
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400256 case GL_RGB10_A2:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400257 case GL_SRGB8_ALPHA8:
258 case GL_RGB5_A1:
259 case GL_RGBA4:
260 case GL_RGBA8UI:
261 case GL_RGB9_E5:
262 case GL_R16F:
263 case GL_R32F:
264 case GL_RG16F:
265 case GL_RG32F:
266 case GL_RGB16F:
267 case GL_RGB32F:
268 case GL_RGBA16F:
269 case GL_RGBA32F:
270 case GL_R11F_G11F_B10F:
Brandon Jones340b7b82017-06-26 13:02:31 -0700271 case GL_LUMINANCE:
272 case GL_LUMINANCE_ALPHA:
273 case GL_ALPHA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400274 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700275
276 default:
277 return false;
278 }
279}
280
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400281bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
282{
283 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
284}
285
Geoff Lang97073d12016-04-20 10:42:34 -0700286bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
287{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400288 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700289 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400290 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700291 }
292
Geoff Langc0094ec2017-08-16 14:16:24 -0400293 if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
294 {
295 context->handleError(InvalidOperation()
296 << "Invalid combination of type and internalFormat.");
297 return false;
298 }
299
Geoff Lang4f0e0032017-05-01 16:04:35 -0400300 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
301 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700302 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400303 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700304 }
305
306 return true;
307}
308
Geoff Lang63458a32017-10-30 15:16:53 -0400309bool IsValidCopyTextureDestinationTargetEnum(Context *context, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700310{
311 switch (target)
312 {
313 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400314 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
315 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
316 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
317 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
318 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
319 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Lang63458a32017-10-30 15:16:53 -0400320 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700321
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400322 case GL_TEXTURE_RECTANGLE_ANGLE:
Geoff Lang63458a32017-10-30 15:16:53 -0400323 return context->getExtensions().textureRectangle;
Geoff Lang97073d12016-04-20 10:42:34 -0700324
325 default:
326 return false;
327 }
328}
329
Geoff Lang63458a32017-10-30 15:16:53 -0400330bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
331{
332 if (IsCubeMapTextureTarget(target))
333 {
334 return textureType == GL_TEXTURE_CUBE_MAP;
335 }
336 else
337 {
338 return textureType == target;
339 }
340}
341
Geoff Lang97073d12016-04-20 10:42:34 -0700342bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
343{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400344 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700345 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400346 case GL_TEXTURE_2D:
347 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400348 case GL_TEXTURE_RECTANGLE_ANGLE:
349 return context->getExtensions().textureRectangle;
Geoff Lang4f0e0032017-05-01 16:04:35 -0400350
351 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
352 // supported
353
354 default:
355 return false;
356 }
357}
358
359bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
360{
Geoff Lang3847f942017-07-12 11:17:28 -0400361 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400362 {
363 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700364 }
365
Geoff Lang4f0e0032017-05-01 16:04:35 -0400366 if (level > 0 && context->getClientVersion() < ES_3_0)
367 {
368 return false;
369 }
Geoff Lang97073d12016-04-20 10:42:34 -0700370
Geoff Lang4f0e0032017-05-01 16:04:35 -0400371 return true;
372}
373
374bool IsValidCopyTextureDestinationLevel(Context *context,
375 GLenum target,
376 GLint level,
377 GLsizei width,
378 GLsizei height)
379{
Geoff Lang3847f942017-07-12 11:17:28 -0400380 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400381 {
382 return false;
383 }
384
Geoff Lang4f0e0032017-05-01 16:04:35 -0400385 const Caps &caps = context->getCaps();
386 if (target == GL_TEXTURE_2D)
387 {
388 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
389 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
390 {
391 return false;
392 }
393 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400394 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
395 {
396 ASSERT(level == 0);
397 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
398 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
399 {
400 return false;
401 }
402 }
Geoff Lang4f0e0032017-05-01 16:04:35 -0400403 else if (IsCubeMapTextureTarget(target))
404 {
405 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
406 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
407 {
408 return false;
409 }
410 }
411
412 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700413}
414
Jamie Madillc1d770e2017-04-13 17:31:24 -0400415bool IsValidStencilFunc(GLenum func)
416{
417 switch (func)
418 {
419 case GL_NEVER:
420 case GL_ALWAYS:
421 case GL_LESS:
422 case GL_LEQUAL:
423 case GL_EQUAL:
424 case GL_GEQUAL:
425 case GL_GREATER:
426 case GL_NOTEQUAL:
427 return true;
428
429 default:
430 return false;
431 }
432}
433
434bool IsValidStencilFace(GLenum face)
435{
436 switch (face)
437 {
438 case GL_FRONT:
439 case GL_BACK:
440 case GL_FRONT_AND_BACK:
441 return true;
442
443 default:
444 return false;
445 }
446}
447
448bool IsValidStencilOp(GLenum op)
449{
450 switch (op)
451 {
452 case GL_ZERO:
453 case GL_KEEP:
454 case GL_REPLACE:
455 case GL_INCR:
456 case GL_DECR:
457 case GL_INVERT:
458 case GL_INCR_WRAP:
459 case GL_DECR_WRAP:
460 return true;
461
462 default:
463 return false;
464 }
465}
466
Jamie Madillbe849e42017-05-02 15:49:00 -0400467bool ValidateES2CopyTexImageParameters(ValidationContext *context,
468 GLenum target,
469 GLint level,
470 GLenum internalformat,
471 bool isSubImage,
472 GLint xoffset,
473 GLint yoffset,
474 GLint x,
475 GLint y,
476 GLsizei width,
477 GLsizei height,
478 GLint border)
479{
480 if (!ValidTexture2DDestinationTarget(context, target))
481 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400483 return false;
484 }
485
486 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500488 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400489 return false;
490 }
491
492 Format textureFormat = Format::Invalid();
493 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
494 xoffset, yoffset, 0, x, y, width, height, border,
495 &textureFormat))
496 {
497 return false;
498 }
499
500 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
501 GLenum colorbufferFormat =
502 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
503 const auto &formatInfo = *textureFormat.info;
504
505 // [OpenGL ES 2.0.24] table 3.9
506 if (isSubImage)
507 {
508 switch (formatInfo.format)
509 {
510 case GL_ALPHA:
511 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400512 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
513 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400514 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700515 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400516 return false;
517 }
518 break;
519 case GL_LUMINANCE:
520 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
521 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
522 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400523 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
524 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400525 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700526 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400527 return false;
528 }
529 break;
530 case GL_RED_EXT:
531 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
532 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
533 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
534 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
535 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400536 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
537 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400538 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700539 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400540 return false;
541 }
542 break;
543 case GL_RG_EXT:
544 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
545 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
546 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
547 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400548 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
549 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400550 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400552 return false;
553 }
554 break;
555 case GL_RGB:
556 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
557 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
558 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400559 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
560 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400561 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400563 return false;
564 }
565 break;
566 case GL_LUMINANCE_ALPHA:
567 case GL_RGBA:
568 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400569 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
570 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400571 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700572 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400573 return false;
574 }
575 break;
576 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
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 case GL_ETC1_RGB8_OES:
581 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
582 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
583 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
584 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
585 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700586 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400587 return false;
588 case GL_DEPTH_COMPONENT:
589 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400591 return false;
592 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400594 return false;
595 }
596
597 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
598 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400600 return false;
601 }
602 }
603 else
604 {
605 switch (internalformat)
606 {
607 case GL_ALPHA:
608 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
609 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
610 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
611 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700612 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400613 return false;
614 }
615 break;
616 case GL_LUMINANCE:
617 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
618 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
619 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
620 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
621 colorbufferFormat != GL_BGR5_A1_ANGLEX)
622 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700623 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400624 return false;
625 }
626 break;
627 case GL_RED_EXT:
628 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
629 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
630 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
631 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
632 colorbufferFormat != GL_BGR5_A1_ANGLEX)
633 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 return false;
636 }
637 break;
638 case GL_RG_EXT:
639 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
640 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
641 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
642 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
643 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400645 return false;
646 }
647 break;
648 case GL_RGB:
649 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
650 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
651 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
652 colorbufferFormat != GL_BGR5_A1_ANGLEX)
653 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400655 return false;
656 }
657 break;
658 case GL_LUMINANCE_ALPHA:
659 case GL_RGBA:
660 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
661 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
662 colorbufferFormat != GL_BGR5_A1_ANGLEX)
663 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666 }
667 break;
668 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
669 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
670 if (context->getExtensions().textureCompressionDXT1)
671 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400673 return false;
674 }
675 else
676 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700677 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400678 return false;
679 }
680 break;
681 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
682 if (context->getExtensions().textureCompressionDXT3)
683 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400685 return false;
686 }
687 else
688 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700689 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400690 return false;
691 }
692 break;
693 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
694 if (context->getExtensions().textureCompressionDXT5)
695 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700696 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400697 return false;
698 }
699 else
700 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700701 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400702 return false;
703 }
704 break;
705 case GL_ETC1_RGB8_OES:
706 if (context->getExtensions().compressedETC1RGB8Texture)
707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500708 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400709 return false;
710 }
711 else
712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500713 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400714 return false;
715 }
716 break;
717 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
718 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
719 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
720 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
721 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
722 if (context->getExtensions().lossyETCDecode)
723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500724 context->handleError(InvalidOperation()
725 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400726 return false;
727 }
728 else
729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500730 context->handleError(InvalidEnum()
731 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400732 return false;
733 }
734 break;
735 case GL_DEPTH_COMPONENT:
736 case GL_DEPTH_COMPONENT16:
737 case GL_DEPTH_COMPONENT32_OES:
738 case GL_DEPTH_STENCIL_OES:
739 case GL_DEPTH24_STENCIL8_OES:
740 if (context->getExtensions().depthTextures)
741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500742 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400743 return false;
744 }
745 else
746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500747 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400748 return false;
749 }
750 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500751 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400752 return false;
753 }
754 }
755
756 // If width or height is zero, it is a no-op. Return false without setting an error.
757 return (width > 0 && height > 0);
758}
759
760bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
761{
762 switch (cap)
763 {
764 // EXT_multisample_compatibility
765 case GL_MULTISAMPLE_EXT:
766 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
767 return context->getExtensions().multisampleCompatibility;
768
769 case GL_CULL_FACE:
770 case GL_POLYGON_OFFSET_FILL:
771 case GL_SAMPLE_ALPHA_TO_COVERAGE:
772 case GL_SAMPLE_COVERAGE:
773 case GL_SCISSOR_TEST:
774 case GL_STENCIL_TEST:
775 case GL_DEPTH_TEST:
776 case GL_BLEND:
777 case GL_DITHER:
778 return true;
779
780 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
781 case GL_RASTERIZER_DISCARD:
782 return (context->getClientMajorVersion() >= 3);
783
784 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
785 case GL_DEBUG_OUTPUT:
786 return context->getExtensions().debug;
787
788 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
789 return queryOnly && context->getExtensions().bindGeneratesResource;
790
791 case GL_CLIENT_ARRAYS_ANGLE:
792 return queryOnly && context->getExtensions().clientArrays;
793
794 case GL_FRAMEBUFFER_SRGB_EXT:
795 return context->getExtensions().sRGBWriteControl;
796
797 case GL_SAMPLE_MASK:
798 return context->getClientVersion() >= Version(3, 1);
799
Geoff Langb433e872017-10-05 14:01:47 -0400800 case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
Jamie Madillbe849e42017-05-02 15:49:00 -0400801 return queryOnly && context->getExtensions().robustResourceInitialization;
802
803 default:
804 return false;
805 }
806}
807
Geoff Langfc32e8b2017-05-31 14:16:59 -0400808// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
809// 3.1.
Geoff Langcab92ee2017-07-19 17:32:07 -0400810bool IsValidESSLCharacter(unsigned char c)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400811{
812 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langcab92ee2017-07-19 17:32:07 -0400813 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
814 c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400815 {
816 return true;
817 }
818
819 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
820 if (c >= 9 && c <= 13)
821 {
822 return true;
823 }
824
825 return false;
826}
827
Geoff Langcab92ee2017-07-19 17:32:07 -0400828bool IsValidESSLString(const char *str, size_t len)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400829{
Geoff Langa71a98e2017-06-19 15:15:00 -0400830 for (size_t i = 0; i < len; i++)
831 {
Geoff Langcab92ee2017-07-19 17:32:07 -0400832 if (!IsValidESSLCharacter(str[i]))
Geoff Langa71a98e2017-06-19 15:15:00 -0400833 {
834 return false;
835 }
836 }
837
838 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400839}
840
Geoff Langcab92ee2017-07-19 17:32:07 -0400841bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
842{
843 enum class ParseState
844 {
845 // Have not seen an ASCII non-whitespace character yet on
846 // this line. Possible that we might see a preprocessor
847 // directive.
848 BEGINING_OF_LINE,
849
850 // Have seen at least one ASCII non-whitespace character
851 // on this line.
852 MIDDLE_OF_LINE,
853
854 // Handling a preprocessor directive. Passes through all
855 // characters up to the end of the line. Disables comment
856 // processing.
857 IN_PREPROCESSOR_DIRECTIVE,
858
859 // Handling a single-line comment. The comment text is
860 // replaced with a single space.
861 IN_SINGLE_LINE_COMMENT,
862
863 // Handling a multi-line comment. Newlines are passed
864 // through to preserve line numbers.
865 IN_MULTI_LINE_COMMENT
866 };
867
868 ParseState state = ParseState::BEGINING_OF_LINE;
869 size_t pos = 0;
870
871 while (pos < len)
872 {
873 char c = str[pos];
874 char next = pos + 1 < len ? str[pos + 1] : 0;
875
876 // Check for newlines
877 if (c == '\n' || c == '\r')
878 {
879 if (state != ParseState::IN_MULTI_LINE_COMMENT)
880 {
881 state = ParseState::BEGINING_OF_LINE;
882 }
883
884 pos++;
885 continue;
886 }
887
888 switch (state)
889 {
890 case ParseState::BEGINING_OF_LINE:
891 if (c == ' ')
892 {
893 // Maintain the BEGINING_OF_LINE state until a non-space is seen
894 pos++;
895 }
896 else if (c == '#')
897 {
898 state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
899 pos++;
900 }
901 else
902 {
903 // Don't advance, re-process this character with the MIDDLE_OF_LINE state
904 state = ParseState::MIDDLE_OF_LINE;
905 }
906 break;
907
908 case ParseState::MIDDLE_OF_LINE:
909 if (c == '/' && next == '/')
910 {
911 state = ParseState::IN_SINGLE_LINE_COMMENT;
912 pos++;
913 }
914 else if (c == '/' && next == '*')
915 {
916 state = ParseState::IN_MULTI_LINE_COMMENT;
917 pos++;
918 }
919 else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
920 {
921 // Skip line continuation characters
922 }
923 else if (!IsValidESSLCharacter(c))
924 {
925 return false;
926 }
927 pos++;
928 break;
929
930 case ParseState::IN_PREPROCESSOR_DIRECTIVE:
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -0700931 // Line-continuation characters may not be permitted.
932 // Otherwise, just pass it through. Do not parse comments in this state.
933 if (!lineContinuationAllowed && c == '\\')
934 {
935 return false;
936 }
Geoff Langcab92ee2017-07-19 17:32:07 -0400937 pos++;
938 break;
939
940 case ParseState::IN_SINGLE_LINE_COMMENT:
941 // Line-continuation characters are processed before comment processing.
942 // Advance string if a new line character is immediately behind
943 // line-continuation character.
944 if (c == '\\' && (next == '\n' || next == '\r'))
945 {
946 pos++;
947 }
948 pos++;
949 break;
950
951 case ParseState::IN_MULTI_LINE_COMMENT:
952 if (c == '*' && next == '/')
953 {
954 state = ParseState::MIDDLE_OF_LINE;
955 pos++;
956 }
957 pos++;
958 break;
959 }
960 }
961
962 return true;
963}
964
Brandon Jonesed5b46f2017-07-21 08:39:17 -0700965bool ValidateWebGLNamePrefix(ValidationContext *context, const GLchar *name)
966{
967 ASSERT(context->isWebGL());
968
969 // WebGL 1.0 [Section 6.16] GLSL Constructs
970 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
971 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
972 {
973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), WebglBindAttribLocationReservedPrefix);
974 return false;
975 }
976
977 return true;
978}
979
980bool ValidateWebGLNameLength(ValidationContext *context, size_t length)
981{
982 ASSERT(context->isWebGL());
983
984 if (context->isWebGL1() && length > 256)
985 {
986 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
987 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
988 // locations.
989 ANGLE_VALIDATION_ERR(context, InvalidValue(), WebglNameLengthLimitExceeded);
990
991 return false;
992 }
993 else if (length > 1024)
994 {
995 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
996 // uniform and attribute locations.
997 ANGLE_VALIDATION_ERR(context, InvalidValue(), Webgl2NameLengthLimitExceeded);
998 return false;
999 }
1000
1001 return true;
1002}
1003
Jamie Madillc29968b2016-01-20 11:17:23 -05001004} // anonymous namespace
1005
Geoff Langff5b2d52016-09-07 11:32:23 -04001006bool ValidateES2TexImageParameters(Context *context,
1007 GLenum target,
1008 GLint level,
1009 GLenum internalformat,
1010 bool isCompressed,
1011 bool isSubImage,
1012 GLint xoffset,
1013 GLint yoffset,
1014 GLsizei width,
1015 GLsizei height,
1016 GLint border,
1017 GLenum format,
1018 GLenum type,
1019 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001020 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001021{
Jamie Madill6f38f822014-06-06 17:12:20 -04001022 if (!ValidTexture2DDestinationTarget(context, target))
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001026 }
1027
Austin Kinross08528e12015-10-07 16:24:40 -07001028 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001030 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 }
1033
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 if (!ValidMipLevel(context, target, level))
1035 {
1036 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
1037 return false;
1038 }
1039
1040 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 std::numeric_limits<GLsizei>::max() - yoffset < height)
1042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001043 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04001044 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 }
1046
Geoff Lang6e898aa2017-06-02 11:17:26 -04001047 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1048 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1049 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1050 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1051 // case.
1052 bool nonEqualFormatsAllowed =
1053 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
1054 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
1055
1056 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001058 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001059 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 }
1061
Geoff Langaae65a42014-05-26 12:43:44 -04001062 const gl::Caps &caps = context->getCaps();
1063
Geoff Langa9be0dc2014-12-17 12:34:40 -05001064 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001066 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
1067 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001069 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001072 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001073 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
1074 {
1075 ASSERT(level == 0);
1076 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1077 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
1078 {
1079 context->handleError(InvalidValue());
1080 return false;
1081 }
1082 if (isCompressed)
1083 {
1084 context->handleError(InvalidEnum()
1085 << "Rectangle texture cannot have a compressed format.");
1086 return false;
1087 }
1088 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001089 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001090 {
1091 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001093 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001094 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001095 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096
Geoff Langa9be0dc2014-12-17 12:34:40 -05001097 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1098 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001100 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001101 return false;
1102 }
1103 }
1104 else
1105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001106 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 }
1109
He Yunchaoced53ae2016-11-29 15:00:51 +08001110 gl::Texture *texture =
1111 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 if (!texture)
1113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001115 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 }
1117
Geoff Langa9be0dc2014-12-17 12:34:40 -05001118 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 {
Geoff Langca271392017-04-05 12:30:00 -04001120 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1121 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001123 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001124 return false;
1125 }
1126
Geoff Langa9be0dc2014-12-17 12:34:40 -05001127 if (format != GL_NONE)
1128 {
Geoff Langca271392017-04-05 12:30:00 -04001129 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1130 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001131 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001133 return false;
1134 }
1135 }
1136
1137 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1138 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001140 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001141 return false;
1142 }
1143 }
1144 else
1145 {
Geoff Lang69cce582015-09-17 13:20:36 -04001146 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001149 return false;
1150 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 }
1152
1153 // Verify zero border
1154 if (border != 0)
1155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001156 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 if (isCompressed)
1161 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001162 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001163 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1164 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 switch (actualInternalFormat)
1166 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001167 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1168 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1169 if (!context->getExtensions().textureCompressionDXT1)
1170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001172 return false;
1173 }
1174 break;
1175 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1176 if (!context->getExtensions().textureCompressionDXT1)
1177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001179 return false;
1180 }
1181 break;
1182 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1183 if (!context->getExtensions().textureCompressionDXT5)
1184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001186 return false;
1187 }
1188 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001189 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1190 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1191 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1192 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1193 if (!context->getExtensions().textureCompressionS3TCsRGB)
1194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001196 return false;
1197 }
1198 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 case GL_ETC1_RGB8_OES:
1200 if (!context->getExtensions().compressedETC1RGB8Texture)
1201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 return false;
1204 }
1205 break;
1206 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001207 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1208 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1209 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1210 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 if (!context->getExtensions().lossyETCDecode)
1212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001213 context->handleError(InvalidEnum()
1214 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001215 return false;
1216 }
1217 break;
1218 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001219 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001221 }
Geoff Lang966c9402017-04-18 12:38:27 -04001222
1223 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001224 {
Geoff Lang966c9402017-04-18 12:38:27 -04001225 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1226 height, texture->getWidth(target, level),
1227 texture->getHeight(target, level)))
1228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001229 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001230 return false;
1231 }
1232
1233 if (format != actualInternalFormat)
1234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001236 return false;
1237 }
1238 }
1239 else
1240 {
1241 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001244 return false;
1245 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 }
1247 }
1248 else
1249 {
1250 // validate <type> by itself (used as secondary key below)
1251 switch (type)
1252 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 case GL_UNSIGNED_BYTE:
1254 case GL_UNSIGNED_SHORT_5_6_5:
1255 case GL_UNSIGNED_SHORT_4_4_4_4:
1256 case GL_UNSIGNED_SHORT_5_5_5_1:
1257 case GL_UNSIGNED_SHORT:
1258 case GL_UNSIGNED_INT:
1259 case GL_UNSIGNED_INT_24_8_OES:
1260 case GL_HALF_FLOAT_OES:
1261 case GL_FLOAT:
1262 break;
1263 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001264 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001265 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001266 }
1267
1268 // validate <format> + <type> combinations
1269 // - invalid <format> -> sets INVALID_ENUM
1270 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1271 switch (format)
1272 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001273 case GL_ALPHA:
1274 case GL_LUMINANCE:
1275 case GL_LUMINANCE_ALPHA:
1276 switch (type)
1277 {
1278 case GL_UNSIGNED_BYTE:
1279 case GL_FLOAT:
1280 case GL_HALF_FLOAT_OES:
1281 break;
1282 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001284 return false;
1285 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001287 case GL_RED:
1288 case GL_RG:
1289 if (!context->getExtensions().textureRG)
1290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001291 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001292 return false;
1293 }
1294 switch (type)
1295 {
1296 case GL_UNSIGNED_BYTE:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001297 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001298 case GL_FLOAT:
1299 case GL_HALF_FLOAT_OES:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001300 if (!context->getExtensions().textureFloat)
1301 {
1302 context->handleError(InvalidEnum());
1303 return false;
1304 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001305 break;
1306 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001308 return false;
1309 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001311 case GL_RGB:
1312 switch (type)
1313 {
1314 case GL_UNSIGNED_BYTE:
1315 case GL_UNSIGNED_SHORT_5_6_5:
1316 case GL_FLOAT:
1317 case GL_HALF_FLOAT_OES:
1318 break;
1319 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001320 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001321 return false;
1322 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001324 case GL_RGBA:
1325 switch (type)
1326 {
1327 case GL_UNSIGNED_BYTE:
1328 case GL_UNSIGNED_SHORT_4_4_4_4:
1329 case GL_UNSIGNED_SHORT_5_5_5_1:
1330 case GL_FLOAT:
1331 case GL_HALF_FLOAT_OES:
1332 break;
1333 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 return false;
1336 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001338 case GL_BGRA_EXT:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001339 if (!context->getExtensions().textureFormatBGRA8888)
1340 {
1341 context->handleError(InvalidEnum());
1342 return false;
1343 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001344 switch (type)
1345 {
1346 case GL_UNSIGNED_BYTE:
1347 break;
1348 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001349 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001350 return false;
1351 }
1352 break;
1353 case GL_SRGB_EXT:
1354 case GL_SRGB_ALPHA_EXT:
1355 if (!context->getExtensions().sRGB)
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001358 return false;
1359 }
1360 switch (type)
1361 {
1362 case GL_UNSIGNED_BYTE:
1363 break;
1364 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001365 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001366 return false;
1367 }
1368 break;
1369 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1370 // handled below
1371 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1372 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1373 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1374 break;
1375 case GL_DEPTH_COMPONENT:
1376 switch (type)
1377 {
1378 case GL_UNSIGNED_SHORT:
1379 case GL_UNSIGNED_INT:
1380 break;
1381 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001382 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001383 return false;
1384 }
1385 break;
1386 case GL_DEPTH_STENCIL_OES:
1387 switch (type)
1388 {
1389 case GL_UNSIGNED_INT_24_8_OES:
1390 break;
1391 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001393 return false;
1394 }
1395 break;
1396 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
1400
1401 switch (format)
1402 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001403 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1404 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1405 if (context->getExtensions().textureCompressionDXT1)
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 return false;
1409 }
1410 else
1411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 return false;
1414 }
1415 break;
1416 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1417 if (context->getExtensions().textureCompressionDXT3)
1418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001420 return false;
1421 }
1422 else
1423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001424 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001425 return false;
1426 }
1427 break;
1428 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1429 if (context->getExtensions().textureCompressionDXT5)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001432 return false;
1433 }
1434 else
1435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001437 return false;
1438 }
1439 break;
1440 case GL_ETC1_RGB8_OES:
1441 if (context->getExtensions().compressedETC1RGB8Texture)
1442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 return false;
1445 }
1446 else
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001449 return false;
1450 }
1451 break;
1452 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001453 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1454 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1455 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1456 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001457 if (context->getExtensions().lossyETCDecode)
1458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001459 context->handleError(InvalidOperation()
1460 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 return false;
1462 }
1463 else
1464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001465 context->handleError(InvalidEnum()
1466 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 return false;
1468 }
1469 break;
1470 case GL_DEPTH_COMPONENT:
1471 case GL_DEPTH_STENCIL_OES:
1472 if (!context->getExtensions().depthTextures)
1473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001474 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 return false;
1476 }
1477 if (target != GL_TEXTURE_2D)
1478 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001479 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001480 return false;
1481 }
1482 // OES_depth_texture supports loading depth data and multiple levels,
1483 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001484 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001485 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1487 return false;
1488 }
1489 if (level != 0)
1490 {
1491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 return false;
1493 }
1494 break;
1495 default:
1496 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001497 }
1498
Geoff Lang6e898aa2017-06-02 11:17:26 -04001499 if (!isSubImage)
1500 {
1501 switch (internalformat)
1502 {
1503 case GL_RGBA32F:
1504 if (!context->getExtensions().colorBufferFloatRGBA)
1505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidValue()
1507 << "Sized GL_RGBA32F internal format requires "
1508 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001509 return false;
1510 }
1511 if (type != GL_FLOAT)
1512 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001513 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001514 return false;
1515 }
1516 if (format != GL_RGBA)
1517 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001519 return false;
1520 }
1521 break;
1522
1523 case GL_RGB32F:
1524 if (!context->getExtensions().colorBufferFloatRGB)
1525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001526 context->handleError(InvalidValue()
1527 << "Sized GL_RGB32F internal format requires "
1528 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001529 return false;
1530 }
1531 if (type != GL_FLOAT)
1532 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001534 return false;
1535 }
1536 if (format != GL_RGB)
1537 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001539 return false;
1540 }
1541 break;
1542
1543 default:
1544 break;
1545 }
1546 }
1547
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001548 if (type == GL_FLOAT)
1549 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001550 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001552 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001553 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001554 }
1555 }
1556 else if (type == GL_HALF_FLOAT_OES)
1557 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001558 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001562 }
1563 }
1564 }
1565
Geoff Langdbcced82017-06-06 15:55:54 -04001566 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1567 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001568 imageSize))
1569 {
1570 return false;
1571 }
1572
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001573 return true;
1574}
1575
He Yunchaoced53ae2016-11-29 15:00:51 +08001576bool ValidateES2TexStorageParameters(Context *context,
1577 GLenum target,
1578 GLsizei levels,
1579 GLenum internalformat,
1580 GLsizei width,
1581 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001582{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001583 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1584 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001586 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001587 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001588 }
1589
1590 if (width < 1 || height < 1 || levels < 1)
1591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001592 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001593 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001594 }
1595
1596 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001598 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001599 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001600 }
1601
1602 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
Geoff Langca271392017-04-05 12:30:00 -04001608 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001609 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001611 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001612 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001613 }
1614
Geoff Langaae65a42014-05-26 12:43:44 -04001615 const gl::Caps &caps = context->getCaps();
1616
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001617 switch (target)
1618 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001619 case GL_TEXTURE_2D:
1620 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1621 static_cast<GLuint>(height) > caps.max2DTextureSize)
1622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001623 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001624 return false;
1625 }
1626 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001627 case GL_TEXTURE_RECTANGLE_ANGLE:
1628 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1629 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1630 {
1631 context->handleError(InvalidValue());
1632 return false;
1633 }
1634 if (formatInfo.compressed)
1635 {
1636 context->handleError(InvalidEnum()
1637 << "Rectangle texture cannot have a compressed format.");
1638 return false;
1639 }
1640 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001641 case GL_TEXTURE_CUBE_MAP:
1642 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1643 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001646 return false;
1647 }
1648 break;
1649 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001650 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001651 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001652 }
1653
Geoff Langc0b9ef42014-07-02 10:02:37 -04001654 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001655 {
1656 if (!gl::isPow2(width) || !gl::isPow2(height))
1657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001658 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001659 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001660 }
1661 }
1662
1663 switch (internalformat)
1664 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001665 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1666 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1667 if (!context->getExtensions().textureCompressionDXT1)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001670 return false;
1671 }
1672 break;
1673 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1674 if (!context->getExtensions().textureCompressionDXT3)
1675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001676 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001677 return false;
1678 }
1679 break;
1680 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1681 if (!context->getExtensions().textureCompressionDXT5)
1682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001683 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001684 return false;
1685 }
1686 break;
1687 case GL_ETC1_RGB8_OES:
1688 if (!context->getExtensions().compressedETC1RGB8Texture)
1689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001690 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001691 return false;
1692 }
1693 break;
1694 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001695 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1696 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1697 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1698 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001699 if (!context->getExtensions().lossyETCDecode)
1700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001701 context->handleError(InvalidEnum()
1702 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001703 return false;
1704 }
1705 break;
1706 case GL_RGBA32F_EXT:
1707 case GL_RGB32F_EXT:
1708 case GL_ALPHA32F_EXT:
1709 case GL_LUMINANCE32F_EXT:
1710 case GL_LUMINANCE_ALPHA32F_EXT:
1711 if (!context->getExtensions().textureFloat)
1712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001713 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001714 return false;
1715 }
1716 break;
1717 case GL_RGBA16F_EXT:
1718 case GL_RGB16F_EXT:
1719 case GL_ALPHA16F_EXT:
1720 case GL_LUMINANCE16F_EXT:
1721 case GL_LUMINANCE_ALPHA16F_EXT:
1722 if (!context->getExtensions().textureHalfFloat)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001725 return false;
1726 }
1727 break;
1728 case GL_R8_EXT:
1729 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001730 if (!context->getExtensions().textureRG)
1731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001732 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001733 return false;
1734 }
1735 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001736 case GL_R16F_EXT:
1737 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001738 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001741 return false;
1742 }
1743 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001744 case GL_R32F_EXT:
1745 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001746 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001749 return false;
1750 }
1751 break;
1752 case GL_DEPTH_COMPONENT16:
1753 case GL_DEPTH_COMPONENT32_OES:
1754 case GL_DEPTH24_STENCIL8_OES:
1755 if (!context->getExtensions().depthTextures)
1756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001757 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001758 return false;
1759 }
1760 if (target != GL_TEXTURE_2D)
1761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001762 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001763 return false;
1764 }
1765 // ANGLE_depth_texture only supports 1-level textures
1766 if (levels != 1)
1767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001768 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001769 return false;
1770 }
1771 break;
1772 default:
1773 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001774 }
1775
Geoff Lang691e58c2014-12-19 17:03:25 -05001776 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 if (!texture || texture->id() == 0)
1778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001779 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001780 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001781 }
1782
Geoff Lang69cce582015-09-17 13:20:36 -04001783 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001785 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001786 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001787 }
1788
1789 return true;
1790}
1791
He Yunchaoced53ae2016-11-29 15:00:51 +08001792bool ValidateDiscardFramebufferEXT(Context *context,
1793 GLenum target,
1794 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001795 const GLenum *attachments)
1796{
Jamie Madillc29968b2016-01-20 11:17:23 -05001797 if (!context->getExtensions().discardFramebuffer)
1798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001799 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001800 return false;
1801 }
1802
Austin Kinross08332632015-05-05 13:35:47 -07001803 bool defaultFramebuffer = false;
1804
1805 switch (target)
1806 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001807 case GL_FRAMEBUFFER:
1808 defaultFramebuffer =
1809 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1810 break;
1811 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001812 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001813 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001814 }
1815
He Yunchaoced53ae2016-11-29 15:00:51 +08001816 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1817 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001818}
1819
Austin Kinrossbc781f32015-10-26 09:27:38 -07001820bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1821{
1822 if (!context->getExtensions().vertexArrayObject)
1823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001824 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001825 return false;
1826 }
1827
1828 return ValidateBindVertexArrayBase(context, array);
1829}
1830
Jamie Madilld7576732017-08-26 18:49:50 -04001831bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001832{
1833 if (!context->getExtensions().vertexArrayObject)
1834 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001836 return false;
1837 }
1838
Olli Etuaho41997e72016-03-10 13:38:39 +02001839 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001840}
1841
Jamie Madilld7576732017-08-26 18:49:50 -04001842bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001843{
1844 if (!context->getExtensions().vertexArrayObject)
1845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001846 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001847 return false;
1848 }
1849
Olli Etuaho41997e72016-03-10 13:38:39 +02001850 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001851}
1852
Jamie Madilld7576732017-08-26 18:49:50 -04001853bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001854{
1855 if (!context->getExtensions().vertexArrayObject)
1856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001858 return false;
1859 }
1860
1861 return true;
1862}
Geoff Langc5629752015-12-07 16:29:04 -05001863
1864bool ValidateProgramBinaryOES(Context *context,
1865 GLuint program,
1866 GLenum binaryFormat,
1867 const void *binary,
1868 GLint length)
1869{
1870 if (!context->getExtensions().getProgramBinary)
1871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001873 return false;
1874 }
1875
1876 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1877}
1878
1879bool ValidateGetProgramBinaryOES(Context *context,
1880 GLuint program,
1881 GLsizei bufSize,
1882 GLsizei *length,
1883 GLenum *binaryFormat,
1884 void *binary)
1885{
1886 if (!context->getExtensions().getProgramBinary)
1887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001889 return false;
1890 }
1891
1892 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1893}
Geoff Lange102fee2015-12-10 11:23:30 -05001894
Geoff Lang70d0f492015-12-10 17:45:46 -05001895static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1896{
1897 switch (source)
1898 {
1899 case GL_DEBUG_SOURCE_API:
1900 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1901 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1902 case GL_DEBUG_SOURCE_OTHER:
1903 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1904 return !mustBeThirdPartyOrApplication;
1905
1906 case GL_DEBUG_SOURCE_THIRD_PARTY:
1907 case GL_DEBUG_SOURCE_APPLICATION:
1908 return true;
1909
1910 default:
1911 return false;
1912 }
1913}
1914
1915static bool ValidDebugType(GLenum type)
1916{
1917 switch (type)
1918 {
1919 case GL_DEBUG_TYPE_ERROR:
1920 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1921 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1922 case GL_DEBUG_TYPE_PERFORMANCE:
1923 case GL_DEBUG_TYPE_PORTABILITY:
1924 case GL_DEBUG_TYPE_OTHER:
1925 case GL_DEBUG_TYPE_MARKER:
1926 case GL_DEBUG_TYPE_PUSH_GROUP:
1927 case GL_DEBUG_TYPE_POP_GROUP:
1928 return true;
1929
1930 default:
1931 return false;
1932 }
1933}
1934
1935static bool ValidDebugSeverity(GLenum severity)
1936{
1937 switch (severity)
1938 {
1939 case GL_DEBUG_SEVERITY_HIGH:
1940 case GL_DEBUG_SEVERITY_MEDIUM:
1941 case GL_DEBUG_SEVERITY_LOW:
1942 case GL_DEBUG_SEVERITY_NOTIFICATION:
1943 return true;
1944
1945 default:
1946 return false;
1947 }
1948}
1949
Geoff Lange102fee2015-12-10 11:23:30 -05001950bool ValidateDebugMessageControlKHR(Context *context,
1951 GLenum source,
1952 GLenum type,
1953 GLenum severity,
1954 GLsizei count,
1955 const GLuint *ids,
1956 GLboolean enabled)
1957{
1958 if (!context->getExtensions().debug)
1959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001961 return false;
1962 }
1963
Geoff Lang70d0f492015-12-10 17:45:46 -05001964 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1965 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001967 return false;
1968 }
1969
1970 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1971 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001973 return false;
1974 }
1975
1976 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1977 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001979 return false;
1980 }
1981
1982 if (count > 0)
1983 {
1984 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001986 context->handleError(
1987 InvalidOperation()
1988 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001989 return false;
1990 }
1991
1992 if (severity != GL_DONT_CARE)
1993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001995 InvalidOperation()
1996 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001997 return false;
1998 }
1999 }
2000
Geoff Lange102fee2015-12-10 11:23:30 -05002001 return true;
2002}
2003
2004bool ValidateDebugMessageInsertKHR(Context *context,
2005 GLenum source,
2006 GLenum type,
2007 GLuint id,
2008 GLenum severity,
2009 GLsizei length,
2010 const GLchar *buf)
2011{
2012 if (!context->getExtensions().debug)
2013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002014 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002015 return false;
2016 }
2017
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002018 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05002019 {
2020 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2021 // not generate an error.
2022 return false;
2023 }
2024
2025 if (!ValidDebugSeverity(severity))
2026 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002027 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002028 return false;
2029 }
2030
2031 if (!ValidDebugType(type))
2032 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002033 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05002034 return false;
2035 }
2036
2037 if (!ValidDebugSource(source, true))
2038 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002039 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002040 return false;
2041 }
2042
2043 size_t messageLength = (length < 0) ? strlen(buf) : length;
2044 if (messageLength > context->getExtensions().maxDebugMessageLength)
2045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002046 context->handleError(InvalidValue()
2047 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002048 return false;
2049 }
2050
Geoff Lange102fee2015-12-10 11:23:30 -05002051 return true;
2052}
2053
2054bool ValidateDebugMessageCallbackKHR(Context *context,
2055 GLDEBUGPROCKHR callback,
2056 const void *userParam)
2057{
2058 if (!context->getExtensions().debug)
2059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002060 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002061 return false;
2062 }
2063
Geoff Lange102fee2015-12-10 11:23:30 -05002064 return true;
2065}
2066
2067bool ValidateGetDebugMessageLogKHR(Context *context,
2068 GLuint count,
2069 GLsizei bufSize,
2070 GLenum *sources,
2071 GLenum *types,
2072 GLuint *ids,
2073 GLenum *severities,
2074 GLsizei *lengths,
2075 GLchar *messageLog)
2076{
2077 if (!context->getExtensions().debug)
2078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002080 return false;
2081 }
2082
Geoff Lang70d0f492015-12-10 17:45:46 -05002083 if (bufSize < 0 && messageLog != nullptr)
2084 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002085 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002086 return false;
2087 }
2088
Geoff Lange102fee2015-12-10 11:23:30 -05002089 return true;
2090}
2091
2092bool ValidatePushDebugGroupKHR(Context *context,
2093 GLenum source,
2094 GLuint id,
2095 GLsizei length,
2096 const GLchar *message)
2097{
2098 if (!context->getExtensions().debug)
2099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002101 return false;
2102 }
2103
Geoff Lang70d0f492015-12-10 17:45:46 -05002104 if (!ValidDebugSource(source, true))
2105 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002107 return false;
2108 }
2109
2110 size_t messageLength = (length < 0) ? strlen(message) : length;
2111 if (messageLength > context->getExtensions().maxDebugMessageLength)
2112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002113 context->handleError(InvalidValue()
2114 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002115 return false;
2116 }
2117
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002118 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002119 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002121 context
2122 ->handleError(StackOverflow()
2123 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002124 return false;
2125 }
2126
Geoff Lange102fee2015-12-10 11:23:30 -05002127 return true;
2128}
2129
2130bool ValidatePopDebugGroupKHR(Context *context)
2131{
2132 if (!context->getExtensions().debug)
2133 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002135 return false;
2136 }
2137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002138 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002139 if (currentStackSize <= 1)
2140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002142 return false;
2143 }
2144
2145 return true;
2146}
2147
2148static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2149{
2150 switch (identifier)
2151 {
2152 case GL_BUFFER:
2153 if (context->getBuffer(name) == nullptr)
2154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002156 return false;
2157 }
2158 return true;
2159
2160 case GL_SHADER:
2161 if (context->getShader(name) == nullptr)
2162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002163 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002164 return false;
2165 }
2166 return true;
2167
2168 case GL_PROGRAM:
2169 if (context->getProgram(name) == nullptr)
2170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002171 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002172 return false;
2173 }
2174 return true;
2175
2176 case GL_VERTEX_ARRAY:
2177 if (context->getVertexArray(name) == nullptr)
2178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002180 return false;
2181 }
2182 return true;
2183
2184 case GL_QUERY:
2185 if (context->getQuery(name) == nullptr)
2186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002187 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002188 return false;
2189 }
2190 return true;
2191
2192 case GL_TRANSFORM_FEEDBACK:
2193 if (context->getTransformFeedback(name) == nullptr)
2194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002196 return false;
2197 }
2198 return true;
2199
2200 case GL_SAMPLER:
2201 if (context->getSampler(name) == nullptr)
2202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002203 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002204 return false;
2205 }
2206 return true;
2207
2208 case GL_TEXTURE:
2209 if (context->getTexture(name) == nullptr)
2210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002211 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002212 return false;
2213 }
2214 return true;
2215
2216 case GL_RENDERBUFFER:
2217 if (context->getRenderbuffer(name) == nullptr)
2218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002219 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002220 return false;
2221 }
2222 return true;
2223
2224 case GL_FRAMEBUFFER:
2225 if (context->getFramebuffer(name) == nullptr)
2226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002227 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002228 return false;
2229 }
2230 return true;
2231
2232 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002233 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002234 return false;
2235 }
Geoff Lange102fee2015-12-10 11:23:30 -05002236}
2237
Martin Radev9d901792016-07-15 15:58:58 +03002238static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2239{
2240 size_t labelLength = 0;
2241
2242 if (length < 0)
2243 {
2244 if (label != nullptr)
2245 {
2246 labelLength = strlen(label);
2247 }
2248 }
2249 else
2250 {
2251 labelLength = static_cast<size_t>(length);
2252 }
2253
2254 if (labelLength > context->getExtensions().maxLabelLength)
2255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002256 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002257 return false;
2258 }
2259
2260 return true;
2261}
2262
Geoff Lange102fee2015-12-10 11:23:30 -05002263bool ValidateObjectLabelKHR(Context *context,
2264 GLenum identifier,
2265 GLuint name,
2266 GLsizei length,
2267 const GLchar *label)
2268{
2269 if (!context->getExtensions().debug)
2270 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002271 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002272 return false;
2273 }
2274
Geoff Lang70d0f492015-12-10 17:45:46 -05002275 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2276 {
2277 return false;
2278 }
2279
Martin Radev9d901792016-07-15 15:58:58 +03002280 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002281 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002282 return false;
2283 }
2284
Geoff Lange102fee2015-12-10 11:23:30 -05002285 return true;
2286}
2287
2288bool ValidateGetObjectLabelKHR(Context *context,
2289 GLenum identifier,
2290 GLuint name,
2291 GLsizei bufSize,
2292 GLsizei *length,
2293 GLchar *label)
2294{
2295 if (!context->getExtensions().debug)
2296 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002298 return false;
2299 }
2300
Geoff Lang70d0f492015-12-10 17:45:46 -05002301 if (bufSize < 0)
2302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002303 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002304 return false;
2305 }
2306
2307 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2308 {
2309 return false;
2310 }
2311
Martin Radev9d901792016-07-15 15:58:58 +03002312 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002313}
2314
2315static bool ValidateObjectPtrName(Context *context, const void *ptr)
2316{
Jamie Madill70b5bb02017-08-28 13:32:37 -04002317 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
Geoff Lang70d0f492015-12-10 17:45:46 -05002318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002319 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002320 return false;
2321 }
2322
Geoff Lange102fee2015-12-10 11:23:30 -05002323 return true;
2324}
2325
2326bool ValidateObjectPtrLabelKHR(Context *context,
2327 const void *ptr,
2328 GLsizei length,
2329 const GLchar *label)
2330{
2331 if (!context->getExtensions().debug)
2332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002334 return false;
2335 }
2336
Geoff Lang70d0f492015-12-10 17:45:46 -05002337 if (!ValidateObjectPtrName(context, ptr))
2338 {
2339 return false;
2340 }
2341
Martin Radev9d901792016-07-15 15:58:58 +03002342 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002343 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002344 return false;
2345 }
2346
Geoff Lange102fee2015-12-10 11:23:30 -05002347 return true;
2348}
2349
2350bool ValidateGetObjectPtrLabelKHR(Context *context,
2351 const void *ptr,
2352 GLsizei bufSize,
2353 GLsizei *length,
2354 GLchar *label)
2355{
2356 if (!context->getExtensions().debug)
2357 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002358 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002359 return false;
2360 }
2361
Geoff Lang70d0f492015-12-10 17:45:46 -05002362 if (bufSize < 0)
2363 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002364 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002365 return false;
2366 }
2367
2368 if (!ValidateObjectPtrName(context, ptr))
2369 {
2370 return false;
2371 }
2372
Martin Radev9d901792016-07-15 15:58:58 +03002373 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002374}
2375
2376bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2377{
2378 if (!context->getExtensions().debug)
2379 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002381 return false;
2382 }
2383
Geoff Lang70d0f492015-12-10 17:45:46 -05002384 // TODO: represent this in Context::getQueryParameterInfo.
2385 switch (pname)
2386 {
2387 case GL_DEBUG_CALLBACK_FUNCTION:
2388 case GL_DEBUG_CALLBACK_USER_PARAM:
2389 break;
2390
2391 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002393 return false;
2394 }
2395
Geoff Lange102fee2015-12-10 11:23:30 -05002396 return true;
2397}
Jamie Madillc29968b2016-01-20 11:17:23 -05002398
2399bool ValidateBlitFramebufferANGLE(Context *context,
2400 GLint srcX0,
2401 GLint srcY0,
2402 GLint srcX1,
2403 GLint srcY1,
2404 GLint dstX0,
2405 GLint dstY0,
2406 GLint dstX1,
2407 GLint dstY1,
2408 GLbitfield mask,
2409 GLenum filter)
2410{
2411 if (!context->getExtensions().framebufferBlit)
2412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002413 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002414 return false;
2415 }
2416
2417 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2418 {
2419 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002420 context->handleError(InvalidOperation() << "Scaling and flipping in "
2421 "BlitFramebufferANGLE not supported by this "
2422 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002423 return false;
2424 }
2425
2426 if (filter == GL_LINEAR)
2427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002428 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002429 return false;
2430 }
2431
Jamie Madill51f40ec2016-06-15 14:06:00 -04002432 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2433 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002434
2435 if (mask & GL_COLOR_BUFFER_BIT)
2436 {
2437 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2438 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2439
2440 if (readColorAttachment && drawColorAttachment)
2441 {
2442 if (!(readColorAttachment->type() == GL_TEXTURE &&
2443 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2444 readColorAttachment->type() != GL_RENDERBUFFER &&
2445 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002447 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002448 return false;
2449 }
2450
Geoff Langa15472a2015-08-11 11:48:03 -04002451 for (size_t drawbufferIdx = 0;
2452 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002453 {
Geoff Langa15472a2015-08-11 11:48:03 -04002454 const FramebufferAttachment *attachment =
2455 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2456 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002457 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002458 if (!(attachment->type() == GL_TEXTURE &&
2459 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2460 attachment->type() != GL_RENDERBUFFER &&
2461 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002463 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002464 return false;
2465 }
2466
2467 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002468 if (!Format::EquivalentForBlit(attachment->getFormat(),
2469 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002471 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002472 return false;
2473 }
2474 }
2475 }
2476
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002477 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002478 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2479 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002482 return false;
2483 }
2484 }
2485 }
2486
2487 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2488 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2489 for (size_t i = 0; i < 2; i++)
2490 {
2491 if (mask & masks[i])
2492 {
2493 const FramebufferAttachment *readBuffer =
2494 readFramebuffer->getAttachment(attachments[i]);
2495 const FramebufferAttachment *drawBuffer =
2496 drawFramebuffer->getAttachment(attachments[i]);
2497
2498 if (readBuffer && drawBuffer)
2499 {
2500 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2501 dstX0, dstY0, dstX1, dstY1))
2502 {
2503 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2505 "stencil blits are supported by "
2506 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002507 return false;
2508 }
2509
2510 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002512 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002513 return false;
2514 }
2515 }
2516 }
2517 }
2518
2519 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2520 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002521}
Jamie Madillc29968b2016-01-20 11:17:23 -05002522
2523bool ValidateClear(ValidationContext *context, GLbitfield mask)
2524{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002525 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002526 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002528 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002529 return false;
2530 }
2531
2532 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2533 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002534 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002535 return false;
2536 }
2537
Geoff Lang76e65652017-03-27 14:58:02 -04002538 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2539 {
2540 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2541 GL_SIGNED_NORMALIZED};
2542
Corentin Wallez59c41592017-07-11 13:19:54 -04002543 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002544 drawBufferIdx++)
2545 {
2546 if (!ValidateWebGLFramebufferAttachmentClearType(
2547 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2548 {
2549 return false;
2550 }
2551 }
2552 }
2553
Jamie Madillc29968b2016-01-20 11:17:23 -05002554 return true;
2555}
2556
2557bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2558{
2559 if (!context->getExtensions().drawBuffers)
2560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002561 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002562 return false;
2563 }
2564
2565 return ValidateDrawBuffersBase(context, n, bufs);
2566}
2567
Jamie Madill73a84962016-02-12 09:27:23 -05002568bool ValidateTexImage2D(Context *context,
2569 GLenum target,
2570 GLint level,
2571 GLint internalformat,
2572 GLsizei width,
2573 GLsizei height,
2574 GLint border,
2575 GLenum format,
2576 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002577 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002578{
Martin Radev1be913c2016-07-11 17:59:16 +03002579 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002580 {
2581 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002582 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002583 }
2584
Martin Radev1be913c2016-07-11 17:59:16 +03002585 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002586 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002587 0, 0, width, height, 1, border, format, type, -1,
2588 pixels);
2589}
2590
2591bool ValidateTexImage2DRobust(Context *context,
2592 GLenum target,
2593 GLint level,
2594 GLint internalformat,
2595 GLsizei width,
2596 GLsizei height,
2597 GLint border,
2598 GLenum format,
2599 GLenum type,
2600 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002601 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002602{
2603 if (!ValidateRobustEntryPoint(context, bufSize))
2604 {
2605 return false;
2606 }
2607
2608 if (context->getClientMajorVersion() < 3)
2609 {
2610 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2611 0, 0, width, height, border, format, type, bufSize,
2612 pixels);
2613 }
2614
2615 ASSERT(context->getClientMajorVersion() >= 3);
2616 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2617 0, 0, width, height, 1, border, format, type, bufSize,
2618 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002619}
2620
2621bool ValidateTexSubImage2D(Context *context,
2622 GLenum target,
2623 GLint level,
2624 GLint xoffset,
2625 GLint yoffset,
2626 GLsizei width,
2627 GLsizei height,
2628 GLenum format,
2629 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002630 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002631{
2632
Martin Radev1be913c2016-07-11 17:59:16 +03002633 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002634 {
2635 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002636 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002637 }
2638
Martin Radev1be913c2016-07-11 17:59:16 +03002639 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002640 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002641 yoffset, 0, width, height, 1, 0, format, type, -1,
2642 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002643}
2644
Geoff Langc52f6f12016-10-14 10:18:00 -04002645bool ValidateTexSubImage2DRobustANGLE(Context *context,
2646 GLenum target,
2647 GLint level,
2648 GLint xoffset,
2649 GLint yoffset,
2650 GLsizei width,
2651 GLsizei height,
2652 GLenum format,
2653 GLenum type,
2654 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002655 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002656{
2657 if (!ValidateRobustEntryPoint(context, bufSize))
2658 {
2659 return false;
2660 }
2661
2662 if (context->getClientMajorVersion() < 3)
2663 {
2664 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2665 yoffset, width, height, 0, format, type, bufSize,
2666 pixels);
2667 }
2668
2669 ASSERT(context->getClientMajorVersion() >= 3);
2670 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2671 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2672 pixels);
2673}
2674
Jamie Madill73a84962016-02-12 09:27:23 -05002675bool ValidateCompressedTexImage2D(Context *context,
2676 GLenum target,
2677 GLint level,
2678 GLenum internalformat,
2679 GLsizei width,
2680 GLsizei height,
2681 GLint border,
2682 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002683 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002684{
Martin Radev1be913c2016-07-11 17:59:16 +03002685 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002686 {
2687 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002688 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002689 {
2690 return false;
2691 }
2692 }
2693 else
2694 {
Martin Radev1be913c2016-07-11 17:59:16 +03002695 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002696 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002697 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002698 data))
2699 {
2700 return false;
2701 }
2702 }
2703
Geoff Langca271392017-04-05 12:30:00 -04002704 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002705 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002706 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002707 if (blockSizeOrErr.isError())
2708 {
2709 context->handleError(blockSizeOrErr.getError());
2710 return false;
2711 }
2712
2713 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002714 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002715 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002716 return false;
2717 }
2718
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002719 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2720 {
2721 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2722 return false;
2723 }
2724
Jamie Madill73a84962016-02-12 09:27:23 -05002725 return true;
2726}
2727
Corentin Wallezb2931602017-04-11 15:58:57 -04002728bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2729 GLenum target,
2730 GLint level,
2731 GLenum internalformat,
2732 GLsizei width,
2733 GLsizei height,
2734 GLint border,
2735 GLsizei imageSize,
2736 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002737 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002738{
2739 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2740 {
2741 return false;
2742 }
2743
2744 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2745 border, imageSize, data);
2746}
2747bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2748 GLenum target,
2749 GLint level,
2750 GLint xoffset,
2751 GLint yoffset,
2752 GLsizei width,
2753 GLsizei height,
2754 GLenum format,
2755 GLsizei imageSize,
2756 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002757 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002758{
2759 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2760 {
2761 return false;
2762 }
2763
2764 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2765 format, imageSize, data);
2766}
2767
Jamie Madill73a84962016-02-12 09:27:23 -05002768bool ValidateCompressedTexSubImage2D(Context *context,
2769 GLenum target,
2770 GLint level,
2771 GLint xoffset,
2772 GLint yoffset,
2773 GLsizei width,
2774 GLsizei height,
2775 GLenum format,
2776 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002777 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002778{
Martin Radev1be913c2016-07-11 17:59:16 +03002779 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002780 {
2781 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002782 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002783 {
2784 return false;
2785 }
2786 }
2787 else
2788 {
Martin Radev1be913c2016-07-11 17:59:16 +03002789 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002790 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002791 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002792 data))
2793 {
2794 return false;
2795 }
2796 }
2797
Geoff Langca271392017-04-05 12:30:00 -04002798 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002799 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002800 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002801 if (blockSizeOrErr.isError())
2802 {
2803 context->handleError(blockSizeOrErr.getError());
2804 return false;
2805 }
2806
2807 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002809 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002810 return false;
2811 }
2812
2813 return true;
2814}
2815
Olli Etuaho4f667482016-03-30 15:56:35 +03002816bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2817{
Geoff Lang496c02d2016-10-20 11:38:11 -07002818 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002819}
2820
2821bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2822{
2823 if (!context->getExtensions().mapBuffer)
2824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002825 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002826 return false;
2827 }
2828
2829 if (!ValidBufferTarget(context, target))
2830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002832 return false;
2833 }
2834
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002835 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002836
2837 if (buffer == nullptr)
2838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002839 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002840 return false;
2841 }
2842
2843 if (access != GL_WRITE_ONLY_OES)
2844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002845 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002846 return false;
2847 }
2848
2849 if (buffer->isMapped())
2850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002851 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002852 return false;
2853 }
2854
Geoff Lang79f71042017-08-14 16:43:43 -04002855 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002856}
2857
2858bool ValidateUnmapBufferOES(Context *context, GLenum target)
2859{
2860 if (!context->getExtensions().mapBuffer)
2861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002862 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002863 return false;
2864 }
2865
2866 return ValidateUnmapBufferBase(context, target);
2867}
2868
2869bool ValidateMapBufferRangeEXT(Context *context,
2870 GLenum target,
2871 GLintptr offset,
2872 GLsizeiptr length,
2873 GLbitfield access)
2874{
2875 if (!context->getExtensions().mapBufferRange)
2876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002877 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002878 return false;
2879 }
2880
2881 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2882}
2883
Geoff Lang79f71042017-08-14 16:43:43 -04002884bool ValidateMapBufferBase(Context *context, GLenum target)
2885{
2886 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2887 ASSERT(buffer != nullptr);
2888
2889 // Check if this buffer is currently being used as a transform feedback output buffer
2890 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2891 if (transformFeedback != nullptr && transformFeedback->isActive())
2892 {
2893 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2894 {
2895 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2896 if (transformFeedbackBuffer.get() == buffer)
2897 {
2898 context->handleError(InvalidOperation()
2899 << "Buffer is currently bound for transform feedback.");
2900 return false;
2901 }
2902 }
2903 }
2904
2905 return true;
2906}
2907
Olli Etuaho4f667482016-03-30 15:56:35 +03002908bool ValidateFlushMappedBufferRangeEXT(Context *context,
2909 GLenum target,
2910 GLintptr offset,
2911 GLsizeiptr length)
2912{
2913 if (!context->getExtensions().mapBufferRange)
2914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002915 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002916 return false;
2917 }
2918
2919 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2920}
2921
Ian Ewell54f87462016-03-10 13:47:21 -05002922bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2923{
2924 Texture *textureObject = context->getTexture(texture);
2925 if (textureObject && textureObject->getTarget() != target && texture != 0)
2926 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002927 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002928 return false;
2929 }
2930
Geoff Langf41a7152016-09-19 15:11:17 -04002931 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2932 !context->isTextureGenerated(texture))
2933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002934 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002935 return false;
2936 }
2937
Ian Ewell54f87462016-03-10 13:47:21 -05002938 switch (target)
2939 {
2940 case GL_TEXTURE_2D:
2941 case GL_TEXTURE_CUBE_MAP:
2942 break;
2943
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002944 case GL_TEXTURE_RECTANGLE_ANGLE:
2945 if (!context->getExtensions().textureRectangle)
2946 {
2947 context->handleError(InvalidEnum()
2948 << "Context does not support GL_ANGLE_texture_rectangle");
2949 return false;
2950 }
2951 break;
2952
Ian Ewell54f87462016-03-10 13:47:21 -05002953 case GL_TEXTURE_3D:
2954 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002955 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002956 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002958 return false;
2959 }
2960 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002961
2962 case GL_TEXTURE_2D_MULTISAMPLE:
2963 if (context->getClientVersion() < Version(3, 1))
2964 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002966 return false;
2967 }
Geoff Lang3b573612016-10-31 14:08:10 -04002968 break;
2969
Ian Ewell54f87462016-03-10 13:47:21 -05002970 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002971 if (!context->getExtensions().eglImageExternal &&
2972 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002974 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002975 return false;
2976 }
2977 break;
2978 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002980 return false;
2981 }
2982
2983 return true;
2984}
2985
Geoff Langd8605522016-04-13 10:19:12 -04002986bool ValidateBindUniformLocationCHROMIUM(Context *context,
2987 GLuint program,
2988 GLint location,
2989 const GLchar *name)
2990{
2991 if (!context->getExtensions().bindUniformLocation)
2992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002993 context->handleError(InvalidOperation()
2994 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002995 return false;
2996 }
2997
2998 Program *programObject = GetValidProgram(context, program);
2999 if (!programObject)
3000 {
3001 return false;
3002 }
3003
3004 if (location < 0)
3005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04003007 return false;
3008 }
3009
3010 const Caps &caps = context->getCaps();
3011 if (static_cast<size_t>(location) >=
3012 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003014 context->handleError(InvalidValue() << "Location must be less than "
3015 "(MAX_VERTEX_UNIFORM_VECTORS + "
3016 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04003017 return false;
3018 }
3019
Geoff Langfc32e8b2017-05-31 14:16:59 -04003020 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3021 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04003022 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04003023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003024 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04003025 return false;
3026 }
3027
Geoff Langd8605522016-04-13 10:19:12 -04003028 if (strncmp(name, "gl_", 3) == 0)
3029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003030 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04003031 return false;
3032 }
3033
3034 return true;
3035}
3036
Jamie Madille2e406c2016-06-02 13:04:10 -04003037bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03003038{
3039 if (!context->getExtensions().framebufferMixedSamples)
3040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003041 context->handleError(InvalidOperation()
3042 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03003043 return false;
3044 }
3045 switch (components)
3046 {
3047 case GL_RGB:
3048 case GL_RGBA:
3049 case GL_ALPHA:
3050 case GL_NONE:
3051 break;
3052 default:
3053 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003054 InvalidEnum()
3055 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03003056 return false;
3057 }
3058
3059 return true;
3060}
3061
Sami Väisänene45e53b2016-05-25 10:36:04 +03003062// CHROMIUM_path_rendering
3063
3064bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3065{
3066 if (!context->getExtensions().pathRendering)
3067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003068 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003069 return false;
3070 }
3071 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3072 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003074 return false;
3075 }
3076 if (matrix == nullptr)
3077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003078 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003079 return false;
3080 }
3081 return true;
3082}
3083
3084bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3085{
3086 if (!context->getExtensions().pathRendering)
3087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003088 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003089 return false;
3090 }
3091 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3092 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003094 return false;
3095 }
3096 return true;
3097}
3098
3099bool ValidateGenPaths(Context *context, GLsizei range)
3100{
3101 if (!context->getExtensions().pathRendering)
3102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003103 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003104 return false;
3105 }
3106
3107 // range = 0 is undefined in NV_path_rendering.
3108 // we add stricter semantic check here and require a non zero positive range.
3109 if (range <= 0)
3110 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003111 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003112 return false;
3113 }
3114
3115 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3116 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003118 return false;
3119 }
3120
3121 return true;
3122}
3123
3124bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3125{
3126 if (!context->getExtensions().pathRendering)
3127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003128 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003129 return false;
3130 }
3131
3132 // range = 0 is undefined in NV_path_rendering.
3133 // we add stricter semantic check here and require a non zero positive range.
3134 if (range <= 0)
3135 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003136 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003137 return false;
3138 }
3139
3140 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3141 checkedRange += range;
3142
3143 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003146 return false;
3147 }
3148 return true;
3149}
3150
3151bool ValidatePathCommands(Context *context,
3152 GLuint path,
3153 GLsizei numCommands,
3154 const GLubyte *commands,
3155 GLsizei numCoords,
3156 GLenum coordType,
3157 const void *coords)
3158{
3159 if (!context->getExtensions().pathRendering)
3160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003161 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003162 return false;
3163 }
3164 if (!context->hasPath(path))
3165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003167 return false;
3168 }
3169
3170 if (numCommands < 0)
3171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003172 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003173 return false;
3174 }
3175 else if (numCommands > 0)
3176 {
3177 if (!commands)
3178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003179 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003180 return false;
3181 }
3182 }
3183
3184 if (numCoords < 0)
3185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003186 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003187 return false;
3188 }
3189 else if (numCoords > 0)
3190 {
3191 if (!coords)
3192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003193 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003194 return false;
3195 }
3196 }
3197
3198 std::uint32_t coordTypeSize = 0;
3199 switch (coordType)
3200 {
3201 case GL_BYTE:
3202 coordTypeSize = sizeof(GLbyte);
3203 break;
3204
3205 case GL_UNSIGNED_BYTE:
3206 coordTypeSize = sizeof(GLubyte);
3207 break;
3208
3209 case GL_SHORT:
3210 coordTypeSize = sizeof(GLshort);
3211 break;
3212
3213 case GL_UNSIGNED_SHORT:
3214 coordTypeSize = sizeof(GLushort);
3215 break;
3216
3217 case GL_FLOAT:
3218 coordTypeSize = sizeof(GLfloat);
3219 break;
3220
3221 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003222 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003223 return false;
3224 }
3225
3226 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3227 checkedSize += (coordTypeSize * numCoords);
3228 if (!checkedSize.IsValid())
3229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003231 return false;
3232 }
3233
3234 // early return skips command data validation when it doesn't exist.
3235 if (!commands)
3236 return true;
3237
3238 GLsizei expectedNumCoords = 0;
3239 for (GLsizei i = 0; i < numCommands; ++i)
3240 {
3241 switch (commands[i])
3242 {
3243 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3244 break;
3245 case GL_MOVE_TO_CHROMIUM:
3246 case GL_LINE_TO_CHROMIUM:
3247 expectedNumCoords += 2;
3248 break;
3249 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3250 expectedNumCoords += 4;
3251 break;
3252 case GL_CUBIC_CURVE_TO_CHROMIUM:
3253 expectedNumCoords += 6;
3254 break;
3255 case GL_CONIC_CURVE_TO_CHROMIUM:
3256 expectedNumCoords += 5;
3257 break;
3258 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003259 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003260 return false;
3261 }
3262 }
3263 if (expectedNumCoords != numCoords)
3264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003265 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003266 return false;
3267 }
3268
3269 return true;
3270}
3271
3272bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3273{
3274 if (!context->getExtensions().pathRendering)
3275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003277 return false;
3278 }
3279 if (!context->hasPath(path))
3280 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003282 return false;
3283 }
3284
3285 switch (pname)
3286 {
3287 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3288 if (value < 0.0f)
3289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003291 return false;
3292 }
3293 break;
3294 case GL_PATH_END_CAPS_CHROMIUM:
3295 switch (static_cast<GLenum>(value))
3296 {
3297 case GL_FLAT_CHROMIUM:
3298 case GL_SQUARE_CHROMIUM:
3299 case GL_ROUND_CHROMIUM:
3300 break;
3301 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003302 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003303 return false;
3304 }
3305 break;
3306 case GL_PATH_JOIN_STYLE_CHROMIUM:
3307 switch (static_cast<GLenum>(value))
3308 {
3309 case GL_MITER_REVERT_CHROMIUM:
3310 case GL_BEVEL_CHROMIUM:
3311 case GL_ROUND_CHROMIUM:
3312 break;
3313 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003314 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003315 return false;
3316 }
3317 case GL_PATH_MITER_LIMIT_CHROMIUM:
3318 if (value < 0.0f)
3319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003320 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003321 return false;
3322 }
3323 break;
3324
3325 case GL_PATH_STROKE_BOUND_CHROMIUM:
3326 // no errors, only clamping.
3327 break;
3328
3329 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003330 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003331 return false;
3332 }
3333 return true;
3334}
3335
3336bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3337{
3338 if (!context->getExtensions().pathRendering)
3339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003340 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003341 return false;
3342 }
3343
3344 if (!context->hasPath(path))
3345 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003346 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003347 return false;
3348 }
3349 if (!value)
3350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003352 return false;
3353 }
3354
3355 switch (pname)
3356 {
3357 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3358 case GL_PATH_END_CAPS_CHROMIUM:
3359 case GL_PATH_JOIN_STYLE_CHROMIUM:
3360 case GL_PATH_MITER_LIMIT_CHROMIUM:
3361 case GL_PATH_STROKE_BOUND_CHROMIUM:
3362 break;
3363
3364 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003365 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003366 return false;
3367 }
3368
3369 return true;
3370}
3371
3372bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3373{
3374 if (!context->getExtensions().pathRendering)
3375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003376 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003377 return false;
3378 }
3379
3380 switch (func)
3381 {
3382 case GL_NEVER:
3383 case GL_ALWAYS:
3384 case GL_LESS:
3385 case GL_LEQUAL:
3386 case GL_EQUAL:
3387 case GL_GEQUAL:
3388 case GL_GREATER:
3389 case GL_NOTEQUAL:
3390 break;
3391 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003393 return false;
3394 }
3395
3396 return true;
3397}
3398
3399// Note that the spec specifies that for the path drawing commands
3400// if the path object is not an existing path object the command
3401// does nothing and no error is generated.
3402// However if the path object exists but has not been specified any
3403// commands then an error is generated.
3404
3405bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3406{
3407 if (!context->getExtensions().pathRendering)
3408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003409 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003410 return false;
3411 }
3412 if (context->hasPath(path) && !context->hasPathData(path))
3413 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003415 return false;
3416 }
3417
3418 switch (fillMode)
3419 {
3420 case GL_COUNT_UP_CHROMIUM:
3421 case GL_COUNT_DOWN_CHROMIUM:
3422 break;
3423 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003425 return false;
3426 }
3427
3428 if (!isPow2(mask + 1))
3429 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003430 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003431 return false;
3432 }
3433
3434 return true;
3435}
3436
3437bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3438{
3439 if (!context->getExtensions().pathRendering)
3440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003441 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003442 return false;
3443 }
3444 if (context->hasPath(path) && !context->hasPathData(path))
3445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003446 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003447 return false;
3448 }
3449
3450 return true;
3451}
3452
3453bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3454{
3455 if (!context->getExtensions().pathRendering)
3456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003457 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003458 return false;
3459 }
3460 if (context->hasPath(path) && !context->hasPathData(path))
3461 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003463 return false;
3464 }
3465
3466 switch (coverMode)
3467 {
3468 case GL_CONVEX_HULL_CHROMIUM:
3469 case GL_BOUNDING_BOX_CHROMIUM:
3470 break;
3471 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003473 return false;
3474 }
3475 return true;
3476}
3477
3478bool ValidateStencilThenCoverFillPath(Context *context,
3479 GLuint path,
3480 GLenum fillMode,
3481 GLuint mask,
3482 GLenum coverMode)
3483{
3484 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3485 ValidateCoverPath(context, path, coverMode);
3486}
3487
3488bool ValidateStencilThenCoverStrokePath(Context *context,
3489 GLuint path,
3490 GLint reference,
3491 GLuint mask,
3492 GLenum coverMode)
3493{
3494 return ValidateStencilStrokePath(context, path, reference, mask) &&
3495 ValidateCoverPath(context, path, coverMode);
3496}
3497
3498bool ValidateIsPath(Context *context)
3499{
3500 if (!context->getExtensions().pathRendering)
3501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003502 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003503 return false;
3504 }
3505 return true;
3506}
3507
Sami Väisänend59ca052016-06-21 16:10:00 +03003508bool ValidateCoverFillPathInstanced(Context *context,
3509 GLsizei numPaths,
3510 GLenum pathNameType,
3511 const void *paths,
3512 GLuint pathBase,
3513 GLenum coverMode,
3514 GLenum transformType,
3515 const GLfloat *transformValues)
3516{
3517 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3518 transformType, transformValues))
3519 return false;
3520
3521 switch (coverMode)
3522 {
3523 case GL_CONVEX_HULL_CHROMIUM:
3524 case GL_BOUNDING_BOX_CHROMIUM:
3525 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3526 break;
3527 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003529 return false;
3530 }
3531
3532 return true;
3533}
3534
3535bool ValidateCoverStrokePathInstanced(Context *context,
3536 GLsizei numPaths,
3537 GLenum pathNameType,
3538 const void *paths,
3539 GLuint pathBase,
3540 GLenum coverMode,
3541 GLenum transformType,
3542 const GLfloat *transformValues)
3543{
3544 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3545 transformType, transformValues))
3546 return false;
3547
3548 switch (coverMode)
3549 {
3550 case GL_CONVEX_HULL_CHROMIUM:
3551 case GL_BOUNDING_BOX_CHROMIUM:
3552 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3553 break;
3554 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003555 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003556 return false;
3557 }
3558
3559 return true;
3560}
3561
3562bool ValidateStencilFillPathInstanced(Context *context,
3563 GLsizei numPaths,
3564 GLenum pathNameType,
3565 const void *paths,
3566 GLuint pathBase,
3567 GLenum fillMode,
3568 GLuint mask,
3569 GLenum transformType,
3570 const GLfloat *transformValues)
3571{
3572
3573 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3574 transformType, transformValues))
3575 return false;
3576
3577 switch (fillMode)
3578 {
3579 case GL_COUNT_UP_CHROMIUM:
3580 case GL_COUNT_DOWN_CHROMIUM:
3581 break;
3582 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003583 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003584 return false;
3585 }
3586 if (!isPow2(mask + 1))
3587 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003588 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003589 return false;
3590 }
3591 return true;
3592}
3593
3594bool ValidateStencilStrokePathInstanced(Context *context,
3595 GLsizei numPaths,
3596 GLenum pathNameType,
3597 const void *paths,
3598 GLuint pathBase,
3599 GLint reference,
3600 GLuint mask,
3601 GLenum transformType,
3602 const GLfloat *transformValues)
3603{
3604 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3605 transformType, transformValues))
3606 return false;
3607
3608 // no more validation here.
3609
3610 return true;
3611}
3612
3613bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3614 GLsizei numPaths,
3615 GLenum pathNameType,
3616 const void *paths,
3617 GLuint pathBase,
3618 GLenum fillMode,
3619 GLuint mask,
3620 GLenum coverMode,
3621 GLenum transformType,
3622 const GLfloat *transformValues)
3623{
3624 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3625 transformType, transformValues))
3626 return false;
3627
3628 switch (coverMode)
3629 {
3630 case GL_CONVEX_HULL_CHROMIUM:
3631 case GL_BOUNDING_BOX_CHROMIUM:
3632 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3633 break;
3634 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003635 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003636 return false;
3637 }
3638
3639 switch (fillMode)
3640 {
3641 case GL_COUNT_UP_CHROMIUM:
3642 case GL_COUNT_DOWN_CHROMIUM:
3643 break;
3644 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003646 return false;
3647 }
3648 if (!isPow2(mask + 1))
3649 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003650 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003651 return false;
3652 }
3653
3654 return true;
3655}
3656
3657bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3658 GLsizei numPaths,
3659 GLenum pathNameType,
3660 const void *paths,
3661 GLuint pathBase,
3662 GLint reference,
3663 GLuint mask,
3664 GLenum coverMode,
3665 GLenum transformType,
3666 const GLfloat *transformValues)
3667{
3668 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3669 transformType, transformValues))
3670 return false;
3671
3672 switch (coverMode)
3673 {
3674 case GL_CONVEX_HULL_CHROMIUM:
3675 case GL_BOUNDING_BOX_CHROMIUM:
3676 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3677 break;
3678 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003679 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003680 return false;
3681 }
3682
3683 return true;
3684}
3685
Sami Väisänen46eaa942016-06-29 10:26:37 +03003686bool ValidateBindFragmentInputLocation(Context *context,
3687 GLuint program,
3688 GLint location,
3689 const GLchar *name)
3690{
3691 if (!context->getExtensions().pathRendering)
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003694 return false;
3695 }
3696
3697 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3698 if (location >= MaxLocation)
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003701 return false;
3702 }
3703
3704 const auto *programObject = context->getProgram(program);
3705 if (!programObject)
3706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003708 return false;
3709 }
3710
3711 if (!name)
3712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003714 return false;
3715 }
3716
3717 if (angle::BeginsWith(name, "gl_"))
3718 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003720 return false;
3721 }
3722
3723 return true;
3724}
3725
3726bool ValidateProgramPathFragmentInputGen(Context *context,
3727 GLuint program,
3728 GLint location,
3729 GLenum genMode,
3730 GLint components,
3731 const GLfloat *coeffs)
3732{
3733 if (!context->getExtensions().pathRendering)
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003736 return false;
3737 }
3738
3739 const auto *programObject = context->getProgram(program);
3740 if (!programObject || programObject->isFlaggedForDeletion())
3741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003742 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003743 return false;
3744 }
3745
3746 if (!programObject->isLinked())
3747 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003748 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003749 return false;
3750 }
3751
3752 switch (genMode)
3753 {
3754 case GL_NONE:
3755 if (components != 0)
3756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003758 return false;
3759 }
3760 break;
3761
3762 case GL_OBJECT_LINEAR_CHROMIUM:
3763 case GL_EYE_LINEAR_CHROMIUM:
3764 case GL_CONSTANT_CHROMIUM:
3765 if (components < 1 || components > 4)
3766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003768 return false;
3769 }
3770 if (!coeffs)
3771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003772 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003773 return false;
3774 }
3775 break;
3776
3777 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003779 return false;
3780 }
3781
3782 // If the location is -1 then the command is silently ignored
3783 // and no further validation is needed.
3784 if (location == -1)
3785 return true;
3786
Jamie Madillbd044ed2017-06-05 12:59:21 -04003787 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003788
3789 if (!binding.valid)
3790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003791 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003792 return false;
3793 }
3794
3795 if (binding.type != GL_NONE)
3796 {
3797 GLint expectedComponents = 0;
3798 switch (binding.type)
3799 {
3800 case GL_FLOAT:
3801 expectedComponents = 1;
3802 break;
3803 case GL_FLOAT_VEC2:
3804 expectedComponents = 2;
3805 break;
3806 case GL_FLOAT_VEC3:
3807 expectedComponents = 3;
3808 break;
3809 case GL_FLOAT_VEC4:
3810 expectedComponents = 4;
3811 break;
3812 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003813 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003814 InvalidOperation()
3815 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003816 return false;
3817 }
3818 if (expectedComponents != components && genMode != GL_NONE)
3819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003820 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003821 return false;
3822 }
3823 }
3824 return true;
3825}
3826
Geoff Lang97073d12016-04-20 10:42:34 -07003827bool ValidateCopyTextureCHROMIUM(Context *context,
3828 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003829 GLint sourceLevel,
3830 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003831 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003832 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003833 GLint internalFormat,
3834 GLenum destType,
3835 GLboolean unpackFlipY,
3836 GLboolean unpackPremultiplyAlpha,
3837 GLboolean unpackUnmultiplyAlpha)
3838{
3839 if (!context->getExtensions().copyTexture)
3840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003841 context->handleError(InvalidOperation()
3842 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003843 return false;
3844 }
3845
Geoff Lang4f0e0032017-05-01 16:04:35 -04003846 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003847 if (source == nullptr)
3848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003849 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003850 return false;
3851 }
3852
3853 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003856 return false;
3857 }
3858
3859 GLenum sourceTarget = source->getTarget();
3860 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003861
3862 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003864 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003865 return false;
3866 }
3867
Geoff Lang4f0e0032017-05-01 16:04:35 -04003868 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3869 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3870 if (sourceWidth == 0 || sourceHeight == 0)
3871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003873 return false;
3874 }
3875
3876 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3877 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003880 return false;
3881 }
3882
Geoff Lang63458a32017-10-30 15:16:53 -04003883 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3884 {
3885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
3886 return false;
3887 }
3888
Geoff Lang4f0e0032017-05-01 16:04:35 -04003889 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003890 if (dest == nullptr)
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidValue()
3893 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003894 return false;
3895 }
3896
Geoff Lang4f0e0032017-05-01 16:04:35 -04003897 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003900 return false;
3901 }
3902
Geoff Lang4f0e0032017-05-01 16:04:35 -04003903 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3904 sourceHeight))
3905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003906 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003907 return false;
3908 }
3909
Geoff Lang97073d12016-04-20 10:42:34 -07003910 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003913 return false;
3914 }
3915
Geoff Lang4f0e0032017-05-01 16:04:35 -04003916 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(
3919 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003920 return false;
3921 }
3922
Geoff Lang97073d12016-04-20 10:42:34 -07003923 if (dest->getImmutableFormat())
3924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003925 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003926 return false;
3927 }
3928
3929 return true;
3930}
3931
3932bool ValidateCopySubTextureCHROMIUM(Context *context,
3933 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003934 GLint sourceLevel,
3935 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003936 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003937 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003938 GLint xoffset,
3939 GLint yoffset,
3940 GLint x,
3941 GLint y,
3942 GLsizei width,
3943 GLsizei height,
3944 GLboolean unpackFlipY,
3945 GLboolean unpackPremultiplyAlpha,
3946 GLboolean unpackUnmultiplyAlpha)
3947{
3948 if (!context->getExtensions().copyTexture)
3949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003950 context->handleError(InvalidOperation()
3951 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003952 return false;
3953 }
3954
Geoff Lang4f0e0032017-05-01 16:04:35 -04003955 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003956 if (source == nullptr)
3957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003959 return false;
3960 }
3961
3962 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003964 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003965 return false;
3966 }
3967
3968 GLenum sourceTarget = source->getTarget();
3969 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003970
3971 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003973 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003974 return false;
3975 }
3976
3977 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3978 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidValue()
3981 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003982 return false;
3983 }
3984
3985 if (x < 0 || y < 0)
3986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003988 return false;
3989 }
3990
3991 if (width < 0 || height < 0)
3992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003993 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003994 return false;
3995 }
3996
Geoff Lang4f0e0032017-05-01 16:04:35 -04003997 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3998 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004000 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07004001 return false;
4002 }
4003
Geoff Lang4f0e0032017-05-01 16:04:35 -04004004 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
4005 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07004008 return false;
4009 }
4010
Geoff Lang63458a32017-10-30 15:16:53 -04004011 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
4012 {
4013 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
4014 return false;
4015 }
4016
Geoff Lang4f0e0032017-05-01 16:04:35 -04004017 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07004018 if (dest == nullptr)
4019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004020 context->handleError(InvalidValue()
4021 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07004022 return false;
4023 }
4024
Geoff Lang4f0e0032017-05-01 16:04:35 -04004025 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07004026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07004028 return false;
4029 }
4030
Geoff Lang4f0e0032017-05-01 16:04:35 -04004031 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07004032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004033 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004034 return false;
4035 }
4036
Geoff Lang4f0e0032017-05-01 16:04:35 -04004037 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
4038 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04004039 context
4040 ->handleError(InvalidOperation()
4041 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04004042 return false;
4043 }
4044
4045 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
4046 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004048 context->handleError(InvalidOperation()
4049 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004050 return false;
4051 }
4052
4053 if (xoffset < 0 || yoffset < 0)
4054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004055 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07004056 return false;
4057 }
4058
Geoff Lang4f0e0032017-05-01 16:04:35 -04004059 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
4060 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07004063 return false;
4064 }
4065
4066 return true;
4067}
4068
Geoff Lang47110bf2016-04-20 11:13:22 -07004069bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
4070{
4071 if (!context->getExtensions().copyCompressedTexture)
4072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004073 context->handleError(InvalidOperation()
4074 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004075 return false;
4076 }
4077
4078 const gl::Texture *source = context->getTexture(sourceId);
4079 if (source == nullptr)
4080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004081 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004082 return false;
4083 }
4084
4085 if (source->getTarget() != GL_TEXTURE_2D)
4086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004087 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004088 return false;
4089 }
4090
4091 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004093 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004094 return false;
4095 }
4096
4097 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4098 if (!sourceFormat.info->compressed)
4099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004100 context->handleError(InvalidOperation()
4101 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004102 return false;
4103 }
4104
4105 const gl::Texture *dest = context->getTexture(destId);
4106 if (dest == nullptr)
4107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004108 context->handleError(InvalidValue()
4109 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004110 return false;
4111 }
4112
4113 if (dest->getTarget() != GL_TEXTURE_2D)
4114 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004115 context->handleError(InvalidValue()
4116 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004117 return false;
4118 }
4119
4120 if (dest->getImmutableFormat())
4121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004122 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004123 return false;
4124 }
4125
4126 return true;
4127}
4128
Martin Radev4c4c8e72016-08-04 12:25:34 +03004129bool ValidateCreateShader(Context *context, GLenum type)
4130{
4131 switch (type)
4132 {
4133 case GL_VERTEX_SHADER:
4134 case GL_FRAGMENT_SHADER:
4135 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004136
Martin Radev4c4c8e72016-08-04 12:25:34 +03004137 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004138 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004139 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Langeb66a6e2016-10-31 13:06:12 -04004141 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004142 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004143 break;
4144
Martin Radev4c4c8e72016-08-04 12:25:34 +03004145 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004147 return false;
4148 }
Jamie Madill29639852016-09-02 15:00:09 -04004149
4150 return true;
4151}
4152
4153bool ValidateBufferData(ValidationContext *context,
4154 GLenum target,
4155 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004156 const void *data,
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004157 BufferUsage usage)
Jamie Madill29639852016-09-02 15:00:09 -04004158{
4159 if (size < 0)
4160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004161 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004162 return false;
4163 }
4164
4165 switch (usage)
4166 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004167 case BufferUsage::StreamDraw:
4168 case BufferUsage::StaticDraw:
4169 case BufferUsage::DynamicDraw:
Jamie Madill29639852016-09-02 15:00:09 -04004170 break;
4171
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004172 case BufferUsage::StreamRead:
4173 case BufferUsage::StaticRead:
4174 case BufferUsage::DynamicRead:
4175 case BufferUsage::StreamCopy:
4176 case BufferUsage::StaticCopy:
4177 case BufferUsage::DynamicCopy:
Jamie Madill29639852016-09-02 15:00:09 -04004178 if (context->getClientMajorVersion() < 3)
4179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004181 return false;
4182 }
4183 break;
4184
4185 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004187 return false;
4188 }
4189
4190 if (!ValidBufferTarget(context, target))
4191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004193 return false;
4194 }
4195
4196 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4197
4198 if (!buffer)
4199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004201 return false;
4202 }
4203
4204 return true;
4205}
4206
4207bool ValidateBufferSubData(ValidationContext *context,
4208 GLenum target,
4209 GLintptr offset,
4210 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004211 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004212{
Brandon Jones6cad5662017-06-14 13:25:13 -07004213 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004215 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4216 return false;
4217 }
4218
4219 if (offset < 0)
4220 {
4221 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004222 return false;
4223 }
4224
4225 if (!ValidBufferTarget(context, target))
4226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004228 return false;
4229 }
4230
4231 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4232
4233 if (!buffer)
4234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004236 return false;
4237 }
4238
4239 if (buffer->isMapped())
4240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004241 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004242 return false;
4243 }
4244
4245 // Check for possible overflow of size + offset
4246 angle::CheckedNumeric<size_t> checkedSize(size);
4247 checkedSize += offset;
4248 if (!checkedSize.IsValid())
4249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004250 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004251 return false;
4252 }
4253
4254 if (size + offset > buffer->getSize())
4255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004256 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004257 return false;
4258 }
4259
Martin Radev4c4c8e72016-08-04 12:25:34 +03004260 return true;
4261}
4262
Geoff Lang111a99e2017-10-17 10:58:41 -04004263bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004264{
Geoff Langc339c4e2016-11-29 10:37:36 -05004265 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004267 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004268 return false;
4269 }
4270
Geoff Lang111a99e2017-10-17 10:58:41 -04004271 if (!context->isExtensionRequestable(name))
Geoff Langc287ea62016-09-16 14:46:51 -04004272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004273 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004274 return false;
4275 }
4276
4277 return true;
4278}
4279
Jamie Madillef300b12016-10-07 15:12:09 -04004280bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4281{
4282 if (texture < GL_TEXTURE0 ||
4283 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004285 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004286 return false;
4287 }
4288
4289 return true;
4290}
4291
4292bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4293{
4294 Program *programObject = GetValidProgram(context, program);
4295 if (!programObject)
4296 {
4297 return false;
4298 }
4299
4300 Shader *shaderObject = GetValidShader(context, shader);
4301 if (!shaderObject)
4302 {
4303 return false;
4304 }
4305
4306 switch (shaderObject->getType())
4307 {
4308 case GL_VERTEX_SHADER:
4309 {
4310 if (programObject->getAttachedVertexShader())
4311 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004313 return false;
4314 }
4315 break;
4316 }
4317 case GL_FRAGMENT_SHADER:
4318 {
4319 if (programObject->getAttachedFragmentShader())
4320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004322 return false;
4323 }
4324 break;
4325 }
4326 case GL_COMPUTE_SHADER:
4327 {
4328 if (programObject->getAttachedComputeShader())
4329 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004330 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004331 return false;
4332 }
4333 break;
4334 }
4335 default:
4336 UNREACHABLE();
4337 break;
4338 }
4339
4340 return true;
4341}
4342
Jamie Madill01a80ee2016-11-07 12:06:18 -05004343bool ValidateBindAttribLocation(ValidationContext *context,
4344 GLuint program,
4345 GLuint index,
4346 const GLchar *name)
4347{
4348 if (index >= MAX_VERTEX_ATTRIBS)
4349 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004350 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004351 return false;
4352 }
4353
4354 if (strncmp(name, "gl_", 3) == 0)
4355 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004357 return false;
4358 }
4359
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004360 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004361 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004362 const size_t length = strlen(name);
4363
4364 if (!IsValidESSLString(name, length))
4365 {
4366 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4367 // for shader-related entry points
4368 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4369 return false;
4370 }
4371
4372 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4373 {
4374 return false;
4375 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004376 }
4377
Jamie Madill01a80ee2016-11-07 12:06:18 -05004378 return GetValidProgram(context, program) != nullptr;
4379}
4380
4381bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4382{
4383 if (!ValidBufferTarget(context, target))
4384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004386 return false;
4387 }
4388
4389 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4390 !context->isBufferGenerated(buffer))
4391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004393 return false;
4394 }
4395
4396 return true;
4397}
4398
4399bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4400{
4401 if (!ValidFramebufferTarget(target))
4402 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004404 return false;
4405 }
4406
4407 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4408 !context->isFramebufferGenerated(framebuffer))
4409 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004410 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004411 return false;
4412 }
4413
4414 return true;
4415}
4416
4417bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4418{
4419 if (target != GL_RENDERBUFFER)
4420 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004422 return false;
4423 }
4424
4425 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4426 !context->isRenderbufferGenerated(renderbuffer))
4427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004429 return false;
4430 }
4431
4432 return true;
4433}
4434
Geoff Lang50cac572017-09-26 17:37:43 -04004435static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004436{
4437 switch (mode)
4438 {
4439 case GL_FUNC_ADD:
4440 case GL_FUNC_SUBTRACT:
4441 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004442 return true;
4443
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004444 case GL_MIN:
4445 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004446 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004447
4448 default:
4449 return false;
4450 }
4451}
4452
Jamie Madillc1d770e2017-04-13 17:31:24 -04004453bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004454 GLfloat red,
4455 GLfloat green,
4456 GLfloat blue,
4457 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004458{
4459 return true;
4460}
4461
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004462bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4463{
Geoff Lang50cac572017-09-26 17:37:43 -04004464 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004465 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004466 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004467 return false;
4468 }
4469
4470 return true;
4471}
4472
4473bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4474{
Geoff Lang50cac572017-09-26 17:37:43 -04004475 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004476 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004478 return false;
4479 }
4480
Geoff Lang50cac572017-09-26 17:37:43 -04004481 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004484 return false;
4485 }
4486
4487 return true;
4488}
4489
4490bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4491{
4492 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4493}
4494
4495static bool ValidSrcBlendFunc(GLenum srcBlend)
4496{
4497 switch (srcBlend)
4498 {
4499 case GL_ZERO:
4500 case GL_ONE:
4501 case GL_SRC_COLOR:
4502 case GL_ONE_MINUS_SRC_COLOR:
4503 case GL_DST_COLOR:
4504 case GL_ONE_MINUS_DST_COLOR:
4505 case GL_SRC_ALPHA:
4506 case GL_ONE_MINUS_SRC_ALPHA:
4507 case GL_DST_ALPHA:
4508 case GL_ONE_MINUS_DST_ALPHA:
4509 case GL_CONSTANT_COLOR:
4510 case GL_ONE_MINUS_CONSTANT_COLOR:
4511 case GL_CONSTANT_ALPHA:
4512 case GL_ONE_MINUS_CONSTANT_ALPHA:
4513 case GL_SRC_ALPHA_SATURATE:
4514 return true;
4515
4516 default:
4517 return false;
4518 }
4519}
4520
4521static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4522{
4523 switch (dstBlend)
4524 {
4525 case GL_ZERO:
4526 case GL_ONE:
4527 case GL_SRC_COLOR:
4528 case GL_ONE_MINUS_SRC_COLOR:
4529 case GL_DST_COLOR:
4530 case GL_ONE_MINUS_DST_COLOR:
4531 case GL_SRC_ALPHA:
4532 case GL_ONE_MINUS_SRC_ALPHA:
4533 case GL_DST_ALPHA:
4534 case GL_ONE_MINUS_DST_ALPHA:
4535 case GL_CONSTANT_COLOR:
4536 case GL_ONE_MINUS_CONSTANT_COLOR:
4537 case GL_CONSTANT_ALPHA:
4538 case GL_ONE_MINUS_CONSTANT_ALPHA:
4539 return true;
4540
4541 case GL_SRC_ALPHA_SATURATE:
4542 return (contextMajorVersion >= 3);
4543
4544 default:
4545 return false;
4546 }
4547}
4548
4549bool ValidateBlendFuncSeparate(ValidationContext *context,
4550 GLenum srcRGB,
4551 GLenum dstRGB,
4552 GLenum srcAlpha,
4553 GLenum dstAlpha)
4554{
4555 if (!ValidSrcBlendFunc(srcRGB))
4556 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004558 return false;
4559 }
4560
4561 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4562 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004563 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004564 return false;
4565 }
4566
4567 if (!ValidSrcBlendFunc(srcAlpha))
4568 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004569 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004570 return false;
4571 }
4572
4573 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004576 return false;
4577 }
4578
Frank Henigman146e8a12017-03-02 23:22:37 -05004579 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4580 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004581 {
4582 bool constantColorUsed =
4583 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4584 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4585
4586 bool constantAlphaUsed =
4587 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4588 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4589
4590 if (constantColorUsed && constantAlphaUsed)
4591 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004592 const char *msg;
4593 if (context->getExtensions().webglCompatibility)
4594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004595 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004596 }
4597 else
4598 {
4599 msg =
4600 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4601 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4602 "implementation.";
4603 ERR() << msg;
4604 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004605 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004606 return false;
4607 }
4608 }
4609
4610 return true;
4611}
4612
Geoff Langc339c4e2016-11-29 10:37:36 -05004613bool ValidateGetString(Context *context, GLenum name)
4614{
4615 switch (name)
4616 {
4617 case GL_VENDOR:
4618 case GL_RENDERER:
4619 case GL_VERSION:
4620 case GL_SHADING_LANGUAGE_VERSION:
4621 case GL_EXTENSIONS:
4622 break;
4623
4624 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4625 if (!context->getExtensions().requestExtension)
4626 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004627 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004628 return false;
4629 }
4630 break;
4631
4632 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004634 return false;
4635 }
4636
4637 return true;
4638}
4639
Geoff Lang47c48082016-12-07 15:38:13 -05004640bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4641{
4642 if (width <= 0.0f || isNaN(width))
4643 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004644 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004645 return false;
4646 }
4647
4648 return true;
4649}
4650
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004651bool ValidateVertexAttribPointer(ValidationContext *context,
4652 GLuint index,
4653 GLint size,
4654 GLenum type,
4655 GLboolean normalized,
4656 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004657 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004658{
Shao80957d92017-02-20 21:25:59 +08004659 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004660 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004661 return false;
4662 }
4663
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004664 if (stride < 0)
4665 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004666 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004667 return false;
4668 }
4669
Shao80957d92017-02-20 21:25:59 +08004670 const Caps &caps = context->getCaps();
4671 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004672 {
Shao80957d92017-02-20 21:25:59 +08004673 if (stride > caps.maxVertexAttribStride)
4674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004675 context->handleError(InvalidValue()
4676 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004677 return false;
4678 }
4679
4680 if (index >= caps.maxVertexAttribBindings)
4681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004682 context->handleError(InvalidValue()
4683 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004684 return false;
4685 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004686 }
4687
4688 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4689 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4690 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4691 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004692 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4693 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004694 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004696 context
4697 ->handleError(InvalidOperation()
4698 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004699 return false;
4700 }
4701
4702 if (context->getExtensions().webglCompatibility)
4703 {
4704 // WebGL 1.0 [Section 6.14] Fixed point support
4705 // The WebGL API does not support the GL_FIXED data type.
4706 if (type == GL_FIXED)
4707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004708 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004709 return false;
4710 }
4711
Geoff Lang2d62ab72017-03-23 16:54:40 -04004712 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004713 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004714 return false;
4715 }
4716 }
4717
4718 return true;
4719}
4720
Jamie Madill876429b2017-04-20 15:46:24 -04004721bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004722{
4723 if (context->getExtensions().webglCompatibility && zNear > zFar)
4724 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004725 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004726 return false;
4727 }
4728
4729 return true;
4730}
4731
Jamie Madille8fb6402017-02-14 17:56:40 -05004732bool ValidateRenderbufferStorage(ValidationContext *context,
4733 GLenum target,
4734 GLenum internalformat,
4735 GLsizei width,
4736 GLsizei height)
4737{
4738 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4739 height);
4740}
4741
4742bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4743 GLenum target,
4744 GLsizei samples,
4745 GLenum internalformat,
4746 GLsizei width,
4747 GLsizei height)
4748{
4749 if (!context->getExtensions().framebufferMultisample)
4750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004751 context->handleError(InvalidOperation()
4752 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004753 return false;
4754 }
4755
4756 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4757 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4758 // generated.
4759 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004761 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004762 return false;
4763 }
4764
4765 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4766 // the specified storage. This is different than ES 3.0 in which a sample number higher
4767 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4768 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4769 if (context->getClientMajorVersion() >= 3)
4770 {
4771 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4772 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004774 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004775 return false;
4776 }
4777 }
4778
4779 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4780 width, height);
4781}
4782
Jamie Madillc1d770e2017-04-13 17:31:24 -04004783bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4784{
4785 if (!ValidFramebufferTarget(target))
4786 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004788 return false;
4789 }
4790
4791 return true;
4792}
4793
4794bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004795 GLfloat red,
4796 GLfloat green,
4797 GLfloat blue,
4798 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004799{
4800 return true;
4801}
4802
Jamie Madill876429b2017-04-20 15:46:24 -04004803bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004804{
4805 return true;
4806}
4807
4808bool ValidateClearStencil(ValidationContext *context, GLint s)
4809{
4810 return true;
4811}
4812
4813bool ValidateColorMask(ValidationContext *context,
4814 GLboolean red,
4815 GLboolean green,
4816 GLboolean blue,
4817 GLboolean alpha)
4818{
4819 return true;
4820}
4821
4822bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4823{
4824 return true;
4825}
4826
4827bool ValidateCreateProgram(ValidationContext *context)
4828{
4829 return true;
4830}
4831
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004832bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004833{
4834 switch (mode)
4835 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004836 case CullFaceMode::Front:
4837 case CullFaceMode::Back:
4838 case CullFaceMode::FrontAndBack:
Jamie Madillc1d770e2017-04-13 17:31:24 -04004839 break;
4840
4841 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004842 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004843 return false;
4844 }
4845
4846 return true;
4847}
4848
4849bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4850{
4851 if (program == 0)
4852 {
4853 return false;
4854 }
4855
4856 if (!context->getProgram(program))
4857 {
4858 if (context->getShader(program))
4859 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004861 return false;
4862 }
4863 else
4864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004865 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004866 return false;
4867 }
4868 }
4869
4870 return true;
4871}
4872
4873bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4874{
4875 if (shader == 0)
4876 {
4877 return false;
4878 }
4879
4880 if (!context->getShader(shader))
4881 {
4882 if (context->getProgram(shader))
4883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004885 return false;
4886 }
4887 else
4888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004889 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004890 return false;
4891 }
4892 }
4893
4894 return true;
4895}
4896
4897bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4898{
4899 switch (func)
4900 {
4901 case GL_NEVER:
4902 case GL_ALWAYS:
4903 case GL_LESS:
4904 case GL_LEQUAL:
4905 case GL_EQUAL:
4906 case GL_GREATER:
4907 case GL_GEQUAL:
4908 case GL_NOTEQUAL:
4909 break;
4910
4911 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004912 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004913 return false;
4914 }
4915
4916 return true;
4917}
4918
4919bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4920{
4921 return true;
4922}
4923
4924bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4925{
4926 Program *programObject = GetValidProgram(context, program);
4927 if (!programObject)
4928 {
4929 return false;
4930 }
4931
4932 Shader *shaderObject = GetValidShader(context, shader);
4933 if (!shaderObject)
4934 {
4935 return false;
4936 }
4937
4938 const Shader *attachedShader = nullptr;
4939
4940 switch (shaderObject->getType())
4941 {
4942 case GL_VERTEX_SHADER:
4943 {
4944 attachedShader = programObject->getAttachedVertexShader();
4945 break;
4946 }
4947 case GL_FRAGMENT_SHADER:
4948 {
4949 attachedShader = programObject->getAttachedFragmentShader();
4950 break;
4951 }
4952 case GL_COMPUTE_SHADER:
4953 {
4954 attachedShader = programObject->getAttachedComputeShader();
4955 break;
4956 }
4957 default:
4958 UNREACHABLE();
4959 return false;
4960 }
4961
4962 if (attachedShader != shaderObject)
4963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004965 return false;
4966 }
4967
4968 return true;
4969}
4970
4971bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4972{
4973 if (index >= MAX_VERTEX_ATTRIBS)
4974 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004975 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004976 return false;
4977 }
4978
4979 return true;
4980}
4981
4982bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4983{
4984 if (index >= MAX_VERTEX_ATTRIBS)
4985 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004986 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004987 return false;
4988 }
4989
4990 return true;
4991}
4992
4993bool ValidateFinish(ValidationContext *context)
4994{
4995 return true;
4996}
4997
4998bool ValidateFlush(ValidationContext *context)
4999{
5000 return true;
5001}
5002
5003bool ValidateFrontFace(ValidationContext *context, GLenum mode)
5004{
5005 switch (mode)
5006 {
5007 case GL_CW:
5008 case GL_CCW:
5009 break;
5010 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005011 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005012 return false;
5013 }
5014
5015 return true;
5016}
5017
5018bool ValidateGetActiveAttrib(ValidationContext *context,
5019 GLuint program,
5020 GLuint index,
5021 GLsizei bufsize,
5022 GLsizei *length,
5023 GLint *size,
5024 GLenum *type,
5025 GLchar *name)
5026{
5027 if (bufsize < 0)
5028 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005029 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005030 return false;
5031 }
5032
5033 Program *programObject = GetValidProgram(context, program);
5034
5035 if (!programObject)
5036 {
5037 return false;
5038 }
5039
5040 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5041 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005042 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005043 return false;
5044 }
5045
5046 return true;
5047}
5048
5049bool ValidateGetActiveUniform(ValidationContext *context,
5050 GLuint program,
5051 GLuint index,
5052 GLsizei bufsize,
5053 GLsizei *length,
5054 GLint *size,
5055 GLenum *type,
5056 GLchar *name)
5057{
5058 if (bufsize < 0)
5059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005060 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005061 return false;
5062 }
5063
5064 Program *programObject = GetValidProgram(context, program);
5065
5066 if (!programObject)
5067 {
5068 return false;
5069 }
5070
5071 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5072 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005073 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005074 return false;
5075 }
5076
5077 return true;
5078}
5079
5080bool ValidateGetAttachedShaders(ValidationContext *context,
5081 GLuint program,
5082 GLsizei maxcount,
5083 GLsizei *count,
5084 GLuint *shaders)
5085{
5086 if (maxcount < 0)
5087 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005088 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005089 return false;
5090 }
5091
5092 Program *programObject = GetValidProgram(context, program);
5093
5094 if (!programObject)
5095 {
5096 return false;
5097 }
5098
5099 return true;
5100}
5101
5102bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5103{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005104 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5105 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005106 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005108 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005109 return false;
5110 }
5111
Jamie Madillc1d770e2017-04-13 17:31:24 -04005112 Program *programObject = GetValidProgram(context, program);
5113
5114 if (!programObject)
5115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005117 return false;
5118 }
5119
5120 if (!programObject->isLinked())
5121 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005123 return false;
5124 }
5125
5126 return true;
5127}
5128
5129bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5130{
5131 GLenum nativeType;
5132 unsigned int numParams = 0;
5133 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5134}
5135
5136bool ValidateGetError(ValidationContext *context)
5137{
5138 return true;
5139}
5140
5141bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5142{
5143 GLenum nativeType;
5144 unsigned int numParams = 0;
5145 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5146}
5147
5148bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5149{
5150 GLenum nativeType;
5151 unsigned int numParams = 0;
5152 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5153}
5154
5155bool ValidateGetProgramInfoLog(ValidationContext *context,
5156 GLuint program,
5157 GLsizei bufsize,
5158 GLsizei *length,
5159 GLchar *infolog)
5160{
5161 if (bufsize < 0)
5162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005163 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005164 return false;
5165 }
5166
5167 Program *programObject = GetValidProgram(context, program);
5168 if (!programObject)
5169 {
5170 return false;
5171 }
5172
5173 return true;
5174}
5175
5176bool ValidateGetShaderInfoLog(ValidationContext *context,
5177 GLuint shader,
5178 GLsizei bufsize,
5179 GLsizei *length,
5180 GLchar *infolog)
5181{
5182 if (bufsize < 0)
5183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005184 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005185 return false;
5186 }
5187
5188 Shader *shaderObject = GetValidShader(context, shader);
5189 if (!shaderObject)
5190 {
5191 return false;
5192 }
5193
5194 return true;
5195}
5196
5197bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5198 GLenum shadertype,
5199 GLenum precisiontype,
5200 GLint *range,
5201 GLint *precision)
5202{
5203 switch (shadertype)
5204 {
5205 case GL_VERTEX_SHADER:
5206 case GL_FRAGMENT_SHADER:
5207 break;
5208 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005209 context->handleError(InvalidOperation()
5210 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005211 return false;
5212 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005214 return false;
5215 }
5216
5217 switch (precisiontype)
5218 {
5219 case GL_LOW_FLOAT:
5220 case GL_MEDIUM_FLOAT:
5221 case GL_HIGH_FLOAT:
5222 case GL_LOW_INT:
5223 case GL_MEDIUM_INT:
5224 case GL_HIGH_INT:
5225 break;
5226
5227 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005228 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005229 return false;
5230 }
5231
5232 return true;
5233}
5234
5235bool ValidateGetShaderSource(ValidationContext *context,
5236 GLuint shader,
5237 GLsizei bufsize,
5238 GLsizei *length,
5239 GLchar *source)
5240{
5241 if (bufsize < 0)
5242 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005243 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005244 return false;
5245 }
5246
5247 Shader *shaderObject = GetValidShader(context, shader);
5248 if (!shaderObject)
5249 {
5250 return false;
5251 }
5252
5253 return true;
5254}
5255
5256bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5257{
5258 if (strstr(name, "gl_") == name)
5259 {
5260 return false;
5261 }
5262
Geoff Langfc32e8b2017-05-31 14:16:59 -04005263 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5264 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005265 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005268 return false;
5269 }
5270
Jamie Madillc1d770e2017-04-13 17:31:24 -04005271 Program *programObject = GetValidProgram(context, program);
5272
5273 if (!programObject)
5274 {
5275 return false;
5276 }
5277
5278 if (!programObject->isLinked())
5279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005281 return false;
5282 }
5283
5284 return true;
5285}
5286
5287bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5288{
5289 switch (mode)
5290 {
5291 case GL_FASTEST:
5292 case GL_NICEST:
5293 case GL_DONT_CARE:
5294 break;
5295
5296 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005297 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005298 return false;
5299 }
5300
5301 switch (target)
5302 {
5303 case GL_GENERATE_MIPMAP_HINT:
5304 break;
5305
Geoff Lange7bd2182017-06-16 16:13:13 -04005306 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5307 if (context->getClientVersion() < ES_3_0 &&
5308 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005309 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005310 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005311 return false;
5312 }
5313 break;
5314
5315 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005316 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005317 return false;
5318 }
5319
5320 return true;
5321}
5322
5323bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5324{
5325 return true;
5326}
5327
5328bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5329{
5330 return true;
5331}
5332
5333bool ValidateIsProgram(ValidationContext *context, GLuint program)
5334{
5335 return true;
5336}
5337
5338bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5339{
5340 return true;
5341}
5342
5343bool ValidateIsShader(ValidationContext *context, GLuint shader)
5344{
5345 return true;
5346}
5347
5348bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5349{
5350 return true;
5351}
5352
5353bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5354{
5355 if (context->getClientMajorVersion() < 3)
5356 {
5357 switch (pname)
5358 {
5359 case GL_UNPACK_IMAGE_HEIGHT:
5360 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005361 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005362 return false;
5363
5364 case GL_UNPACK_ROW_LENGTH:
5365 case GL_UNPACK_SKIP_ROWS:
5366 case GL_UNPACK_SKIP_PIXELS:
5367 if (!context->getExtensions().unpackSubimage)
5368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005369 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005370 return false;
5371 }
5372 break;
5373
5374 case GL_PACK_ROW_LENGTH:
5375 case GL_PACK_SKIP_ROWS:
5376 case GL_PACK_SKIP_PIXELS:
5377 if (!context->getExtensions().packSubimage)
5378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005379 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005380 return false;
5381 }
5382 break;
5383 }
5384 }
5385
5386 if (param < 0)
5387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005388 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005389 return false;
5390 }
5391
5392 switch (pname)
5393 {
5394 case GL_UNPACK_ALIGNMENT:
5395 if (param != 1 && param != 2 && param != 4 && param != 8)
5396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005397 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005398 return false;
5399 }
5400 break;
5401
5402 case GL_PACK_ALIGNMENT:
5403 if (param != 1 && param != 2 && param != 4 && param != 8)
5404 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005405 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005406 return false;
5407 }
5408 break;
5409
5410 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005411 if (!context->getExtensions().packReverseRowOrder)
5412 {
5413 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5414 }
5415 break;
5416
Jamie Madillc1d770e2017-04-13 17:31:24 -04005417 case GL_UNPACK_ROW_LENGTH:
5418 case GL_UNPACK_IMAGE_HEIGHT:
5419 case GL_UNPACK_SKIP_IMAGES:
5420 case GL_UNPACK_SKIP_ROWS:
5421 case GL_UNPACK_SKIP_PIXELS:
5422 case GL_PACK_ROW_LENGTH:
5423 case GL_PACK_SKIP_ROWS:
5424 case GL_PACK_SKIP_PIXELS:
5425 break;
5426
5427 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005429 return false;
5430 }
5431
5432 return true;
5433}
5434
5435bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5436{
5437 return true;
5438}
5439
5440bool ValidateReleaseShaderCompiler(ValidationContext *context)
5441{
5442 return true;
5443}
5444
Jamie Madill876429b2017-04-20 15:46:24 -04005445bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005446{
5447 return true;
5448}
5449
5450bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5451{
5452 if (width < 0 || height < 0)
5453 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005454 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005455 return false;
5456 }
5457
5458 return true;
5459}
5460
5461bool ValidateShaderBinary(ValidationContext *context,
5462 GLsizei n,
5463 const GLuint *shaders,
5464 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005465 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005466 GLsizei length)
5467{
5468 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5469 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5470 shaderBinaryFormats.end())
5471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005472 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005473 return false;
5474 }
5475
5476 return true;
5477}
5478
5479bool ValidateShaderSource(ValidationContext *context,
5480 GLuint shader,
5481 GLsizei count,
5482 const GLchar *const *string,
5483 const GLint *length)
5484{
5485 if (count < 0)
5486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005488 return false;
5489 }
5490
Geoff Langfc32e8b2017-05-31 14:16:59 -04005491 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5492 // shader-related entry points
5493 if (context->getExtensions().webglCompatibility)
5494 {
5495 for (GLsizei i = 0; i < count; i++)
5496 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005497 size_t len =
5498 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005499
5500 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005501 if (!IsValidESSLShaderSourceString(string[i], len,
5502 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005503 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005504 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005505 return false;
5506 }
5507 }
5508 }
5509
Jamie Madillc1d770e2017-04-13 17:31:24 -04005510 Shader *shaderObject = GetValidShader(context, shader);
5511 if (!shaderObject)
5512 {
5513 return false;
5514 }
5515
5516 return true;
5517}
5518
5519bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5520{
5521 if (!IsValidStencilFunc(func))
5522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005524 return false;
5525 }
5526
5527 return true;
5528}
5529
5530bool ValidateStencilFuncSeparate(ValidationContext *context,
5531 GLenum face,
5532 GLenum func,
5533 GLint ref,
5534 GLuint mask)
5535{
5536 if (!IsValidStencilFace(face))
5537 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005539 return false;
5540 }
5541
5542 if (!IsValidStencilFunc(func))
5543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005545 return false;
5546 }
5547
5548 return true;
5549}
5550
5551bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5552{
5553 return true;
5554}
5555
5556bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5557{
5558 if (!IsValidStencilFace(face))
5559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005561 return false;
5562 }
5563
5564 return true;
5565}
5566
5567bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5568{
5569 if (!IsValidStencilOp(fail))
5570 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005571 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005572 return false;
5573 }
5574
5575 if (!IsValidStencilOp(zfail))
5576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005578 return false;
5579 }
5580
5581 if (!IsValidStencilOp(zpass))
5582 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005583 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005584 return false;
5585 }
5586
5587 return true;
5588}
5589
5590bool ValidateStencilOpSeparate(ValidationContext *context,
5591 GLenum face,
5592 GLenum fail,
5593 GLenum zfail,
5594 GLenum zpass)
5595{
5596 if (!IsValidStencilFace(face))
5597 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005598 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005599 return false;
5600 }
5601
5602 return ValidateStencilOp(context, fail, zfail, zpass);
5603}
5604
5605bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5606{
5607 return ValidateUniform(context, GL_FLOAT, location, 1);
5608}
5609
5610bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5611{
5612 return ValidateUniform(context, GL_FLOAT, location, count);
5613}
5614
Jamie Madillbe849e42017-05-02 15:49:00 -04005615bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5616{
5617 return ValidateUniform1iv(context, location, 1, &x);
5618}
5619
Jamie Madillc1d770e2017-04-13 17:31:24 -04005620bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5621{
5622 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5623}
5624
5625bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5626{
5627 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5628}
5629
5630bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5631{
5632 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5633}
5634
5635bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5636{
5637 return ValidateUniform(context, GL_INT_VEC2, location, count);
5638}
5639
5640bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5641{
5642 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5643}
5644
5645bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5646{
5647 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5648}
5649
5650bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5651{
5652 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5653}
5654
5655bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5656{
5657 return ValidateUniform(context, GL_INT_VEC3, location, count);
5658}
5659
5660bool ValidateUniform4f(ValidationContext *context,
5661 GLint location,
5662 GLfloat x,
5663 GLfloat y,
5664 GLfloat z,
5665 GLfloat w)
5666{
5667 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5668}
5669
5670bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5671{
5672 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5673}
5674
5675bool ValidateUniform4i(ValidationContext *context,
5676 GLint location,
5677 GLint x,
5678 GLint y,
5679 GLint z,
5680 GLint w)
5681{
5682 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5683}
5684
5685bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5686{
5687 return ValidateUniform(context, GL_INT_VEC4, location, count);
5688}
5689
5690bool ValidateUniformMatrix2fv(ValidationContext *context,
5691 GLint location,
5692 GLsizei count,
5693 GLboolean transpose,
5694 const GLfloat *value)
5695{
5696 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5697}
5698
5699bool ValidateUniformMatrix3fv(ValidationContext *context,
5700 GLint location,
5701 GLsizei count,
5702 GLboolean transpose,
5703 const GLfloat *value)
5704{
5705 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5706}
5707
5708bool ValidateUniformMatrix4fv(ValidationContext *context,
5709 GLint location,
5710 GLsizei count,
5711 GLboolean transpose,
5712 const GLfloat *value)
5713{
5714 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5715}
5716
5717bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5718{
5719 Program *programObject = GetValidProgram(context, program);
5720
5721 if (!programObject)
5722 {
5723 return false;
5724 }
5725
5726 return true;
5727}
5728
Jamie Madillc1d770e2017-04-13 17:31:24 -04005729bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5730{
5731 return ValidateVertexAttribIndex(context, index);
5732}
5733
5734bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5735{
5736 return ValidateVertexAttribIndex(context, index);
5737}
5738
5739bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5740{
5741 return ValidateVertexAttribIndex(context, index);
5742}
5743
5744bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5745{
5746 return ValidateVertexAttribIndex(context, index);
5747}
5748
5749bool ValidateVertexAttrib3f(ValidationContext *context,
5750 GLuint index,
5751 GLfloat x,
5752 GLfloat y,
5753 GLfloat z)
5754{
5755 return ValidateVertexAttribIndex(context, index);
5756}
5757
5758bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5759{
5760 return ValidateVertexAttribIndex(context, index);
5761}
5762
5763bool ValidateVertexAttrib4f(ValidationContext *context,
5764 GLuint index,
5765 GLfloat x,
5766 GLfloat y,
5767 GLfloat z,
5768 GLfloat w)
5769{
5770 return ValidateVertexAttribIndex(context, index);
5771}
5772
5773bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5774{
5775 return ValidateVertexAttribIndex(context, index);
5776}
5777
5778bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5779{
5780 if (width < 0 || height < 0)
5781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005782 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005783 return false;
5784 }
5785
5786 return true;
5787}
5788
5789bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5790{
5791 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5792}
5793
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005794bool ValidateDrawElements(ValidationContext *context,
5795 GLenum mode,
5796 GLsizei count,
5797 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005798 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005799{
5800 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5801}
5802
Jamie Madillbe849e42017-05-02 15:49:00 -04005803bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5804 GLenum target,
5805 GLenum attachment,
5806 GLenum pname,
5807 GLint *params)
5808{
5809 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5810 nullptr);
5811}
5812
5813bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5814{
5815 return ValidateGetProgramivBase(context, program, pname, nullptr);
5816}
5817
5818bool ValidateCopyTexImage2D(ValidationContext *context,
5819 GLenum target,
5820 GLint level,
5821 GLenum internalformat,
5822 GLint x,
5823 GLint y,
5824 GLsizei width,
5825 GLsizei height,
5826 GLint border)
5827{
5828 if (context->getClientMajorVersion() < 3)
5829 {
5830 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5831 0, x, y, width, height, border);
5832 }
5833
5834 ASSERT(context->getClientMajorVersion() == 3);
5835 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5836 0, x, y, width, height, border);
5837}
5838
5839bool ValidateCopyTexSubImage2D(Context *context,
5840 GLenum target,
5841 GLint level,
5842 GLint xoffset,
5843 GLint yoffset,
5844 GLint x,
5845 GLint y,
5846 GLsizei width,
5847 GLsizei height)
5848{
5849 if (context->getClientMajorVersion() < 3)
5850 {
5851 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5852 yoffset, x, y, width, height, 0);
5853 }
5854
5855 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5856 yoffset, 0, x, y, width, height, 0);
5857}
5858
5859bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5860{
5861 return ValidateGenOrDelete(context, n);
5862}
5863
5864bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5865{
5866 return ValidateGenOrDelete(context, n);
5867}
5868
5869bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5870{
5871 return ValidateGenOrDelete(context, n);
5872}
5873
5874bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5875{
5876 return ValidateGenOrDelete(context, n);
5877}
5878
5879bool ValidateDisable(Context *context, GLenum cap)
5880{
5881 if (!ValidCap(context, cap, false))
5882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005884 return false;
5885 }
5886
5887 return true;
5888}
5889
5890bool ValidateEnable(Context *context, GLenum cap)
5891{
5892 if (!ValidCap(context, cap, false))
5893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 return false;
5896 }
5897
5898 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5899 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5900 {
5901 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005902 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005903
5904 // We also output an error message to the debugger window if tracing is active, so that
5905 // developers can see the error message.
5906 ERR() << errorMessage;
5907 return false;
5908 }
5909
5910 return true;
5911}
5912
5913bool ValidateFramebufferRenderbuffer(Context *context,
5914 GLenum target,
5915 GLenum attachment,
5916 GLenum renderbuffertarget,
5917 GLuint renderbuffer)
5918{
Brandon Jones6cad5662017-06-14 13:25:13 -07005919 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5922 return false;
5923 }
5924
5925 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5926 {
5927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 return false;
5929 }
5930
5931 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5932 renderbuffertarget, renderbuffer);
5933}
5934
5935bool ValidateFramebufferTexture2D(Context *context,
5936 GLenum target,
5937 GLenum attachment,
5938 GLenum textarget,
5939 GLuint texture,
5940 GLint level)
5941{
5942 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5943 // extension
5944 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5945 level != 0)
5946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005947 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005948 return false;
5949 }
5950
5951 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5952 {
5953 return false;
5954 }
5955
5956 if (texture != 0)
5957 {
5958 gl::Texture *tex = context->getTexture(texture);
5959 ASSERT(tex);
5960
5961 const gl::Caps &caps = context->getCaps();
5962
5963 switch (textarget)
5964 {
5965 case GL_TEXTURE_2D:
5966 {
5967 if (level > gl::log2(caps.max2DTextureSize))
5968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005969 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005970 return false;
5971 }
5972 if (tex->getTarget() != GL_TEXTURE_2D)
5973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005975 return false;
5976 }
5977 }
5978 break;
5979
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005980 case GL_TEXTURE_RECTANGLE_ANGLE:
5981 {
5982 if (level != 0)
5983 {
5984 context->handleError(InvalidValue());
5985 return false;
5986 }
5987 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5988 {
5989 context->handleError(InvalidOperation()
5990 << "Textarget must match the texture target type.");
5991 return false;
5992 }
5993 }
5994 break;
5995
Jamie Madillbe849e42017-05-02 15:49:00 -04005996 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5997 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5998 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5999 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
6000 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
6001 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
6002 {
6003 if (level > gl::log2(caps.maxCubeMapTextureSize))
6004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006005 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04006006 return false;
6007 }
6008 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
6009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006010 context->handleError(InvalidOperation()
6011 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006012 return false;
6013 }
6014 }
6015 break;
6016
6017 case GL_TEXTURE_2D_MULTISAMPLE:
6018 {
6019 if (context->getClientVersion() < ES_3_1)
6020 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04006022 return false;
6023 }
6024
6025 if (level != 0)
6026 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006027 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04006028 return false;
6029 }
6030 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
6031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006032 context->handleError(InvalidOperation()
6033 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006034 return false;
6035 }
6036 }
6037 break;
6038
6039 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006041 return false;
6042 }
6043
6044 const Format &format = tex->getFormat(textarget, level);
6045 if (format.info->compressed)
6046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006047 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006048 return false;
6049 }
6050 }
6051
6052 return true;
6053}
6054
6055bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6056{
6057 return ValidateGenOrDelete(context, n);
6058}
6059
6060bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6061{
6062 return ValidateGenOrDelete(context, n);
6063}
6064
6065bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6066{
6067 return ValidateGenOrDelete(context, n);
6068}
6069
6070bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6071{
6072 return ValidateGenOrDelete(context, n);
6073}
6074
6075bool ValidateGenerateMipmap(Context *context, GLenum target)
6076{
6077 if (!ValidTextureTarget(context, target))
6078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006079 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006080 return false;
6081 }
6082
6083 Texture *texture = context->getTargetTexture(target);
6084
6085 if (texture == nullptr)
6086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006088 return false;
6089 }
6090
6091 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6092
6093 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6094 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6095 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006097 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006098 return false;
6099 }
6100
6101 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006102 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6103 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6104 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006105 {
6106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6107 return false;
6108 }
6109
Geoff Lang536eca12017-09-13 11:23:35 -04006110 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6111 bool formatUnsized = !format.sized;
6112 bool formatColorRenderableAndFilterable =
6113 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6114 format.renderSupport(context->getClientVersion(), context->getExtensions());
6115 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006116 {
Geoff Lang536eca12017-09-13 11:23:35 -04006117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006118 return false;
6119 }
6120
Geoff Lang536eca12017-09-13 11:23:35 -04006121 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6122 // generation
6123 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6124 {
6125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6126 return false;
6127 }
6128
6129 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6130 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006131 bool supportsSRGBMipmapGeneration =
6132 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006133 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006134 {
Geoff Lang536eca12017-09-13 11:23:35 -04006135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006136 return false;
6137 }
6138
6139 // Non-power of 2 ES2 check
6140 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6141 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6142 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6143 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006144 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6145 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006147 return false;
6148 }
6149
6150 // Cube completeness check
6151 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006154 return false;
6155 }
6156
6157 return true;
6158}
6159
6160bool ValidateGetBufferParameteriv(ValidationContext *context,
6161 GLenum target,
6162 GLenum pname,
6163 GLint *params)
6164{
6165 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6166}
6167
6168bool ValidateGetRenderbufferParameteriv(Context *context,
6169 GLenum target,
6170 GLenum pname,
6171 GLint *params)
6172{
6173 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6174}
6175
6176bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6177{
6178 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6179}
6180
6181bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6182{
6183 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6184}
6185
6186bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6187{
6188 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6189}
6190
6191bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6192{
6193 return ValidateGetUniformBase(context, program, location);
6194}
6195
6196bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6197{
6198 return ValidateGetUniformBase(context, program, location);
6199}
6200
6201bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6202{
6203 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6204}
6205
6206bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6207{
6208 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6209}
6210
6211bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6212{
6213 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6214}
6215
6216bool ValidateIsEnabled(Context *context, GLenum cap)
6217{
6218 if (!ValidCap(context, cap, true))
6219 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006221 return false;
6222 }
6223
6224 return true;
6225}
6226
6227bool ValidateLinkProgram(Context *context, GLuint program)
6228{
6229 if (context->hasActiveTransformFeedback(program))
6230 {
6231 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006232 context->handleError(InvalidOperation() << "Cannot link program while program is "
6233 "associated with an active transform "
6234 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006235 return false;
6236 }
6237
6238 Program *programObject = GetValidProgram(context, program);
6239 if (!programObject)
6240 {
6241 return false;
6242 }
6243
6244 return true;
6245}
6246
Jamie Madill4928b7c2017-06-20 12:57:39 -04006247bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006248 GLint x,
6249 GLint y,
6250 GLsizei width,
6251 GLsizei height,
6252 GLenum format,
6253 GLenum type,
6254 void *pixels)
6255{
6256 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6257 nullptr, pixels);
6258}
6259
6260bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6261{
6262 return ValidateTexParameterBase(context, target, pname, -1, &param);
6263}
6264
6265bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6266{
6267 return ValidateTexParameterBase(context, target, pname, -1, params);
6268}
6269
6270bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6271{
6272 return ValidateTexParameterBase(context, target, pname, -1, &param);
6273}
6274
6275bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6276{
6277 return ValidateTexParameterBase(context, target, pname, -1, params);
6278}
6279
6280bool ValidateUseProgram(Context *context, GLuint program)
6281{
6282 if (program != 0)
6283 {
6284 Program *programObject = context->getProgram(program);
6285 if (!programObject)
6286 {
6287 // ES 3.1.0 section 7.3 page 72
6288 if (context->getShader(program))
6289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006291 return false;
6292 }
6293 else
6294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006295 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006296 return false;
6297 }
6298 }
6299 if (!programObject->isLinked())
6300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006302 return false;
6303 }
6304 }
6305 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6306 {
6307 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006308 context
6309 ->handleError(InvalidOperation()
6310 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006311 return false;
6312 }
6313
6314 return true;
6315}
6316
Jamie Madillc29968b2016-01-20 11:17:23 -05006317} // namespace gl