blob: a07227f7d856c31ccd20953658c4e6ee67c9b9b2 [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:
Geoff Lang86f81162017-10-30 15:10:45 -04001176 if (!context->getExtensions().textureCompressionDXT3)
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 {
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 }
Geoff Lang86f81162017-10-30 15:10:45 -04001205 if (isSubImage)
1206 {
1207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
1208 return false;
1209 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 break;
1211 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001212 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1213 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1214 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1215 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001216 if (!context->getExtensions().lossyETCDecode)
1217 {
Geoff Lang86f81162017-10-30 15:10:45 -04001218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001219 return false;
1220 }
1221 break;
1222 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001224 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001225 }
Geoff Lang966c9402017-04-18 12:38:27 -04001226
1227 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001228 {
Geoff Lang966c9402017-04-18 12:38:27 -04001229 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1230 height, texture->getWidth(target, level),
1231 texture->getHeight(target, level)))
1232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001234 return false;
1235 }
1236
1237 if (format != actualInternalFormat)
1238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001240 return false;
1241 }
1242 }
1243 else
1244 {
1245 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001248 return false;
1249 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250 }
1251 }
1252 else
1253 {
1254 // validate <type> by itself (used as secondary key below)
1255 switch (type)
1256 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001257 case GL_UNSIGNED_BYTE:
1258 case GL_UNSIGNED_SHORT_5_6_5:
1259 case GL_UNSIGNED_SHORT_4_4_4_4:
1260 case GL_UNSIGNED_SHORT_5_5_5_1:
1261 case GL_UNSIGNED_SHORT:
1262 case GL_UNSIGNED_INT:
1263 case GL_UNSIGNED_INT_24_8_OES:
1264 case GL_HALF_FLOAT_OES:
1265 case GL_FLOAT:
1266 break;
1267 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001268 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
1272 // validate <format> + <type> combinations
1273 // - invalid <format> -> sets INVALID_ENUM
1274 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1275 switch (format)
1276 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001277 case GL_ALPHA:
1278 case GL_LUMINANCE:
1279 case GL_LUMINANCE_ALPHA:
1280 switch (type)
1281 {
1282 case GL_UNSIGNED_BYTE:
1283 case GL_FLOAT:
1284 case GL_HALF_FLOAT_OES:
1285 break;
1286 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001288 return false;
1289 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001290 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001291 case GL_RED:
1292 case GL_RG:
1293 if (!context->getExtensions().textureRG)
1294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001295 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001296 return false;
1297 }
1298 switch (type)
1299 {
1300 case GL_UNSIGNED_BYTE:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001301 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001302 case GL_FLOAT:
1303 case GL_HALF_FLOAT_OES:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001304 if (!context->getExtensions().textureFloat)
1305 {
1306 context->handleError(InvalidEnum());
1307 return false;
1308 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001309 break;
1310 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001312 return false;
1313 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001315 case GL_RGB:
1316 switch (type)
1317 {
1318 case GL_UNSIGNED_BYTE:
1319 case GL_UNSIGNED_SHORT_5_6_5:
1320 case GL_FLOAT:
1321 case GL_HALF_FLOAT_OES:
1322 break;
1323 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 return false;
1326 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001328 case GL_RGBA:
1329 switch (type)
1330 {
1331 case GL_UNSIGNED_BYTE:
1332 case GL_UNSIGNED_SHORT_4_4_4_4:
1333 case GL_UNSIGNED_SHORT_5_5_5_1:
1334 case GL_FLOAT:
1335 case GL_HALF_FLOAT_OES:
1336 break;
1337 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001339 return false;
1340 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 case GL_BGRA_EXT:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001343 if (!context->getExtensions().textureFormatBGRA8888)
1344 {
1345 context->handleError(InvalidEnum());
1346 return false;
1347 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001348 switch (type)
1349 {
1350 case GL_UNSIGNED_BYTE:
1351 break;
1352 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001353 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001354 return false;
1355 }
1356 break;
1357 case GL_SRGB_EXT:
1358 case GL_SRGB_ALPHA_EXT:
1359 if (!context->getExtensions().sRGB)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001362 return false;
1363 }
1364 switch (type)
1365 {
1366 case GL_UNSIGNED_BYTE:
1367 break;
1368 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001370 return false;
1371 }
1372 break;
1373 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1374 // handled below
1375 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1376 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1377 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1378 break;
1379 case GL_DEPTH_COMPONENT:
1380 switch (type)
1381 {
1382 case GL_UNSIGNED_SHORT:
1383 case GL_UNSIGNED_INT:
1384 break;
1385 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001387 return false;
1388 }
1389 break;
1390 case GL_DEPTH_STENCIL_OES:
1391 switch (type)
1392 {
1393 case GL_UNSIGNED_INT_24_8_OES:
1394 break;
1395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001396 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001397 return false;
1398 }
1399 break;
1400 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001401 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 }
1404
1405 switch (format)
1406 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001407 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1408 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1409 if (context->getExtensions().textureCompressionDXT1)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 return false;
1413 }
1414 else
1415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 return false;
1418 }
1419 break;
1420 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1421 if (context->getExtensions().textureCompressionDXT3)
1422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001424 return false;
1425 }
1426 else
1427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 return false;
1430 }
1431 break;
1432 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1433 if (context->getExtensions().textureCompressionDXT5)
1434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001435 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001436 return false;
1437 }
1438 else
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001441 return false;
1442 }
1443 break;
1444 case GL_ETC1_RGB8_OES:
1445 if (context->getExtensions().compressedETC1RGB8Texture)
1446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001447 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 return false;
1449 }
1450 else
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001453 return false;
1454 }
1455 break;
1456 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001457 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1458 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1459 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1460 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 if (context->getExtensions().lossyETCDecode)
1462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidOperation()
1464 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001465 return false;
1466 }
1467 else
1468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001469 context->handleError(InvalidEnum()
1470 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001471 return false;
1472 }
1473 break;
1474 case GL_DEPTH_COMPONENT:
1475 case GL_DEPTH_STENCIL_OES:
1476 if (!context->getExtensions().depthTextures)
1477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001478 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001479 return false;
1480 }
1481 if (target != GL_TEXTURE_2D)
1482 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001483 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001484 return false;
1485 }
1486 // OES_depth_texture supports loading depth data and multiple levels,
1487 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001488 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001489 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1491 return false;
1492 }
1493 if (level != 0)
1494 {
1495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001496 return false;
1497 }
1498 break;
1499 default:
1500 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001501 }
1502
Geoff Lang6e898aa2017-06-02 11:17:26 -04001503 if (!isSubImage)
1504 {
1505 switch (internalformat)
1506 {
1507 case GL_RGBA32F:
1508 if (!context->getExtensions().colorBufferFloatRGBA)
1509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidValue()
1511 << "Sized GL_RGBA32F internal format requires "
1512 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001513 return false;
1514 }
1515 if (type != GL_FLOAT)
1516 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001518 return false;
1519 }
1520 if (format != GL_RGBA)
1521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001523 return false;
1524 }
1525 break;
1526
1527 case GL_RGB32F:
1528 if (!context->getExtensions().colorBufferFloatRGB)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidValue()
1531 << "Sized GL_RGB32F internal format requires "
1532 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001533 return false;
1534 }
1535 if (type != GL_FLOAT)
1536 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001538 return false;
1539 }
1540 if (format != GL_RGB)
1541 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001542 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001543 return false;
1544 }
1545 break;
1546
1547 default:
1548 break;
1549 }
1550 }
1551
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001552 if (type == GL_FLOAT)
1553 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001554 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001556 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001557 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001558 }
1559 }
1560 else if (type == GL_HALF_FLOAT_OES)
1561 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001562 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001564 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001565 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001566 }
1567 }
1568 }
1569
Geoff Langdbcced82017-06-06 15:55:54 -04001570 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1571 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001572 imageSize))
1573 {
1574 return false;
1575 }
1576
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001577 return true;
1578}
1579
He Yunchaoced53ae2016-11-29 15:00:51 +08001580bool ValidateES2TexStorageParameters(Context *context,
1581 GLenum target,
1582 GLsizei levels,
1583 GLenum internalformat,
1584 GLsizei width,
1585 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001587 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1588 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001590 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001591 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001592 }
1593
1594 if (width < 1 || height < 1 || levels < 1)
1595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001596 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001597 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001598 }
1599
1600 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001602 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001603 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001604 }
1605
1606 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001609 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001610 }
1611
Geoff Langca271392017-04-05 12:30:00 -04001612 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001613 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001616 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001617 }
1618
Geoff Langaae65a42014-05-26 12:43:44 -04001619 const gl::Caps &caps = context->getCaps();
1620
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 switch (target)
1622 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001623 case GL_TEXTURE_2D:
1624 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1625 static_cast<GLuint>(height) > caps.max2DTextureSize)
1626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001627 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001628 return false;
1629 }
1630 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001631 case GL_TEXTURE_RECTANGLE_ANGLE:
1632 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1633 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1634 {
1635 context->handleError(InvalidValue());
1636 return false;
1637 }
1638 if (formatInfo.compressed)
1639 {
1640 context->handleError(InvalidEnum()
1641 << "Rectangle texture cannot have a compressed format.");
1642 return false;
1643 }
1644 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001645 case GL_TEXTURE_CUBE_MAP:
1646 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1647 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001649 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001650 return false;
1651 }
1652 break;
1653 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001654 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001656 }
1657
Geoff Langc0b9ef42014-07-02 10:02:37 -04001658 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 {
1660 if (!gl::isPow2(width) || !gl::isPow2(height))
1661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001662 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001663 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001664 }
1665 }
1666
1667 switch (internalformat)
1668 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001669 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1670 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1671 if (!context->getExtensions().textureCompressionDXT1)
1672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001673 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001674 return false;
1675 }
1676 break;
1677 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1678 if (!context->getExtensions().textureCompressionDXT3)
1679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001680 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001681 return false;
1682 }
1683 break;
1684 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1685 if (!context->getExtensions().textureCompressionDXT5)
1686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001687 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001688 return false;
1689 }
1690 break;
1691 case GL_ETC1_RGB8_OES:
1692 if (!context->getExtensions().compressedETC1RGB8Texture)
1693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001694 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001695 return false;
1696 }
1697 break;
1698 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001699 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1700 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1701 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1702 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001703 if (!context->getExtensions().lossyETCDecode)
1704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidEnum()
1706 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001707 return false;
1708 }
1709 break;
1710 case GL_RGBA32F_EXT:
1711 case GL_RGB32F_EXT:
1712 case GL_ALPHA32F_EXT:
1713 case GL_LUMINANCE32F_EXT:
1714 case GL_LUMINANCE_ALPHA32F_EXT:
1715 if (!context->getExtensions().textureFloat)
1716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001718 return false;
1719 }
1720 break;
1721 case GL_RGBA16F_EXT:
1722 case GL_RGB16F_EXT:
1723 case GL_ALPHA16F_EXT:
1724 case GL_LUMINANCE16F_EXT:
1725 case GL_LUMINANCE_ALPHA16F_EXT:
1726 if (!context->getExtensions().textureHalfFloat)
1727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001729 return false;
1730 }
1731 break;
1732 case GL_R8_EXT:
1733 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001734 if (!context->getExtensions().textureRG)
1735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001737 return false;
1738 }
1739 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001740 case GL_R16F_EXT:
1741 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001742 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001745 return false;
1746 }
1747 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001748 case GL_R32F_EXT:
1749 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001750 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001752 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001753 return false;
1754 }
1755 break;
1756 case GL_DEPTH_COMPONENT16:
1757 case GL_DEPTH_COMPONENT32_OES:
1758 case GL_DEPTH24_STENCIL8_OES:
1759 if (!context->getExtensions().depthTextures)
1760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001762 return false;
1763 }
1764 if (target != GL_TEXTURE_2D)
1765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001767 return false;
1768 }
1769 // ANGLE_depth_texture only supports 1-level textures
1770 if (levels != 1)
1771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001772 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001773 return false;
1774 }
1775 break;
1776 default:
1777 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001778 }
1779
Geoff Lang691e58c2014-12-19 17:03:25 -05001780 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001781 if (!texture || texture->id() == 0)
1782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001783 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001785 }
1786
Geoff Lang69cce582015-09-17 13:20:36 -04001787 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001791 }
1792
1793 return true;
1794}
1795
He Yunchaoced53ae2016-11-29 15:00:51 +08001796bool ValidateDiscardFramebufferEXT(Context *context,
1797 GLenum target,
1798 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001799 const GLenum *attachments)
1800{
Jamie Madillc29968b2016-01-20 11:17:23 -05001801 if (!context->getExtensions().discardFramebuffer)
1802 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 return false;
1805 }
1806
Austin Kinross08332632015-05-05 13:35:47 -07001807 bool defaultFramebuffer = false;
1808
1809 switch (target)
1810 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001811 case GL_FRAMEBUFFER:
1812 defaultFramebuffer =
1813 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1814 break;
1815 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001816 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001817 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001818 }
1819
He Yunchaoced53ae2016-11-29 15:00:51 +08001820 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1821 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001822}
1823
Austin Kinrossbc781f32015-10-26 09:27:38 -07001824bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1825{
1826 if (!context->getExtensions().vertexArrayObject)
1827 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001828 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001829 return false;
1830 }
1831
1832 return ValidateBindVertexArrayBase(context, array);
1833}
1834
Jamie Madilld7576732017-08-26 18:49:50 -04001835bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001836{
1837 if (!context->getExtensions().vertexArrayObject)
1838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001840 return false;
1841 }
1842
Olli Etuaho41997e72016-03-10 13:38:39 +02001843 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001844}
1845
Jamie Madilld7576732017-08-26 18:49:50 -04001846bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001847{
1848 if (!context->getExtensions().vertexArrayObject)
1849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001851 return false;
1852 }
1853
Olli Etuaho41997e72016-03-10 13:38:39 +02001854 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001855}
1856
Jamie Madilld7576732017-08-26 18:49:50 -04001857bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001858{
1859 if (!context->getExtensions().vertexArrayObject)
1860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001862 return false;
1863 }
1864
1865 return true;
1866}
Geoff Langc5629752015-12-07 16:29:04 -05001867
1868bool ValidateProgramBinaryOES(Context *context,
1869 GLuint program,
1870 GLenum binaryFormat,
1871 const void *binary,
1872 GLint length)
1873{
1874 if (!context->getExtensions().getProgramBinary)
1875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001876 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001877 return false;
1878 }
1879
1880 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1881}
1882
1883bool ValidateGetProgramBinaryOES(Context *context,
1884 GLuint program,
1885 GLsizei bufSize,
1886 GLsizei *length,
1887 GLenum *binaryFormat,
1888 void *binary)
1889{
1890 if (!context->getExtensions().getProgramBinary)
1891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001893 return false;
1894 }
1895
1896 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1897}
Geoff Lange102fee2015-12-10 11:23:30 -05001898
Geoff Lang70d0f492015-12-10 17:45:46 -05001899static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1900{
1901 switch (source)
1902 {
1903 case GL_DEBUG_SOURCE_API:
1904 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1905 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1906 case GL_DEBUG_SOURCE_OTHER:
1907 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1908 return !mustBeThirdPartyOrApplication;
1909
1910 case GL_DEBUG_SOURCE_THIRD_PARTY:
1911 case GL_DEBUG_SOURCE_APPLICATION:
1912 return true;
1913
1914 default:
1915 return false;
1916 }
1917}
1918
1919static bool ValidDebugType(GLenum type)
1920{
1921 switch (type)
1922 {
1923 case GL_DEBUG_TYPE_ERROR:
1924 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1925 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1926 case GL_DEBUG_TYPE_PERFORMANCE:
1927 case GL_DEBUG_TYPE_PORTABILITY:
1928 case GL_DEBUG_TYPE_OTHER:
1929 case GL_DEBUG_TYPE_MARKER:
1930 case GL_DEBUG_TYPE_PUSH_GROUP:
1931 case GL_DEBUG_TYPE_POP_GROUP:
1932 return true;
1933
1934 default:
1935 return false;
1936 }
1937}
1938
1939static bool ValidDebugSeverity(GLenum severity)
1940{
1941 switch (severity)
1942 {
1943 case GL_DEBUG_SEVERITY_HIGH:
1944 case GL_DEBUG_SEVERITY_MEDIUM:
1945 case GL_DEBUG_SEVERITY_LOW:
1946 case GL_DEBUG_SEVERITY_NOTIFICATION:
1947 return true;
1948
1949 default:
1950 return false;
1951 }
1952}
1953
Geoff Lange102fee2015-12-10 11:23:30 -05001954bool ValidateDebugMessageControlKHR(Context *context,
1955 GLenum source,
1956 GLenum type,
1957 GLenum severity,
1958 GLsizei count,
1959 const GLuint *ids,
1960 GLboolean enabled)
1961{
1962 if (!context->getExtensions().debug)
1963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001965 return false;
1966 }
1967
Geoff Lang70d0f492015-12-10 17:45:46 -05001968 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1969 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001970 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001971 return false;
1972 }
1973
1974 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1975 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001977 return false;
1978 }
1979
1980 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1981 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001982 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001983 return false;
1984 }
1985
1986 if (count > 0)
1987 {
1988 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001990 context->handleError(
1991 InvalidOperation()
1992 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001993 return false;
1994 }
1995
1996 if (severity != GL_DONT_CARE)
1997 {
Jamie Madill437fa652016-05-03 15:13:24 -04001998 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001999 InvalidOperation()
2000 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002001 return false;
2002 }
2003 }
2004
Geoff Lange102fee2015-12-10 11:23:30 -05002005 return true;
2006}
2007
2008bool ValidateDebugMessageInsertKHR(Context *context,
2009 GLenum source,
2010 GLenum type,
2011 GLuint id,
2012 GLenum severity,
2013 GLsizei length,
2014 const GLchar *buf)
2015{
2016 if (!context->getExtensions().debug)
2017 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002019 return false;
2020 }
2021
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002022 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05002023 {
2024 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2025 // not generate an error.
2026 return false;
2027 }
2028
2029 if (!ValidDebugSeverity(severity))
2030 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002031 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002032 return false;
2033 }
2034
2035 if (!ValidDebugType(type))
2036 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002037 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05002038 return false;
2039 }
2040
2041 if (!ValidDebugSource(source, true))
2042 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002044 return false;
2045 }
2046
2047 size_t messageLength = (length < 0) ? strlen(buf) : length;
2048 if (messageLength > context->getExtensions().maxDebugMessageLength)
2049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002050 context->handleError(InvalidValue()
2051 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002052 return false;
2053 }
2054
Geoff Lange102fee2015-12-10 11:23:30 -05002055 return true;
2056}
2057
2058bool ValidateDebugMessageCallbackKHR(Context *context,
2059 GLDEBUGPROCKHR callback,
2060 const void *userParam)
2061{
2062 if (!context->getExtensions().debug)
2063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002065 return false;
2066 }
2067
Geoff Lange102fee2015-12-10 11:23:30 -05002068 return true;
2069}
2070
2071bool ValidateGetDebugMessageLogKHR(Context *context,
2072 GLuint count,
2073 GLsizei bufSize,
2074 GLenum *sources,
2075 GLenum *types,
2076 GLuint *ids,
2077 GLenum *severities,
2078 GLsizei *lengths,
2079 GLchar *messageLog)
2080{
2081 if (!context->getExtensions().debug)
2082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002084 return false;
2085 }
2086
Geoff Lang70d0f492015-12-10 17:45:46 -05002087 if (bufSize < 0 && messageLog != nullptr)
2088 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002089 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002090 return false;
2091 }
2092
Geoff Lange102fee2015-12-10 11:23:30 -05002093 return true;
2094}
2095
2096bool ValidatePushDebugGroupKHR(Context *context,
2097 GLenum source,
2098 GLuint id,
2099 GLsizei length,
2100 const GLchar *message)
2101{
2102 if (!context->getExtensions().debug)
2103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002105 return false;
2106 }
2107
Geoff Lang70d0f492015-12-10 17:45:46 -05002108 if (!ValidDebugSource(source, true))
2109 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002111 return false;
2112 }
2113
2114 size_t messageLength = (length < 0) ? strlen(message) : length;
2115 if (messageLength > context->getExtensions().maxDebugMessageLength)
2116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002117 context->handleError(InvalidValue()
2118 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002119 return false;
2120 }
2121
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002122 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002123 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002125 context
2126 ->handleError(StackOverflow()
2127 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002128 return false;
2129 }
2130
Geoff Lange102fee2015-12-10 11:23:30 -05002131 return true;
2132}
2133
2134bool ValidatePopDebugGroupKHR(Context *context)
2135{
2136 if (!context->getExtensions().debug)
2137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002138 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002139 return false;
2140 }
2141
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002142 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002143 if (currentStackSize <= 1)
2144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002145 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002146 return false;
2147 }
2148
2149 return true;
2150}
2151
2152static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2153{
2154 switch (identifier)
2155 {
2156 case GL_BUFFER:
2157 if (context->getBuffer(name) == nullptr)
2158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002159 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002160 return false;
2161 }
2162 return true;
2163
2164 case GL_SHADER:
2165 if (context->getShader(name) == nullptr)
2166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002167 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002168 return false;
2169 }
2170 return true;
2171
2172 case GL_PROGRAM:
2173 if (context->getProgram(name) == nullptr)
2174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002175 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002176 return false;
2177 }
2178 return true;
2179
2180 case GL_VERTEX_ARRAY:
2181 if (context->getVertexArray(name) == nullptr)
2182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002183 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002184 return false;
2185 }
2186 return true;
2187
2188 case GL_QUERY:
2189 if (context->getQuery(name) == nullptr)
2190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002191 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002192 return false;
2193 }
2194 return true;
2195
2196 case GL_TRANSFORM_FEEDBACK:
2197 if (context->getTransformFeedback(name) == nullptr)
2198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002199 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002200 return false;
2201 }
2202 return true;
2203
2204 case GL_SAMPLER:
2205 if (context->getSampler(name) == nullptr)
2206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002208 return false;
2209 }
2210 return true;
2211
2212 case GL_TEXTURE:
2213 if (context->getTexture(name) == nullptr)
2214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002215 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002216 return false;
2217 }
2218 return true;
2219
2220 case GL_RENDERBUFFER:
2221 if (context->getRenderbuffer(name) == nullptr)
2222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002223 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002224 return false;
2225 }
2226 return true;
2227
2228 case GL_FRAMEBUFFER:
2229 if (context->getFramebuffer(name) == nullptr)
2230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002231 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002232 return false;
2233 }
2234 return true;
2235
2236 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002237 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002238 return false;
2239 }
Geoff Lange102fee2015-12-10 11:23:30 -05002240}
2241
Martin Radev9d901792016-07-15 15:58:58 +03002242static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2243{
2244 size_t labelLength = 0;
2245
2246 if (length < 0)
2247 {
2248 if (label != nullptr)
2249 {
2250 labelLength = strlen(label);
2251 }
2252 }
2253 else
2254 {
2255 labelLength = static_cast<size_t>(length);
2256 }
2257
2258 if (labelLength > context->getExtensions().maxLabelLength)
2259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002260 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002261 return false;
2262 }
2263
2264 return true;
2265}
2266
Geoff Lange102fee2015-12-10 11:23:30 -05002267bool ValidateObjectLabelKHR(Context *context,
2268 GLenum identifier,
2269 GLuint name,
2270 GLsizei length,
2271 const GLchar *label)
2272{
2273 if (!context->getExtensions().debug)
2274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002276 return false;
2277 }
2278
Geoff Lang70d0f492015-12-10 17:45:46 -05002279 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2280 {
2281 return false;
2282 }
2283
Martin Radev9d901792016-07-15 15:58:58 +03002284 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002285 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002286 return false;
2287 }
2288
Geoff Lange102fee2015-12-10 11:23:30 -05002289 return true;
2290}
2291
2292bool ValidateGetObjectLabelKHR(Context *context,
2293 GLenum identifier,
2294 GLuint name,
2295 GLsizei bufSize,
2296 GLsizei *length,
2297 GLchar *label)
2298{
2299 if (!context->getExtensions().debug)
2300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002302 return false;
2303 }
2304
Geoff Lang70d0f492015-12-10 17:45:46 -05002305 if (bufSize < 0)
2306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002307 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002308 return false;
2309 }
2310
2311 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2312 {
2313 return false;
2314 }
2315
Martin Radev9d901792016-07-15 15:58:58 +03002316 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002317}
2318
2319static bool ValidateObjectPtrName(Context *context, const void *ptr)
2320{
Jamie Madill70b5bb02017-08-28 13:32:37 -04002321 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
Geoff Lang70d0f492015-12-10 17:45:46 -05002322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002324 return false;
2325 }
2326
Geoff Lange102fee2015-12-10 11:23:30 -05002327 return true;
2328}
2329
2330bool ValidateObjectPtrLabelKHR(Context *context,
2331 const void *ptr,
2332 GLsizei length,
2333 const GLchar *label)
2334{
2335 if (!context->getExtensions().debug)
2336 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002337 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002338 return false;
2339 }
2340
Geoff Lang70d0f492015-12-10 17:45:46 -05002341 if (!ValidateObjectPtrName(context, ptr))
2342 {
2343 return false;
2344 }
2345
Martin Radev9d901792016-07-15 15:58:58 +03002346 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002347 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002348 return false;
2349 }
2350
Geoff Lange102fee2015-12-10 11:23:30 -05002351 return true;
2352}
2353
2354bool ValidateGetObjectPtrLabelKHR(Context *context,
2355 const void *ptr,
2356 GLsizei bufSize,
2357 GLsizei *length,
2358 GLchar *label)
2359{
2360 if (!context->getExtensions().debug)
2361 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002362 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002363 return false;
2364 }
2365
Geoff Lang70d0f492015-12-10 17:45:46 -05002366 if (bufSize < 0)
2367 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002368 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002369 return false;
2370 }
2371
2372 if (!ValidateObjectPtrName(context, ptr))
2373 {
2374 return false;
2375 }
2376
Martin Radev9d901792016-07-15 15:58:58 +03002377 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002378}
2379
2380bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2381{
2382 if (!context->getExtensions().debug)
2383 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002384 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002385 return false;
2386 }
2387
Geoff Lang70d0f492015-12-10 17:45:46 -05002388 // TODO: represent this in Context::getQueryParameterInfo.
2389 switch (pname)
2390 {
2391 case GL_DEBUG_CALLBACK_FUNCTION:
2392 case GL_DEBUG_CALLBACK_USER_PARAM:
2393 break;
2394
2395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002397 return false;
2398 }
2399
Geoff Lange102fee2015-12-10 11:23:30 -05002400 return true;
2401}
Jamie Madillc29968b2016-01-20 11:17:23 -05002402
2403bool ValidateBlitFramebufferANGLE(Context *context,
2404 GLint srcX0,
2405 GLint srcY0,
2406 GLint srcX1,
2407 GLint srcY1,
2408 GLint dstX0,
2409 GLint dstY0,
2410 GLint dstX1,
2411 GLint dstY1,
2412 GLbitfield mask,
2413 GLenum filter)
2414{
2415 if (!context->getExtensions().framebufferBlit)
2416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002417 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002418 return false;
2419 }
2420
2421 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2422 {
2423 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002424 context->handleError(InvalidOperation() << "Scaling and flipping in "
2425 "BlitFramebufferANGLE not supported by this "
2426 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002427 return false;
2428 }
2429
2430 if (filter == GL_LINEAR)
2431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002432 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002433 return false;
2434 }
2435
Jamie Madill51f40ec2016-06-15 14:06:00 -04002436 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2437 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002438
2439 if (mask & GL_COLOR_BUFFER_BIT)
2440 {
2441 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2442 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2443
2444 if (readColorAttachment && drawColorAttachment)
2445 {
2446 if (!(readColorAttachment->type() == GL_TEXTURE &&
2447 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2448 readColorAttachment->type() != GL_RENDERBUFFER &&
2449 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002451 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002452 return false;
2453 }
2454
Geoff Langa15472a2015-08-11 11:48:03 -04002455 for (size_t drawbufferIdx = 0;
2456 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002457 {
Geoff Langa15472a2015-08-11 11:48:03 -04002458 const FramebufferAttachment *attachment =
2459 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2460 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002461 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002462 if (!(attachment->type() == GL_TEXTURE &&
2463 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2464 attachment->type() != GL_RENDERBUFFER &&
2465 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002467 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002468 return false;
2469 }
2470
2471 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002472 if (!Format::EquivalentForBlit(attachment->getFormat(),
2473 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002475 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002476 return false;
2477 }
2478 }
2479 }
2480
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002481 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002482 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2483 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002485 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002486 return false;
2487 }
2488 }
2489 }
2490
2491 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2492 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2493 for (size_t i = 0; i < 2; i++)
2494 {
2495 if (mask & masks[i])
2496 {
2497 const FramebufferAttachment *readBuffer =
2498 readFramebuffer->getAttachment(attachments[i]);
2499 const FramebufferAttachment *drawBuffer =
2500 drawFramebuffer->getAttachment(attachments[i]);
2501
2502 if (readBuffer && drawBuffer)
2503 {
2504 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2505 dstX0, dstY0, dstX1, dstY1))
2506 {
2507 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2509 "stencil blits are supported by "
2510 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002511 return false;
2512 }
2513
2514 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002516 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002517 return false;
2518 }
2519 }
2520 }
2521 }
2522
2523 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2524 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002525}
Jamie Madillc29968b2016-01-20 11:17:23 -05002526
2527bool ValidateClear(ValidationContext *context, GLbitfield mask)
2528{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002529 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002530 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002532 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002533 return false;
2534 }
2535
2536 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2537 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002538 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002539 return false;
2540 }
2541
Geoff Lang76e65652017-03-27 14:58:02 -04002542 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2543 {
2544 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2545 GL_SIGNED_NORMALIZED};
2546
Corentin Wallez59c41592017-07-11 13:19:54 -04002547 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002548 drawBufferIdx++)
2549 {
2550 if (!ValidateWebGLFramebufferAttachmentClearType(
2551 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2552 {
2553 return false;
2554 }
2555 }
2556 }
2557
Jamie Madillc29968b2016-01-20 11:17:23 -05002558 return true;
2559}
2560
2561bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2562{
2563 if (!context->getExtensions().drawBuffers)
2564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002566 return false;
2567 }
2568
2569 return ValidateDrawBuffersBase(context, n, bufs);
2570}
2571
Jamie Madill73a84962016-02-12 09:27:23 -05002572bool ValidateTexImage2D(Context *context,
2573 GLenum target,
2574 GLint level,
2575 GLint internalformat,
2576 GLsizei width,
2577 GLsizei height,
2578 GLint border,
2579 GLenum format,
2580 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002581 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002582{
Martin Radev1be913c2016-07-11 17:59:16 +03002583 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002584 {
2585 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002586 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002587 }
2588
Martin Radev1be913c2016-07-11 17:59:16 +03002589 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002590 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002591 0, 0, width, height, 1, border, format, type, -1,
2592 pixels);
2593}
2594
2595bool ValidateTexImage2DRobust(Context *context,
2596 GLenum target,
2597 GLint level,
2598 GLint internalformat,
2599 GLsizei width,
2600 GLsizei height,
2601 GLint border,
2602 GLenum format,
2603 GLenum type,
2604 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002605 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002606{
2607 if (!ValidateRobustEntryPoint(context, bufSize))
2608 {
2609 return false;
2610 }
2611
2612 if (context->getClientMajorVersion() < 3)
2613 {
2614 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2615 0, 0, width, height, border, format, type, bufSize,
2616 pixels);
2617 }
2618
2619 ASSERT(context->getClientMajorVersion() >= 3);
2620 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2621 0, 0, width, height, 1, border, format, type, bufSize,
2622 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002623}
2624
2625bool ValidateTexSubImage2D(Context *context,
2626 GLenum target,
2627 GLint level,
2628 GLint xoffset,
2629 GLint yoffset,
2630 GLsizei width,
2631 GLsizei height,
2632 GLenum format,
2633 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002634 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002635{
2636
Martin Radev1be913c2016-07-11 17:59:16 +03002637 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002638 {
2639 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002640 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002641 }
2642
Martin Radev1be913c2016-07-11 17:59:16 +03002643 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002644 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002645 yoffset, 0, width, height, 1, 0, format, type, -1,
2646 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002647}
2648
Geoff Langc52f6f12016-10-14 10:18:00 -04002649bool ValidateTexSubImage2DRobustANGLE(Context *context,
2650 GLenum target,
2651 GLint level,
2652 GLint xoffset,
2653 GLint yoffset,
2654 GLsizei width,
2655 GLsizei height,
2656 GLenum format,
2657 GLenum type,
2658 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002659 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002660{
2661 if (!ValidateRobustEntryPoint(context, bufSize))
2662 {
2663 return false;
2664 }
2665
2666 if (context->getClientMajorVersion() < 3)
2667 {
2668 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2669 yoffset, width, height, 0, format, type, bufSize,
2670 pixels);
2671 }
2672
2673 ASSERT(context->getClientMajorVersion() >= 3);
2674 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2675 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2676 pixels);
2677}
2678
Jamie Madill73a84962016-02-12 09:27:23 -05002679bool ValidateCompressedTexImage2D(Context *context,
2680 GLenum target,
2681 GLint level,
2682 GLenum internalformat,
2683 GLsizei width,
2684 GLsizei height,
2685 GLint border,
2686 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002687 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002688{
Martin Radev1be913c2016-07-11 17:59:16 +03002689 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002690 {
2691 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002692 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002693 {
2694 return false;
2695 }
2696 }
2697 else
2698 {
Martin Radev1be913c2016-07-11 17:59:16 +03002699 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002700 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002701 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002702 data))
2703 {
2704 return false;
2705 }
2706 }
2707
Geoff Langca271392017-04-05 12:30:00 -04002708 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002709 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002710 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002711 if (blockSizeOrErr.isError())
2712 {
2713 context->handleError(blockSizeOrErr.getError());
2714 return false;
2715 }
2716
2717 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002718 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002719 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002720 return false;
2721 }
2722
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002723 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2724 {
2725 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2726 return false;
2727 }
2728
Jamie Madill73a84962016-02-12 09:27:23 -05002729 return true;
2730}
2731
Corentin Wallezb2931602017-04-11 15:58:57 -04002732bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2733 GLenum target,
2734 GLint level,
2735 GLenum internalformat,
2736 GLsizei width,
2737 GLsizei height,
2738 GLint border,
2739 GLsizei imageSize,
2740 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002741 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002742{
2743 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2744 {
2745 return false;
2746 }
2747
2748 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2749 border, imageSize, data);
2750}
2751bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2752 GLenum target,
2753 GLint level,
2754 GLint xoffset,
2755 GLint yoffset,
2756 GLsizei width,
2757 GLsizei height,
2758 GLenum format,
2759 GLsizei imageSize,
2760 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002761 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002762{
2763 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2764 {
2765 return false;
2766 }
2767
2768 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2769 format, imageSize, data);
2770}
2771
Jamie Madill73a84962016-02-12 09:27:23 -05002772bool ValidateCompressedTexSubImage2D(Context *context,
2773 GLenum target,
2774 GLint level,
2775 GLint xoffset,
2776 GLint yoffset,
2777 GLsizei width,
2778 GLsizei height,
2779 GLenum format,
2780 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002781 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002782{
Martin Radev1be913c2016-07-11 17:59:16 +03002783 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002784 {
2785 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002786 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002787 {
2788 return false;
2789 }
2790 }
2791 else
2792 {
Martin Radev1be913c2016-07-11 17:59:16 +03002793 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002794 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002795 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002796 data))
2797 {
2798 return false;
2799 }
2800 }
2801
Geoff Langca271392017-04-05 12:30:00 -04002802 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002803 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002804 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002805 if (blockSizeOrErr.isError())
2806 {
2807 context->handleError(blockSizeOrErr.getError());
2808 return false;
2809 }
2810
2811 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002813 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002814 return false;
2815 }
2816
2817 return true;
2818}
2819
Olli Etuaho4f667482016-03-30 15:56:35 +03002820bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2821{
Geoff Lang496c02d2016-10-20 11:38:11 -07002822 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002823}
2824
2825bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2826{
2827 if (!context->getExtensions().mapBuffer)
2828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002829 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002830 return false;
2831 }
2832
2833 if (!ValidBufferTarget(context, target))
2834 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002835 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002836 return false;
2837 }
2838
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002839 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002840
2841 if (buffer == nullptr)
2842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002843 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002844 return false;
2845 }
2846
2847 if (access != GL_WRITE_ONLY_OES)
2848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002849 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002850 return false;
2851 }
2852
2853 if (buffer->isMapped())
2854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002855 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002856 return false;
2857 }
2858
Geoff Lang79f71042017-08-14 16:43:43 -04002859 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002860}
2861
2862bool ValidateUnmapBufferOES(Context *context, GLenum target)
2863{
2864 if (!context->getExtensions().mapBuffer)
2865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002866 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002867 return false;
2868 }
2869
2870 return ValidateUnmapBufferBase(context, target);
2871}
2872
2873bool ValidateMapBufferRangeEXT(Context *context,
2874 GLenum target,
2875 GLintptr offset,
2876 GLsizeiptr length,
2877 GLbitfield access)
2878{
2879 if (!context->getExtensions().mapBufferRange)
2880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002881 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002882 return false;
2883 }
2884
2885 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2886}
2887
Geoff Lang79f71042017-08-14 16:43:43 -04002888bool ValidateMapBufferBase(Context *context, GLenum target)
2889{
2890 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2891 ASSERT(buffer != nullptr);
2892
2893 // Check if this buffer is currently being used as a transform feedback output buffer
2894 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2895 if (transformFeedback != nullptr && transformFeedback->isActive())
2896 {
2897 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2898 {
2899 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2900 if (transformFeedbackBuffer.get() == buffer)
2901 {
2902 context->handleError(InvalidOperation()
2903 << "Buffer is currently bound for transform feedback.");
2904 return false;
2905 }
2906 }
2907 }
2908
2909 return true;
2910}
2911
Olli Etuaho4f667482016-03-30 15:56:35 +03002912bool ValidateFlushMappedBufferRangeEXT(Context *context,
2913 GLenum target,
2914 GLintptr offset,
2915 GLsizeiptr length)
2916{
2917 if (!context->getExtensions().mapBufferRange)
2918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002919 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002920 return false;
2921 }
2922
2923 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2924}
2925
Ian Ewell54f87462016-03-10 13:47:21 -05002926bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2927{
2928 Texture *textureObject = context->getTexture(texture);
2929 if (textureObject && textureObject->getTarget() != target && texture != 0)
2930 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002932 return false;
2933 }
2934
Geoff Langf41a7152016-09-19 15:11:17 -04002935 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2936 !context->isTextureGenerated(texture))
2937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002938 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002939 return false;
2940 }
2941
Ian Ewell54f87462016-03-10 13:47:21 -05002942 switch (target)
2943 {
2944 case GL_TEXTURE_2D:
2945 case GL_TEXTURE_CUBE_MAP:
2946 break;
2947
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002948 case GL_TEXTURE_RECTANGLE_ANGLE:
2949 if (!context->getExtensions().textureRectangle)
2950 {
2951 context->handleError(InvalidEnum()
2952 << "Context does not support GL_ANGLE_texture_rectangle");
2953 return false;
2954 }
2955 break;
2956
Ian Ewell54f87462016-03-10 13:47:21 -05002957 case GL_TEXTURE_3D:
2958 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002959 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002960 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002962 return false;
2963 }
2964 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002965
2966 case GL_TEXTURE_2D_MULTISAMPLE:
2967 if (context->getClientVersion() < Version(3, 1))
2968 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002970 return false;
2971 }
Geoff Lang3b573612016-10-31 14:08:10 -04002972 break;
2973
Ian Ewell54f87462016-03-10 13:47:21 -05002974 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002975 if (!context->getExtensions().eglImageExternal &&
2976 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002978 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002979 return false;
2980 }
2981 break;
2982 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002983 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002984 return false;
2985 }
2986
2987 return true;
2988}
2989
Geoff Langd8605522016-04-13 10:19:12 -04002990bool ValidateBindUniformLocationCHROMIUM(Context *context,
2991 GLuint program,
2992 GLint location,
2993 const GLchar *name)
2994{
2995 if (!context->getExtensions().bindUniformLocation)
2996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002997 context->handleError(InvalidOperation()
2998 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002999 return false;
3000 }
3001
3002 Program *programObject = GetValidProgram(context, program);
3003 if (!programObject)
3004 {
3005 return false;
3006 }
3007
3008 if (location < 0)
3009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003010 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04003011 return false;
3012 }
3013
3014 const Caps &caps = context->getCaps();
3015 if (static_cast<size_t>(location) >=
3016 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidValue() << "Location must be less than "
3019 "(MAX_VERTEX_UNIFORM_VECTORS + "
3020 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04003021 return false;
3022 }
3023
Geoff Langfc32e8b2017-05-31 14:16:59 -04003024 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3025 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04003026 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04003027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003028 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04003029 return false;
3030 }
3031
Geoff Langd8605522016-04-13 10:19:12 -04003032 if (strncmp(name, "gl_", 3) == 0)
3033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003034 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04003035 return false;
3036 }
3037
3038 return true;
3039}
3040
Jamie Madille2e406c2016-06-02 13:04:10 -04003041bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03003042{
3043 if (!context->getExtensions().framebufferMixedSamples)
3044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003045 context->handleError(InvalidOperation()
3046 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03003047 return false;
3048 }
3049 switch (components)
3050 {
3051 case GL_RGB:
3052 case GL_RGBA:
3053 case GL_ALPHA:
3054 case GL_NONE:
3055 break;
3056 default:
3057 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003058 InvalidEnum()
3059 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03003060 return false;
3061 }
3062
3063 return true;
3064}
3065
Sami Väisänene45e53b2016-05-25 10:36:04 +03003066// CHROMIUM_path_rendering
3067
3068bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3069{
3070 if (!context->getExtensions().pathRendering)
3071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003072 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003073 return false;
3074 }
3075 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3076 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003077 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003078 return false;
3079 }
3080 if (matrix == nullptr)
3081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003082 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003083 return false;
3084 }
3085 return true;
3086}
3087
3088bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3089{
3090 if (!context->getExtensions().pathRendering)
3091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003092 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003093 return false;
3094 }
3095 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003098 return false;
3099 }
3100 return true;
3101}
3102
3103bool ValidateGenPaths(Context *context, GLsizei range)
3104{
3105 if (!context->getExtensions().pathRendering)
3106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003107 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003108 return false;
3109 }
3110
3111 // range = 0 is undefined in NV_path_rendering.
3112 // we add stricter semantic check here and require a non zero positive range.
3113 if (range <= 0)
3114 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003115 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003116 return false;
3117 }
3118
3119 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003122 return false;
3123 }
3124
3125 return true;
3126}
3127
3128bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3129{
3130 if (!context->getExtensions().pathRendering)
3131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003132 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003133 return false;
3134 }
3135
3136 // range = 0 is undefined in NV_path_rendering.
3137 // we add stricter semantic check here and require a non zero positive range.
3138 if (range <= 0)
3139 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003140 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003141 return false;
3142 }
3143
3144 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3145 checkedRange += range;
3146
3147 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3148 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003150 return false;
3151 }
3152 return true;
3153}
3154
3155bool ValidatePathCommands(Context *context,
3156 GLuint path,
3157 GLsizei numCommands,
3158 const GLubyte *commands,
3159 GLsizei numCoords,
3160 GLenum coordType,
3161 const void *coords)
3162{
3163 if (!context->getExtensions().pathRendering)
3164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003165 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003166 return false;
3167 }
3168 if (!context->hasPath(path))
3169 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003171 return false;
3172 }
3173
3174 if (numCommands < 0)
3175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003176 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003177 return false;
3178 }
3179 else if (numCommands > 0)
3180 {
3181 if (!commands)
3182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003183 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003184 return false;
3185 }
3186 }
3187
3188 if (numCoords < 0)
3189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003190 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003191 return false;
3192 }
3193 else if (numCoords > 0)
3194 {
3195 if (!coords)
3196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003197 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003198 return false;
3199 }
3200 }
3201
3202 std::uint32_t coordTypeSize = 0;
3203 switch (coordType)
3204 {
3205 case GL_BYTE:
3206 coordTypeSize = sizeof(GLbyte);
3207 break;
3208
3209 case GL_UNSIGNED_BYTE:
3210 coordTypeSize = sizeof(GLubyte);
3211 break;
3212
3213 case GL_SHORT:
3214 coordTypeSize = sizeof(GLshort);
3215 break;
3216
3217 case GL_UNSIGNED_SHORT:
3218 coordTypeSize = sizeof(GLushort);
3219 break;
3220
3221 case GL_FLOAT:
3222 coordTypeSize = sizeof(GLfloat);
3223 break;
3224
3225 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003227 return false;
3228 }
3229
3230 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3231 checkedSize += (coordTypeSize * numCoords);
3232 if (!checkedSize.IsValid())
3233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003235 return false;
3236 }
3237
3238 // early return skips command data validation when it doesn't exist.
3239 if (!commands)
3240 return true;
3241
3242 GLsizei expectedNumCoords = 0;
3243 for (GLsizei i = 0; i < numCommands; ++i)
3244 {
3245 switch (commands[i])
3246 {
3247 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3248 break;
3249 case GL_MOVE_TO_CHROMIUM:
3250 case GL_LINE_TO_CHROMIUM:
3251 expectedNumCoords += 2;
3252 break;
3253 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3254 expectedNumCoords += 4;
3255 break;
3256 case GL_CUBIC_CURVE_TO_CHROMIUM:
3257 expectedNumCoords += 6;
3258 break;
3259 case GL_CONIC_CURVE_TO_CHROMIUM:
3260 expectedNumCoords += 5;
3261 break;
3262 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003263 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003264 return false;
3265 }
3266 }
3267 if (expectedNumCoords != numCoords)
3268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003269 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003270 return false;
3271 }
3272
3273 return true;
3274}
3275
3276bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3277{
3278 if (!context->getExtensions().pathRendering)
3279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003280 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003281 return false;
3282 }
3283 if (!context->hasPath(path))
3284 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003285 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003286 return false;
3287 }
3288
3289 switch (pname)
3290 {
3291 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3292 if (value < 0.0f)
3293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003294 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003295 return false;
3296 }
3297 break;
3298 case GL_PATH_END_CAPS_CHROMIUM:
3299 switch (static_cast<GLenum>(value))
3300 {
3301 case GL_FLAT_CHROMIUM:
3302 case GL_SQUARE_CHROMIUM:
3303 case GL_ROUND_CHROMIUM:
3304 break;
3305 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003306 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003307 return false;
3308 }
3309 break;
3310 case GL_PATH_JOIN_STYLE_CHROMIUM:
3311 switch (static_cast<GLenum>(value))
3312 {
3313 case GL_MITER_REVERT_CHROMIUM:
3314 case GL_BEVEL_CHROMIUM:
3315 case GL_ROUND_CHROMIUM:
3316 break;
3317 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003319 return false;
3320 }
3321 case GL_PATH_MITER_LIMIT_CHROMIUM:
3322 if (value < 0.0f)
3323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003324 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003325 return false;
3326 }
3327 break;
3328
3329 case GL_PATH_STROKE_BOUND_CHROMIUM:
3330 // no errors, only clamping.
3331 break;
3332
3333 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003334 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003335 return false;
3336 }
3337 return true;
3338}
3339
3340bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3341{
3342 if (!context->getExtensions().pathRendering)
3343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003344 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003345 return false;
3346 }
3347
3348 if (!context->hasPath(path))
3349 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003350 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003351 return false;
3352 }
3353 if (!value)
3354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003355 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003356 return false;
3357 }
3358
3359 switch (pname)
3360 {
3361 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3362 case GL_PATH_END_CAPS_CHROMIUM:
3363 case GL_PATH_JOIN_STYLE_CHROMIUM:
3364 case GL_PATH_MITER_LIMIT_CHROMIUM:
3365 case GL_PATH_STROKE_BOUND_CHROMIUM:
3366 break;
3367
3368 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003369 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003370 return false;
3371 }
3372
3373 return true;
3374}
3375
3376bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3377{
3378 if (!context->getExtensions().pathRendering)
3379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003380 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003381 return false;
3382 }
3383
3384 switch (func)
3385 {
3386 case GL_NEVER:
3387 case GL_ALWAYS:
3388 case GL_LESS:
3389 case GL_LEQUAL:
3390 case GL_EQUAL:
3391 case GL_GEQUAL:
3392 case GL_GREATER:
3393 case GL_NOTEQUAL:
3394 break;
3395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003397 return false;
3398 }
3399
3400 return true;
3401}
3402
3403// Note that the spec specifies that for the path drawing commands
3404// if the path object is not an existing path object the command
3405// does nothing and no error is generated.
3406// However if the path object exists but has not been specified any
3407// commands then an error is generated.
3408
3409bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3410{
3411 if (!context->getExtensions().pathRendering)
3412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003414 return false;
3415 }
3416 if (context->hasPath(path) && !context->hasPathData(path))
3417 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003419 return false;
3420 }
3421
3422 switch (fillMode)
3423 {
3424 case GL_COUNT_UP_CHROMIUM:
3425 case GL_COUNT_DOWN_CHROMIUM:
3426 break;
3427 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003429 return false;
3430 }
3431
3432 if (!isPow2(mask + 1))
3433 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003434 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003435 return false;
3436 }
3437
3438 return true;
3439}
3440
3441bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3442{
3443 if (!context->getExtensions().pathRendering)
3444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003446 return false;
3447 }
3448 if (context->hasPath(path) && !context->hasPathData(path))
3449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003450 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003451 return false;
3452 }
3453
3454 return true;
3455}
3456
3457bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3458{
3459 if (!context->getExtensions().pathRendering)
3460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003461 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003462 return false;
3463 }
3464 if (context->hasPath(path) && !context->hasPathData(path))
3465 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003467 return false;
3468 }
3469
3470 switch (coverMode)
3471 {
3472 case GL_CONVEX_HULL_CHROMIUM:
3473 case GL_BOUNDING_BOX_CHROMIUM:
3474 break;
3475 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003476 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003477 return false;
3478 }
3479 return true;
3480}
3481
3482bool ValidateStencilThenCoverFillPath(Context *context,
3483 GLuint path,
3484 GLenum fillMode,
3485 GLuint mask,
3486 GLenum coverMode)
3487{
3488 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3489 ValidateCoverPath(context, path, coverMode);
3490}
3491
3492bool ValidateStencilThenCoverStrokePath(Context *context,
3493 GLuint path,
3494 GLint reference,
3495 GLuint mask,
3496 GLenum coverMode)
3497{
3498 return ValidateStencilStrokePath(context, path, reference, mask) &&
3499 ValidateCoverPath(context, path, coverMode);
3500}
3501
3502bool ValidateIsPath(Context *context)
3503{
3504 if (!context->getExtensions().pathRendering)
3505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003506 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003507 return false;
3508 }
3509 return true;
3510}
3511
Sami Väisänend59ca052016-06-21 16:10:00 +03003512bool ValidateCoverFillPathInstanced(Context *context,
3513 GLsizei numPaths,
3514 GLenum pathNameType,
3515 const void *paths,
3516 GLuint pathBase,
3517 GLenum coverMode,
3518 GLenum transformType,
3519 const GLfloat *transformValues)
3520{
3521 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3522 transformType, transformValues))
3523 return false;
3524
3525 switch (coverMode)
3526 {
3527 case GL_CONVEX_HULL_CHROMIUM:
3528 case GL_BOUNDING_BOX_CHROMIUM:
3529 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3530 break;
3531 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003532 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003533 return false;
3534 }
3535
3536 return true;
3537}
3538
3539bool ValidateCoverStrokePathInstanced(Context *context,
3540 GLsizei numPaths,
3541 GLenum pathNameType,
3542 const void *paths,
3543 GLuint pathBase,
3544 GLenum coverMode,
3545 GLenum transformType,
3546 const GLfloat *transformValues)
3547{
3548 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3549 transformType, transformValues))
3550 return false;
3551
3552 switch (coverMode)
3553 {
3554 case GL_CONVEX_HULL_CHROMIUM:
3555 case GL_BOUNDING_BOX_CHROMIUM:
3556 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3557 break;
3558 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003560 return false;
3561 }
3562
3563 return true;
3564}
3565
3566bool ValidateStencilFillPathInstanced(Context *context,
3567 GLsizei numPaths,
3568 GLenum pathNameType,
3569 const void *paths,
3570 GLuint pathBase,
3571 GLenum fillMode,
3572 GLuint mask,
3573 GLenum transformType,
3574 const GLfloat *transformValues)
3575{
3576
3577 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3578 transformType, transformValues))
3579 return false;
3580
3581 switch (fillMode)
3582 {
3583 case GL_COUNT_UP_CHROMIUM:
3584 case GL_COUNT_DOWN_CHROMIUM:
3585 break;
3586 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003588 return false;
3589 }
3590 if (!isPow2(mask + 1))
3591 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003592 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003593 return false;
3594 }
3595 return true;
3596}
3597
3598bool ValidateStencilStrokePathInstanced(Context *context,
3599 GLsizei numPaths,
3600 GLenum pathNameType,
3601 const void *paths,
3602 GLuint pathBase,
3603 GLint reference,
3604 GLuint mask,
3605 GLenum transformType,
3606 const GLfloat *transformValues)
3607{
3608 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3609 transformType, transformValues))
3610 return false;
3611
3612 // no more validation here.
3613
3614 return true;
3615}
3616
3617bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3618 GLsizei numPaths,
3619 GLenum pathNameType,
3620 const void *paths,
3621 GLuint pathBase,
3622 GLenum fillMode,
3623 GLuint mask,
3624 GLenum coverMode,
3625 GLenum transformType,
3626 const GLfloat *transformValues)
3627{
3628 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3629 transformType, transformValues))
3630 return false;
3631
3632 switch (coverMode)
3633 {
3634 case GL_CONVEX_HULL_CHROMIUM:
3635 case GL_BOUNDING_BOX_CHROMIUM:
3636 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3637 break;
3638 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003640 return false;
3641 }
3642
3643 switch (fillMode)
3644 {
3645 case GL_COUNT_UP_CHROMIUM:
3646 case GL_COUNT_DOWN_CHROMIUM:
3647 break;
3648 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003650 return false;
3651 }
3652 if (!isPow2(mask + 1))
3653 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003654 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003655 return false;
3656 }
3657
3658 return true;
3659}
3660
3661bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3662 GLsizei numPaths,
3663 GLenum pathNameType,
3664 const void *paths,
3665 GLuint pathBase,
3666 GLint reference,
3667 GLuint mask,
3668 GLenum coverMode,
3669 GLenum transformType,
3670 const GLfloat *transformValues)
3671{
3672 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3673 transformType, transformValues))
3674 return false;
3675
3676 switch (coverMode)
3677 {
3678 case GL_CONVEX_HULL_CHROMIUM:
3679 case GL_BOUNDING_BOX_CHROMIUM:
3680 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3681 break;
3682 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003684 return false;
3685 }
3686
3687 return true;
3688}
3689
Sami Väisänen46eaa942016-06-29 10:26:37 +03003690bool ValidateBindFragmentInputLocation(Context *context,
3691 GLuint program,
3692 GLint location,
3693 const GLchar *name)
3694{
3695 if (!context->getExtensions().pathRendering)
3696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003698 return false;
3699 }
3700
3701 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3702 if (location >= MaxLocation)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003705 return false;
3706 }
3707
3708 const auto *programObject = context->getProgram(program);
3709 if (!programObject)
3710 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003712 return false;
3713 }
3714
3715 if (!name)
3716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003717 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003718 return false;
3719 }
3720
3721 if (angle::BeginsWith(name, "gl_"))
3722 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003724 return false;
3725 }
3726
3727 return true;
3728}
3729
3730bool ValidateProgramPathFragmentInputGen(Context *context,
3731 GLuint program,
3732 GLint location,
3733 GLenum genMode,
3734 GLint components,
3735 const GLfloat *coeffs)
3736{
3737 if (!context->getExtensions().pathRendering)
3738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003740 return false;
3741 }
3742
3743 const auto *programObject = context->getProgram(program);
3744 if (!programObject || programObject->isFlaggedForDeletion())
3745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003746 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003747 return false;
3748 }
3749
3750 if (!programObject->isLinked())
3751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003753 return false;
3754 }
3755
3756 switch (genMode)
3757 {
3758 case GL_NONE:
3759 if (components != 0)
3760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003761 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003762 return false;
3763 }
3764 break;
3765
3766 case GL_OBJECT_LINEAR_CHROMIUM:
3767 case GL_EYE_LINEAR_CHROMIUM:
3768 case GL_CONSTANT_CHROMIUM:
3769 if (components < 1 || components > 4)
3770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003772 return false;
3773 }
3774 if (!coeffs)
3775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003776 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003777 return false;
3778 }
3779 break;
3780
3781 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003783 return false;
3784 }
3785
3786 // If the location is -1 then the command is silently ignored
3787 // and no further validation is needed.
3788 if (location == -1)
3789 return true;
3790
Jamie Madillbd044ed2017-06-05 12:59:21 -04003791 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003792
3793 if (!binding.valid)
3794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003795 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003796 return false;
3797 }
3798
3799 if (binding.type != GL_NONE)
3800 {
3801 GLint expectedComponents = 0;
3802 switch (binding.type)
3803 {
3804 case GL_FLOAT:
3805 expectedComponents = 1;
3806 break;
3807 case GL_FLOAT_VEC2:
3808 expectedComponents = 2;
3809 break;
3810 case GL_FLOAT_VEC3:
3811 expectedComponents = 3;
3812 break;
3813 case GL_FLOAT_VEC4:
3814 expectedComponents = 4;
3815 break;
3816 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003817 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 InvalidOperation()
3819 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003820 return false;
3821 }
3822 if (expectedComponents != components && genMode != GL_NONE)
3823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003825 return false;
3826 }
3827 }
3828 return true;
3829}
3830
Geoff Lang97073d12016-04-20 10:42:34 -07003831bool ValidateCopyTextureCHROMIUM(Context *context,
3832 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003833 GLint sourceLevel,
3834 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003835 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003836 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003837 GLint internalFormat,
3838 GLenum destType,
3839 GLboolean unpackFlipY,
3840 GLboolean unpackPremultiplyAlpha,
3841 GLboolean unpackUnmultiplyAlpha)
3842{
3843 if (!context->getExtensions().copyTexture)
3844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003845 context->handleError(InvalidOperation()
3846 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003847 return false;
3848 }
3849
Geoff Lang4f0e0032017-05-01 16:04:35 -04003850 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003851 if (source == nullptr)
3852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003853 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003854 return false;
3855 }
3856
3857 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003859 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003860 return false;
3861 }
3862
3863 GLenum sourceTarget = source->getTarget();
3864 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003865
3866 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003868 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003869 return false;
3870 }
3871
Geoff Lang4f0e0032017-05-01 16:04:35 -04003872 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3873 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3874 if (sourceWidth == 0 || sourceHeight == 0)
3875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003876 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003877 return false;
3878 }
3879
3880 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3881 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003884 return false;
3885 }
3886
Geoff Lang63458a32017-10-30 15:16:53 -04003887 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3888 {
3889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
3890 return false;
3891 }
3892
Geoff Lang4f0e0032017-05-01 16:04:35 -04003893 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003894 if (dest == nullptr)
3895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003896 context->handleError(InvalidValue()
3897 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003898 return false;
3899 }
3900
Geoff Lang4f0e0032017-05-01 16:04:35 -04003901 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003903 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003904 return false;
3905 }
3906
Geoff Lang4f0e0032017-05-01 16:04:35 -04003907 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3908 sourceHeight))
3909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003910 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003911 return false;
3912 }
3913
Geoff Lang97073d12016-04-20 10:42:34 -07003914 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003917 return false;
3918 }
3919
Geoff Lang4f0e0032017-05-01 16:04:35 -04003920 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003922 context->handleError(
3923 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003924 return false;
3925 }
3926
Geoff Lang97073d12016-04-20 10:42:34 -07003927 if (dest->getImmutableFormat())
3928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003929 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003930 return false;
3931 }
3932
3933 return true;
3934}
3935
3936bool ValidateCopySubTextureCHROMIUM(Context *context,
3937 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003938 GLint sourceLevel,
3939 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003940 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003941 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003942 GLint xoffset,
3943 GLint yoffset,
3944 GLint x,
3945 GLint y,
3946 GLsizei width,
3947 GLsizei height,
3948 GLboolean unpackFlipY,
3949 GLboolean unpackPremultiplyAlpha,
3950 GLboolean unpackUnmultiplyAlpha)
3951{
3952 if (!context->getExtensions().copyTexture)
3953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(InvalidOperation()
3955 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003956 return false;
3957 }
3958
Geoff Lang4f0e0032017-05-01 16:04:35 -04003959 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003960 if (source == nullptr)
3961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003962 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003963 return false;
3964 }
3965
3966 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003968 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003969 return false;
3970 }
3971
3972 GLenum sourceTarget = source->getTarget();
3973 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003974
3975 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003977 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003978 return false;
3979 }
3980
3981 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3982 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidValue()
3985 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003986 return false;
3987 }
3988
3989 if (x < 0 || y < 0)
3990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003991 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003992 return false;
3993 }
3994
3995 if (width < 0 || height < 0)
3996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003997 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003998 return false;
3999 }
4000
Geoff Lang4f0e0032017-05-01 16:04:35 -04004001 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
4002 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004004 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07004005 return false;
4006 }
4007
Geoff Lang4f0e0032017-05-01 16:04:35 -04004008 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
4009 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07004012 return false;
4013 }
4014
Geoff Lang63458a32017-10-30 15:16:53 -04004015 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
4016 {
4017 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
4018 return false;
4019 }
4020
Geoff Lang4f0e0032017-05-01 16:04:35 -04004021 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07004022 if (dest == nullptr)
4023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004024 context->handleError(InvalidValue()
4025 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07004026 return false;
4027 }
4028
Geoff Lang4f0e0032017-05-01 16:04:35 -04004029 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07004030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004031 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07004032 return false;
4033 }
4034
Geoff Lang4f0e0032017-05-01 16:04:35 -04004035 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07004036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004037 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004038 return false;
4039 }
4040
Geoff Lang4f0e0032017-05-01 16:04:35 -04004041 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
4042 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04004043 context
4044 ->handleError(InvalidOperation()
4045 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04004046 return false;
4047 }
4048
4049 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
4050 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004051 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004052 context->handleError(InvalidOperation()
4053 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004054 return false;
4055 }
4056
4057 if (xoffset < 0 || yoffset < 0)
4058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004059 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07004060 return false;
4061 }
4062
Geoff Lang4f0e0032017-05-01 16:04:35 -04004063 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
4064 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004066 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07004067 return false;
4068 }
4069
4070 return true;
4071}
4072
Geoff Lang47110bf2016-04-20 11:13:22 -07004073bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
4074{
4075 if (!context->getExtensions().copyCompressedTexture)
4076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004077 context->handleError(InvalidOperation()
4078 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004079 return false;
4080 }
4081
4082 const gl::Texture *source = context->getTexture(sourceId);
4083 if (source == nullptr)
4084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004085 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004086 return false;
4087 }
4088
4089 if (source->getTarget() != GL_TEXTURE_2D)
4090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004091 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004092 return false;
4093 }
4094
4095 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004097 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004098 return false;
4099 }
4100
4101 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4102 if (!sourceFormat.info->compressed)
4103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004104 context->handleError(InvalidOperation()
4105 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004106 return false;
4107 }
4108
4109 const gl::Texture *dest = context->getTexture(destId);
4110 if (dest == nullptr)
4111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004112 context->handleError(InvalidValue()
4113 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004114 return false;
4115 }
4116
4117 if (dest->getTarget() != GL_TEXTURE_2D)
4118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004119 context->handleError(InvalidValue()
4120 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004121 return false;
4122 }
4123
4124 if (dest->getImmutableFormat())
4125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004126 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004127 return false;
4128 }
4129
4130 return true;
4131}
4132
Martin Radev4c4c8e72016-08-04 12:25:34 +03004133bool ValidateCreateShader(Context *context, GLenum type)
4134{
4135 switch (type)
4136 {
4137 case GL_VERTEX_SHADER:
4138 case GL_FRAGMENT_SHADER:
4139 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004140
Martin Radev4c4c8e72016-08-04 12:25:34 +03004141 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004142 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004143 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Langeb66a6e2016-10-31 13:06:12 -04004145 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004146 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004147 break;
4148
Martin Radev4c4c8e72016-08-04 12:25:34 +03004149 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004151 return false;
4152 }
Jamie Madill29639852016-09-02 15:00:09 -04004153
4154 return true;
4155}
4156
4157bool ValidateBufferData(ValidationContext *context,
4158 GLenum target,
4159 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004160 const void *data,
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004161 BufferUsage usage)
Jamie Madill29639852016-09-02 15:00:09 -04004162{
4163 if (size < 0)
4164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004165 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004166 return false;
4167 }
4168
4169 switch (usage)
4170 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004171 case BufferUsage::StreamDraw:
4172 case BufferUsage::StaticDraw:
4173 case BufferUsage::DynamicDraw:
Jamie Madill29639852016-09-02 15:00:09 -04004174 break;
4175
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004176 case BufferUsage::StreamRead:
4177 case BufferUsage::StaticRead:
4178 case BufferUsage::DynamicRead:
4179 case BufferUsage::StreamCopy:
4180 case BufferUsage::StaticCopy:
4181 case BufferUsage::DynamicCopy:
Jamie Madill29639852016-09-02 15:00:09 -04004182 if (context->getClientMajorVersion() < 3)
4183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004185 return false;
4186 }
4187 break;
4188
4189 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004191 return false;
4192 }
4193
4194 if (!ValidBufferTarget(context, target))
4195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004197 return false;
4198 }
4199
4200 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4201
4202 if (!buffer)
4203 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004205 return false;
4206 }
4207
4208 return true;
4209}
4210
4211bool ValidateBufferSubData(ValidationContext *context,
4212 GLenum target,
4213 GLintptr offset,
4214 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004215 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004216{
Brandon Jones6cad5662017-06-14 13:25:13 -07004217 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004219 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4220 return false;
4221 }
4222
4223 if (offset < 0)
4224 {
4225 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004226 return false;
4227 }
4228
4229 if (!ValidBufferTarget(context, target))
4230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004232 return false;
4233 }
4234
4235 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4236
4237 if (!buffer)
4238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004240 return false;
4241 }
4242
4243 if (buffer->isMapped())
4244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004245 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004246 return false;
4247 }
4248
4249 // Check for possible overflow of size + offset
4250 angle::CheckedNumeric<size_t> checkedSize(size);
4251 checkedSize += offset;
4252 if (!checkedSize.IsValid())
4253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004254 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004255 return false;
4256 }
4257
4258 if (size + offset > buffer->getSize())
4259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004260 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004261 return false;
4262 }
4263
Martin Radev4c4c8e72016-08-04 12:25:34 +03004264 return true;
4265}
4266
Geoff Lang111a99e2017-10-17 10:58:41 -04004267bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004268{
Geoff Langc339c4e2016-11-29 10:37:36 -05004269 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004271 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004272 return false;
4273 }
4274
Geoff Lang111a99e2017-10-17 10:58:41 -04004275 if (!context->isExtensionRequestable(name))
Geoff Langc287ea62016-09-16 14:46:51 -04004276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004277 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004278 return false;
4279 }
4280
4281 return true;
4282}
4283
Jamie Madillef300b12016-10-07 15:12:09 -04004284bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4285{
4286 if (texture < GL_TEXTURE0 ||
4287 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004289 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004290 return false;
4291 }
4292
4293 return true;
4294}
4295
4296bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4297{
4298 Program *programObject = GetValidProgram(context, program);
4299 if (!programObject)
4300 {
4301 return false;
4302 }
4303
4304 Shader *shaderObject = GetValidShader(context, shader);
4305 if (!shaderObject)
4306 {
4307 return false;
4308 }
4309
4310 switch (shaderObject->getType())
4311 {
4312 case GL_VERTEX_SHADER:
4313 {
4314 if (programObject->getAttachedVertexShader())
4315 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004317 return false;
4318 }
4319 break;
4320 }
4321 case GL_FRAGMENT_SHADER:
4322 {
4323 if (programObject->getAttachedFragmentShader())
4324 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004325 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004326 return false;
4327 }
4328 break;
4329 }
4330 case GL_COMPUTE_SHADER:
4331 {
4332 if (programObject->getAttachedComputeShader())
4333 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004335 return false;
4336 }
4337 break;
4338 }
4339 default:
4340 UNREACHABLE();
4341 break;
4342 }
4343
4344 return true;
4345}
4346
Jamie Madill01a80ee2016-11-07 12:06:18 -05004347bool ValidateBindAttribLocation(ValidationContext *context,
4348 GLuint program,
4349 GLuint index,
4350 const GLchar *name)
4351{
4352 if (index >= MAX_VERTEX_ATTRIBS)
4353 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004354 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004355 return false;
4356 }
4357
4358 if (strncmp(name, "gl_", 3) == 0)
4359 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004360 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004361 return false;
4362 }
4363
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004364 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004365 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004366 const size_t length = strlen(name);
4367
4368 if (!IsValidESSLString(name, length))
4369 {
4370 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4371 // for shader-related entry points
4372 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4373 return false;
4374 }
4375
4376 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4377 {
4378 return false;
4379 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004380 }
4381
Jamie Madill01a80ee2016-11-07 12:06:18 -05004382 return GetValidProgram(context, program) != nullptr;
4383}
4384
4385bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4386{
4387 if (!ValidBufferTarget(context, target))
4388 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004390 return false;
4391 }
4392
4393 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4394 !context->isBufferGenerated(buffer))
4395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004396 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004397 return false;
4398 }
4399
4400 return true;
4401}
4402
4403bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4404{
4405 if (!ValidFramebufferTarget(target))
4406 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004408 return false;
4409 }
4410
4411 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4412 !context->isFramebufferGenerated(framebuffer))
4413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004415 return false;
4416 }
4417
4418 return true;
4419}
4420
4421bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4422{
4423 if (target != GL_RENDERBUFFER)
4424 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004426 return false;
4427 }
4428
4429 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4430 !context->isRenderbufferGenerated(renderbuffer))
4431 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004432 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004433 return false;
4434 }
4435
4436 return true;
4437}
4438
Geoff Lang50cac572017-09-26 17:37:43 -04004439static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004440{
4441 switch (mode)
4442 {
4443 case GL_FUNC_ADD:
4444 case GL_FUNC_SUBTRACT:
4445 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004446 return true;
4447
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004448 case GL_MIN:
4449 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004450 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004451
4452 default:
4453 return false;
4454 }
4455}
4456
Jamie Madillc1d770e2017-04-13 17:31:24 -04004457bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004458 GLfloat red,
4459 GLfloat green,
4460 GLfloat blue,
4461 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004462{
4463 return true;
4464}
4465
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004466bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4467{
Geoff Lang50cac572017-09-26 17:37:43 -04004468 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004471 return false;
4472 }
4473
4474 return true;
4475}
4476
4477bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4478{
Geoff Lang50cac572017-09-26 17:37:43 -04004479 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004480 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004482 return false;
4483 }
4484
Geoff Lang50cac572017-09-26 17:37:43 -04004485 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004488 return false;
4489 }
4490
4491 return true;
4492}
4493
4494bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4495{
4496 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4497}
4498
4499static bool ValidSrcBlendFunc(GLenum srcBlend)
4500{
4501 switch (srcBlend)
4502 {
4503 case GL_ZERO:
4504 case GL_ONE:
4505 case GL_SRC_COLOR:
4506 case GL_ONE_MINUS_SRC_COLOR:
4507 case GL_DST_COLOR:
4508 case GL_ONE_MINUS_DST_COLOR:
4509 case GL_SRC_ALPHA:
4510 case GL_ONE_MINUS_SRC_ALPHA:
4511 case GL_DST_ALPHA:
4512 case GL_ONE_MINUS_DST_ALPHA:
4513 case GL_CONSTANT_COLOR:
4514 case GL_ONE_MINUS_CONSTANT_COLOR:
4515 case GL_CONSTANT_ALPHA:
4516 case GL_ONE_MINUS_CONSTANT_ALPHA:
4517 case GL_SRC_ALPHA_SATURATE:
4518 return true;
4519
4520 default:
4521 return false;
4522 }
4523}
4524
4525static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4526{
4527 switch (dstBlend)
4528 {
4529 case GL_ZERO:
4530 case GL_ONE:
4531 case GL_SRC_COLOR:
4532 case GL_ONE_MINUS_SRC_COLOR:
4533 case GL_DST_COLOR:
4534 case GL_ONE_MINUS_DST_COLOR:
4535 case GL_SRC_ALPHA:
4536 case GL_ONE_MINUS_SRC_ALPHA:
4537 case GL_DST_ALPHA:
4538 case GL_ONE_MINUS_DST_ALPHA:
4539 case GL_CONSTANT_COLOR:
4540 case GL_ONE_MINUS_CONSTANT_COLOR:
4541 case GL_CONSTANT_ALPHA:
4542 case GL_ONE_MINUS_CONSTANT_ALPHA:
4543 return true;
4544
4545 case GL_SRC_ALPHA_SATURATE:
4546 return (contextMajorVersion >= 3);
4547
4548 default:
4549 return false;
4550 }
4551}
4552
4553bool ValidateBlendFuncSeparate(ValidationContext *context,
4554 GLenum srcRGB,
4555 GLenum dstRGB,
4556 GLenum srcAlpha,
4557 GLenum dstAlpha)
4558{
4559 if (!ValidSrcBlendFunc(srcRGB))
4560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004561 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004562 return false;
4563 }
4564
4565 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004568 return false;
4569 }
4570
4571 if (!ValidSrcBlendFunc(srcAlpha))
4572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004574 return false;
4575 }
4576
4577 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4578 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004580 return false;
4581 }
4582
Frank Henigman146e8a12017-03-02 23:22:37 -05004583 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4584 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004585 {
4586 bool constantColorUsed =
4587 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4588 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4589
4590 bool constantAlphaUsed =
4591 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4592 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4593
4594 if (constantColorUsed && constantAlphaUsed)
4595 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004596 const char *msg;
4597 if (context->getExtensions().webglCompatibility)
4598 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004599 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004600 }
4601 else
4602 {
4603 msg =
4604 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4605 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4606 "implementation.";
4607 ERR() << msg;
4608 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004609 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004610 return false;
4611 }
4612 }
4613
4614 return true;
4615}
4616
Geoff Langc339c4e2016-11-29 10:37:36 -05004617bool ValidateGetString(Context *context, GLenum name)
4618{
4619 switch (name)
4620 {
4621 case GL_VENDOR:
4622 case GL_RENDERER:
4623 case GL_VERSION:
4624 case GL_SHADING_LANGUAGE_VERSION:
4625 case GL_EXTENSIONS:
4626 break;
4627
4628 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4629 if (!context->getExtensions().requestExtension)
4630 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004631 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004632 return false;
4633 }
4634 break;
4635
4636 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004637 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004638 return false;
4639 }
4640
4641 return true;
4642}
4643
Geoff Lang47c48082016-12-07 15:38:13 -05004644bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4645{
4646 if (width <= 0.0f || isNaN(width))
4647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004648 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004649 return false;
4650 }
4651
4652 return true;
4653}
4654
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004655bool ValidateVertexAttribPointer(ValidationContext *context,
4656 GLuint index,
4657 GLint size,
4658 GLenum type,
4659 GLboolean normalized,
4660 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004661 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004662{
Shao80957d92017-02-20 21:25:59 +08004663 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004664 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004665 return false;
4666 }
4667
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004668 if (stride < 0)
4669 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004670 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004671 return false;
4672 }
4673
Shao80957d92017-02-20 21:25:59 +08004674 const Caps &caps = context->getCaps();
4675 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004676 {
Shao80957d92017-02-20 21:25:59 +08004677 if (stride > caps.maxVertexAttribStride)
4678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004679 context->handleError(InvalidValue()
4680 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004681 return false;
4682 }
4683
4684 if (index >= caps.maxVertexAttribBindings)
4685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004686 context->handleError(InvalidValue()
4687 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004688 return false;
4689 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004690 }
4691
4692 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4693 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4694 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4695 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004696 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4697 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004698 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004700 context
4701 ->handleError(InvalidOperation()
4702 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004703 return false;
4704 }
4705
4706 if (context->getExtensions().webglCompatibility)
4707 {
4708 // WebGL 1.0 [Section 6.14] Fixed point support
4709 // The WebGL API does not support the GL_FIXED data type.
4710 if (type == GL_FIXED)
4711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004712 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004713 return false;
4714 }
4715
Geoff Lang2d62ab72017-03-23 16:54:40 -04004716 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004717 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004718 return false;
4719 }
4720 }
4721
4722 return true;
4723}
4724
Jamie Madill876429b2017-04-20 15:46:24 -04004725bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004726{
4727 if (context->getExtensions().webglCompatibility && zNear > zFar)
4728 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004729 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004730 return false;
4731 }
4732
4733 return true;
4734}
4735
Jamie Madille8fb6402017-02-14 17:56:40 -05004736bool ValidateRenderbufferStorage(ValidationContext *context,
4737 GLenum target,
4738 GLenum internalformat,
4739 GLsizei width,
4740 GLsizei height)
4741{
4742 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4743 height);
4744}
4745
4746bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4747 GLenum target,
4748 GLsizei samples,
4749 GLenum internalformat,
4750 GLsizei width,
4751 GLsizei height)
4752{
4753 if (!context->getExtensions().framebufferMultisample)
4754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004755 context->handleError(InvalidOperation()
4756 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004757 return false;
4758 }
4759
4760 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4761 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4762 // generated.
4763 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004765 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004766 return false;
4767 }
4768
4769 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4770 // the specified storage. This is different than ES 3.0 in which a sample number higher
4771 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4772 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4773 if (context->getClientMajorVersion() >= 3)
4774 {
4775 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4776 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004778 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004779 return false;
4780 }
4781 }
4782
4783 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4784 width, height);
4785}
4786
Jamie Madillc1d770e2017-04-13 17:31:24 -04004787bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4788{
4789 if (!ValidFramebufferTarget(target))
4790 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004791 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004792 return false;
4793 }
4794
4795 return true;
4796}
4797
4798bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004799 GLfloat red,
4800 GLfloat green,
4801 GLfloat blue,
4802 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004803{
4804 return true;
4805}
4806
Jamie Madill876429b2017-04-20 15:46:24 -04004807bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004808{
4809 return true;
4810}
4811
4812bool ValidateClearStencil(ValidationContext *context, GLint s)
4813{
4814 return true;
4815}
4816
4817bool ValidateColorMask(ValidationContext *context,
4818 GLboolean red,
4819 GLboolean green,
4820 GLboolean blue,
4821 GLboolean alpha)
4822{
4823 return true;
4824}
4825
4826bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4827{
4828 return true;
4829}
4830
4831bool ValidateCreateProgram(ValidationContext *context)
4832{
4833 return true;
4834}
4835
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004836bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004837{
4838 switch (mode)
4839 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004840 case CullFaceMode::Front:
4841 case CullFaceMode::Back:
4842 case CullFaceMode::FrontAndBack:
Jamie Madillc1d770e2017-04-13 17:31:24 -04004843 break;
4844
4845 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004847 return false;
4848 }
4849
4850 return true;
4851}
4852
4853bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4854{
4855 if (program == 0)
4856 {
4857 return false;
4858 }
4859
4860 if (!context->getProgram(program))
4861 {
4862 if (context->getShader(program))
4863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004865 return false;
4866 }
4867 else
4868 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004869 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004870 return false;
4871 }
4872 }
4873
4874 return true;
4875}
4876
4877bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4878{
4879 if (shader == 0)
4880 {
4881 return false;
4882 }
4883
4884 if (!context->getShader(shader))
4885 {
4886 if (context->getProgram(shader))
4887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004889 return false;
4890 }
4891 else
4892 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004893 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004894 return false;
4895 }
4896 }
4897
4898 return true;
4899}
4900
4901bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4902{
4903 switch (func)
4904 {
4905 case GL_NEVER:
4906 case GL_ALWAYS:
4907 case GL_LESS:
4908 case GL_LEQUAL:
4909 case GL_EQUAL:
4910 case GL_GREATER:
4911 case GL_GEQUAL:
4912 case GL_NOTEQUAL:
4913 break;
4914
4915 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004917 return false;
4918 }
4919
4920 return true;
4921}
4922
4923bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4924{
4925 return true;
4926}
4927
4928bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4929{
4930 Program *programObject = GetValidProgram(context, program);
4931 if (!programObject)
4932 {
4933 return false;
4934 }
4935
4936 Shader *shaderObject = GetValidShader(context, shader);
4937 if (!shaderObject)
4938 {
4939 return false;
4940 }
4941
4942 const Shader *attachedShader = nullptr;
4943
4944 switch (shaderObject->getType())
4945 {
4946 case GL_VERTEX_SHADER:
4947 {
4948 attachedShader = programObject->getAttachedVertexShader();
4949 break;
4950 }
4951 case GL_FRAGMENT_SHADER:
4952 {
4953 attachedShader = programObject->getAttachedFragmentShader();
4954 break;
4955 }
4956 case GL_COMPUTE_SHADER:
4957 {
4958 attachedShader = programObject->getAttachedComputeShader();
4959 break;
4960 }
4961 default:
4962 UNREACHABLE();
4963 return false;
4964 }
4965
4966 if (attachedShader != shaderObject)
4967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004969 return false;
4970 }
4971
4972 return true;
4973}
4974
4975bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4976{
4977 if (index >= MAX_VERTEX_ATTRIBS)
4978 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004979 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004980 return false;
4981 }
4982
4983 return true;
4984}
4985
4986bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4987{
4988 if (index >= MAX_VERTEX_ATTRIBS)
4989 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004990 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004991 return false;
4992 }
4993
4994 return true;
4995}
4996
4997bool ValidateFinish(ValidationContext *context)
4998{
4999 return true;
5000}
5001
5002bool ValidateFlush(ValidationContext *context)
5003{
5004 return true;
5005}
5006
5007bool ValidateFrontFace(ValidationContext *context, GLenum mode)
5008{
5009 switch (mode)
5010 {
5011 case GL_CW:
5012 case GL_CCW:
5013 break;
5014 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005016 return false;
5017 }
5018
5019 return true;
5020}
5021
5022bool ValidateGetActiveAttrib(ValidationContext *context,
5023 GLuint program,
5024 GLuint index,
5025 GLsizei bufsize,
5026 GLsizei *length,
5027 GLint *size,
5028 GLenum *type,
5029 GLchar *name)
5030{
5031 if (bufsize < 0)
5032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005033 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005034 return false;
5035 }
5036
5037 Program *programObject = GetValidProgram(context, program);
5038
5039 if (!programObject)
5040 {
5041 return false;
5042 }
5043
5044 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5045 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005046 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005047 return false;
5048 }
5049
5050 return true;
5051}
5052
5053bool ValidateGetActiveUniform(ValidationContext *context,
5054 GLuint program,
5055 GLuint index,
5056 GLsizei bufsize,
5057 GLsizei *length,
5058 GLint *size,
5059 GLenum *type,
5060 GLchar *name)
5061{
5062 if (bufsize < 0)
5063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005064 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005065 return false;
5066 }
5067
5068 Program *programObject = GetValidProgram(context, program);
5069
5070 if (!programObject)
5071 {
5072 return false;
5073 }
5074
5075 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5076 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005077 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005078 return false;
5079 }
5080
5081 return true;
5082}
5083
5084bool ValidateGetAttachedShaders(ValidationContext *context,
5085 GLuint program,
5086 GLsizei maxcount,
5087 GLsizei *count,
5088 GLuint *shaders)
5089{
5090 if (maxcount < 0)
5091 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005092 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005093 return false;
5094 }
5095
5096 Program *programObject = GetValidProgram(context, program);
5097
5098 if (!programObject)
5099 {
5100 return false;
5101 }
5102
5103 return true;
5104}
5105
5106bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5107{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005108 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5109 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005110 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005111 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005112 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005113 return false;
5114 }
5115
Jamie Madillc1d770e2017-04-13 17:31:24 -04005116 Program *programObject = GetValidProgram(context, program);
5117
5118 if (!programObject)
5119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005121 return false;
5122 }
5123
5124 if (!programObject->isLinked())
5125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005127 return false;
5128 }
5129
5130 return true;
5131}
5132
5133bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5134{
5135 GLenum nativeType;
5136 unsigned int numParams = 0;
5137 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5138}
5139
5140bool ValidateGetError(ValidationContext *context)
5141{
5142 return true;
5143}
5144
5145bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5146{
5147 GLenum nativeType;
5148 unsigned int numParams = 0;
5149 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5150}
5151
5152bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5153{
5154 GLenum nativeType;
5155 unsigned int numParams = 0;
5156 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5157}
5158
5159bool ValidateGetProgramInfoLog(ValidationContext *context,
5160 GLuint program,
5161 GLsizei bufsize,
5162 GLsizei *length,
5163 GLchar *infolog)
5164{
5165 if (bufsize < 0)
5166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005167 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005168 return false;
5169 }
5170
5171 Program *programObject = GetValidProgram(context, program);
5172 if (!programObject)
5173 {
5174 return false;
5175 }
5176
5177 return true;
5178}
5179
5180bool ValidateGetShaderInfoLog(ValidationContext *context,
5181 GLuint shader,
5182 GLsizei bufsize,
5183 GLsizei *length,
5184 GLchar *infolog)
5185{
5186 if (bufsize < 0)
5187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005188 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005189 return false;
5190 }
5191
5192 Shader *shaderObject = GetValidShader(context, shader);
5193 if (!shaderObject)
5194 {
5195 return false;
5196 }
5197
5198 return true;
5199}
5200
5201bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5202 GLenum shadertype,
5203 GLenum precisiontype,
5204 GLint *range,
5205 GLint *precision)
5206{
5207 switch (shadertype)
5208 {
5209 case GL_VERTEX_SHADER:
5210 case GL_FRAGMENT_SHADER:
5211 break;
5212 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005213 context->handleError(InvalidOperation()
5214 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005215 return false;
5216 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005217 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005218 return false;
5219 }
5220
5221 switch (precisiontype)
5222 {
5223 case GL_LOW_FLOAT:
5224 case GL_MEDIUM_FLOAT:
5225 case GL_HIGH_FLOAT:
5226 case GL_LOW_INT:
5227 case GL_MEDIUM_INT:
5228 case GL_HIGH_INT:
5229 break;
5230
5231 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005233 return false;
5234 }
5235
5236 return true;
5237}
5238
5239bool ValidateGetShaderSource(ValidationContext *context,
5240 GLuint shader,
5241 GLsizei bufsize,
5242 GLsizei *length,
5243 GLchar *source)
5244{
5245 if (bufsize < 0)
5246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005247 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005248 return false;
5249 }
5250
5251 Shader *shaderObject = GetValidShader(context, shader);
5252 if (!shaderObject)
5253 {
5254 return false;
5255 }
5256
5257 return true;
5258}
5259
5260bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5261{
5262 if (strstr(name, "gl_") == name)
5263 {
5264 return false;
5265 }
5266
Geoff Langfc32e8b2017-05-31 14:16:59 -04005267 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5268 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005269 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005270 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005271 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005272 return false;
5273 }
5274
Jamie Madillc1d770e2017-04-13 17:31:24 -04005275 Program *programObject = GetValidProgram(context, program);
5276
5277 if (!programObject)
5278 {
5279 return false;
5280 }
5281
5282 if (!programObject->isLinked())
5283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005285 return false;
5286 }
5287
5288 return true;
5289}
5290
5291bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5292{
5293 switch (mode)
5294 {
5295 case GL_FASTEST:
5296 case GL_NICEST:
5297 case GL_DONT_CARE:
5298 break;
5299
5300 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005302 return false;
5303 }
5304
5305 switch (target)
5306 {
5307 case GL_GENERATE_MIPMAP_HINT:
5308 break;
5309
Geoff Lange7bd2182017-06-16 16:13:13 -04005310 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5311 if (context->getClientVersion() < ES_3_0 &&
5312 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005313 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005314 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005315 return false;
5316 }
5317 break;
5318
5319 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005321 return false;
5322 }
5323
5324 return true;
5325}
5326
5327bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5328{
5329 return true;
5330}
5331
5332bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5333{
5334 return true;
5335}
5336
5337bool ValidateIsProgram(ValidationContext *context, GLuint program)
5338{
5339 return true;
5340}
5341
5342bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5343{
5344 return true;
5345}
5346
5347bool ValidateIsShader(ValidationContext *context, GLuint shader)
5348{
5349 return true;
5350}
5351
5352bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5353{
5354 return true;
5355}
5356
5357bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5358{
5359 if (context->getClientMajorVersion() < 3)
5360 {
5361 switch (pname)
5362 {
5363 case GL_UNPACK_IMAGE_HEIGHT:
5364 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005365 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005366 return false;
5367
5368 case GL_UNPACK_ROW_LENGTH:
5369 case GL_UNPACK_SKIP_ROWS:
5370 case GL_UNPACK_SKIP_PIXELS:
5371 if (!context->getExtensions().unpackSubimage)
5372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005373 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005374 return false;
5375 }
5376 break;
5377
5378 case GL_PACK_ROW_LENGTH:
5379 case GL_PACK_SKIP_ROWS:
5380 case GL_PACK_SKIP_PIXELS:
5381 if (!context->getExtensions().packSubimage)
5382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005383 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005384 return false;
5385 }
5386 break;
5387 }
5388 }
5389
5390 if (param < 0)
5391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005392 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005393 return false;
5394 }
5395
5396 switch (pname)
5397 {
5398 case GL_UNPACK_ALIGNMENT:
5399 if (param != 1 && param != 2 && param != 4 && param != 8)
5400 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005401 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005402 return false;
5403 }
5404 break;
5405
5406 case GL_PACK_ALIGNMENT:
5407 if (param != 1 && param != 2 && param != 4 && param != 8)
5408 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005409 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005410 return false;
5411 }
5412 break;
5413
5414 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005415 if (!context->getExtensions().packReverseRowOrder)
5416 {
5417 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5418 }
5419 break;
5420
Jamie Madillc1d770e2017-04-13 17:31:24 -04005421 case GL_UNPACK_ROW_LENGTH:
5422 case GL_UNPACK_IMAGE_HEIGHT:
5423 case GL_UNPACK_SKIP_IMAGES:
5424 case GL_UNPACK_SKIP_ROWS:
5425 case GL_UNPACK_SKIP_PIXELS:
5426 case GL_PACK_ROW_LENGTH:
5427 case GL_PACK_SKIP_ROWS:
5428 case GL_PACK_SKIP_PIXELS:
5429 break;
5430
5431 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005433 return false;
5434 }
5435
5436 return true;
5437}
5438
5439bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5440{
5441 return true;
5442}
5443
5444bool ValidateReleaseShaderCompiler(ValidationContext *context)
5445{
5446 return true;
5447}
5448
Jamie Madill876429b2017-04-20 15:46:24 -04005449bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005450{
5451 return true;
5452}
5453
5454bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5455{
5456 if (width < 0 || height < 0)
5457 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005458 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005459 return false;
5460 }
5461
5462 return true;
5463}
5464
5465bool ValidateShaderBinary(ValidationContext *context,
5466 GLsizei n,
5467 const GLuint *shaders,
5468 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005469 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005470 GLsizei length)
5471{
5472 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5473 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5474 shaderBinaryFormats.end())
5475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005476 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005477 return false;
5478 }
5479
5480 return true;
5481}
5482
5483bool ValidateShaderSource(ValidationContext *context,
5484 GLuint shader,
5485 GLsizei count,
5486 const GLchar *const *string,
5487 const GLint *length)
5488{
5489 if (count < 0)
5490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005492 return false;
5493 }
5494
Geoff Langfc32e8b2017-05-31 14:16:59 -04005495 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5496 // shader-related entry points
5497 if (context->getExtensions().webglCompatibility)
5498 {
5499 for (GLsizei i = 0; i < count; i++)
5500 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005501 size_t len =
5502 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005503
5504 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005505 if (!IsValidESSLShaderSourceString(string[i], len,
5506 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005507 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005508 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005509 return false;
5510 }
5511 }
5512 }
5513
Jamie Madillc1d770e2017-04-13 17:31:24 -04005514 Shader *shaderObject = GetValidShader(context, shader);
5515 if (!shaderObject)
5516 {
5517 return false;
5518 }
5519
5520 return true;
5521}
5522
5523bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5524{
5525 if (!IsValidStencilFunc(func))
5526 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005527 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005528 return false;
5529 }
5530
5531 return true;
5532}
5533
5534bool ValidateStencilFuncSeparate(ValidationContext *context,
5535 GLenum face,
5536 GLenum func,
5537 GLint ref,
5538 GLuint mask)
5539{
5540 if (!IsValidStencilFace(face))
5541 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005543 return false;
5544 }
5545
5546 if (!IsValidStencilFunc(func))
5547 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005549 return false;
5550 }
5551
5552 return true;
5553}
5554
5555bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5556{
5557 return true;
5558}
5559
5560bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5561{
5562 if (!IsValidStencilFace(face))
5563 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005564 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005565 return false;
5566 }
5567
5568 return true;
5569}
5570
5571bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5572{
5573 if (!IsValidStencilOp(fail))
5574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005576 return false;
5577 }
5578
5579 if (!IsValidStencilOp(zfail))
5580 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005582 return false;
5583 }
5584
5585 if (!IsValidStencilOp(zpass))
5586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005588 return false;
5589 }
5590
5591 return true;
5592}
5593
5594bool ValidateStencilOpSeparate(ValidationContext *context,
5595 GLenum face,
5596 GLenum fail,
5597 GLenum zfail,
5598 GLenum zpass)
5599{
5600 if (!IsValidStencilFace(face))
5601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005602 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005603 return false;
5604 }
5605
5606 return ValidateStencilOp(context, fail, zfail, zpass);
5607}
5608
5609bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5610{
5611 return ValidateUniform(context, GL_FLOAT, location, 1);
5612}
5613
5614bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5615{
5616 return ValidateUniform(context, GL_FLOAT, location, count);
5617}
5618
Jamie Madillbe849e42017-05-02 15:49:00 -04005619bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5620{
5621 return ValidateUniform1iv(context, location, 1, &x);
5622}
5623
Jamie Madillc1d770e2017-04-13 17:31:24 -04005624bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5625{
5626 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5627}
5628
5629bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5630{
5631 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5632}
5633
5634bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5635{
5636 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5637}
5638
5639bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5640{
5641 return ValidateUniform(context, GL_INT_VEC2, location, count);
5642}
5643
5644bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5645{
5646 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5647}
5648
5649bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5650{
5651 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5652}
5653
5654bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5655{
5656 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5657}
5658
5659bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5660{
5661 return ValidateUniform(context, GL_INT_VEC3, location, count);
5662}
5663
5664bool ValidateUniform4f(ValidationContext *context,
5665 GLint location,
5666 GLfloat x,
5667 GLfloat y,
5668 GLfloat z,
5669 GLfloat w)
5670{
5671 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5672}
5673
5674bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5675{
5676 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5677}
5678
5679bool ValidateUniform4i(ValidationContext *context,
5680 GLint location,
5681 GLint x,
5682 GLint y,
5683 GLint z,
5684 GLint w)
5685{
5686 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5687}
5688
5689bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5690{
5691 return ValidateUniform(context, GL_INT_VEC4, location, count);
5692}
5693
5694bool ValidateUniformMatrix2fv(ValidationContext *context,
5695 GLint location,
5696 GLsizei count,
5697 GLboolean transpose,
5698 const GLfloat *value)
5699{
5700 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5701}
5702
5703bool ValidateUniformMatrix3fv(ValidationContext *context,
5704 GLint location,
5705 GLsizei count,
5706 GLboolean transpose,
5707 const GLfloat *value)
5708{
5709 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5710}
5711
5712bool ValidateUniformMatrix4fv(ValidationContext *context,
5713 GLint location,
5714 GLsizei count,
5715 GLboolean transpose,
5716 const GLfloat *value)
5717{
5718 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5719}
5720
5721bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5722{
5723 Program *programObject = GetValidProgram(context, program);
5724
5725 if (!programObject)
5726 {
5727 return false;
5728 }
5729
5730 return true;
5731}
5732
Jamie Madillc1d770e2017-04-13 17:31:24 -04005733bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5734{
5735 return ValidateVertexAttribIndex(context, index);
5736}
5737
5738bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5739{
5740 return ValidateVertexAttribIndex(context, index);
5741}
5742
5743bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5744{
5745 return ValidateVertexAttribIndex(context, index);
5746}
5747
5748bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5749{
5750 return ValidateVertexAttribIndex(context, index);
5751}
5752
5753bool ValidateVertexAttrib3f(ValidationContext *context,
5754 GLuint index,
5755 GLfloat x,
5756 GLfloat y,
5757 GLfloat z)
5758{
5759 return ValidateVertexAttribIndex(context, index);
5760}
5761
5762bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5763{
5764 return ValidateVertexAttribIndex(context, index);
5765}
5766
5767bool ValidateVertexAttrib4f(ValidationContext *context,
5768 GLuint index,
5769 GLfloat x,
5770 GLfloat y,
5771 GLfloat z,
5772 GLfloat w)
5773{
5774 return ValidateVertexAttribIndex(context, index);
5775}
5776
5777bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5778{
5779 return ValidateVertexAttribIndex(context, index);
5780}
5781
5782bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5783{
5784 if (width < 0 || height < 0)
5785 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005786 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005787 return false;
5788 }
5789
5790 return true;
5791}
5792
5793bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5794{
5795 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5796}
5797
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005798bool ValidateDrawElements(ValidationContext *context,
5799 GLenum mode,
5800 GLsizei count,
5801 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005802 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005803{
5804 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5805}
5806
Jamie Madillbe849e42017-05-02 15:49:00 -04005807bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5808 GLenum target,
5809 GLenum attachment,
5810 GLenum pname,
5811 GLint *params)
5812{
5813 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5814 nullptr);
5815}
5816
5817bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5818{
5819 return ValidateGetProgramivBase(context, program, pname, nullptr);
5820}
5821
5822bool ValidateCopyTexImage2D(ValidationContext *context,
5823 GLenum target,
5824 GLint level,
5825 GLenum internalformat,
5826 GLint x,
5827 GLint y,
5828 GLsizei width,
5829 GLsizei height,
5830 GLint border)
5831{
5832 if (context->getClientMajorVersion() < 3)
5833 {
5834 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5835 0, x, y, width, height, border);
5836 }
5837
5838 ASSERT(context->getClientMajorVersion() == 3);
5839 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5840 0, x, y, width, height, border);
5841}
5842
5843bool ValidateCopyTexSubImage2D(Context *context,
5844 GLenum target,
5845 GLint level,
5846 GLint xoffset,
5847 GLint yoffset,
5848 GLint x,
5849 GLint y,
5850 GLsizei width,
5851 GLsizei height)
5852{
5853 if (context->getClientMajorVersion() < 3)
5854 {
5855 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5856 yoffset, x, y, width, height, 0);
5857 }
5858
5859 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5860 yoffset, 0, x, y, width, height, 0);
5861}
5862
5863bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5864{
5865 return ValidateGenOrDelete(context, n);
5866}
5867
5868bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5869{
5870 return ValidateGenOrDelete(context, n);
5871}
5872
5873bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5874{
5875 return ValidateGenOrDelete(context, n);
5876}
5877
5878bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5879{
5880 return ValidateGenOrDelete(context, n);
5881}
5882
5883bool ValidateDisable(Context *context, GLenum cap)
5884{
5885 if (!ValidCap(context, cap, false))
5886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 return false;
5889 }
5890
5891 return true;
5892}
5893
5894bool ValidateEnable(Context *context, GLenum cap)
5895{
5896 if (!ValidCap(context, cap, false))
5897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 return false;
5900 }
5901
5902 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5903 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5904 {
5905 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005906 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005907
5908 // We also output an error message to the debugger window if tracing is active, so that
5909 // developers can see the error message.
5910 ERR() << errorMessage;
5911 return false;
5912 }
5913
5914 return true;
5915}
5916
5917bool ValidateFramebufferRenderbuffer(Context *context,
5918 GLenum target,
5919 GLenum attachment,
5920 GLenum renderbuffertarget,
5921 GLuint renderbuffer)
5922{
Brandon Jones6cad5662017-06-14 13:25:13 -07005923 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5926 return false;
5927 }
5928
5929 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5930 {
5931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 return false;
5933 }
5934
5935 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5936 renderbuffertarget, renderbuffer);
5937}
5938
5939bool ValidateFramebufferTexture2D(Context *context,
5940 GLenum target,
5941 GLenum attachment,
5942 GLenum textarget,
5943 GLuint texture,
5944 GLint level)
5945{
5946 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5947 // extension
5948 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5949 level != 0)
5950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005951 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 return false;
5953 }
5954
5955 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5956 {
5957 return false;
5958 }
5959
5960 if (texture != 0)
5961 {
5962 gl::Texture *tex = context->getTexture(texture);
5963 ASSERT(tex);
5964
5965 const gl::Caps &caps = context->getCaps();
5966
5967 switch (textarget)
5968 {
5969 case GL_TEXTURE_2D:
5970 {
5971 if (level > gl::log2(caps.max2DTextureSize))
5972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005973 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005974 return false;
5975 }
5976 if (tex->getTarget() != GL_TEXTURE_2D)
5977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005979 return false;
5980 }
5981 }
5982 break;
5983
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005984 case GL_TEXTURE_RECTANGLE_ANGLE:
5985 {
5986 if (level != 0)
5987 {
5988 context->handleError(InvalidValue());
5989 return false;
5990 }
5991 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5992 {
5993 context->handleError(InvalidOperation()
5994 << "Textarget must match the texture target type.");
5995 return false;
5996 }
5997 }
5998 break;
5999
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
6001 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
6002 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
6003 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
6004 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
6005 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
6006 {
6007 if (level > gl::log2(caps.maxCubeMapTextureSize))
6008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006009 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04006010 return false;
6011 }
6012 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
6013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006014 context->handleError(InvalidOperation()
6015 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006016 return false;
6017 }
6018 }
6019 break;
6020
6021 case GL_TEXTURE_2D_MULTISAMPLE:
6022 {
6023 if (context->getClientVersion() < ES_3_1)
6024 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04006026 return false;
6027 }
6028
6029 if (level != 0)
6030 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006031 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04006032 return false;
6033 }
6034 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
6035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006036 context->handleError(InvalidOperation()
6037 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006038 return false;
6039 }
6040 }
6041 break;
6042
6043 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006044 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006045 return false;
6046 }
6047
6048 const Format &format = tex->getFormat(textarget, level);
6049 if (format.info->compressed)
6050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006051 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006052 return false;
6053 }
6054 }
6055
6056 return true;
6057}
6058
6059bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6060{
6061 return ValidateGenOrDelete(context, n);
6062}
6063
6064bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6065{
6066 return ValidateGenOrDelete(context, n);
6067}
6068
6069bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6070{
6071 return ValidateGenOrDelete(context, n);
6072}
6073
6074bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6075{
6076 return ValidateGenOrDelete(context, n);
6077}
6078
6079bool ValidateGenerateMipmap(Context *context, GLenum target)
6080{
6081 if (!ValidTextureTarget(context, target))
6082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006084 return false;
6085 }
6086
6087 Texture *texture = context->getTargetTexture(target);
6088
6089 if (texture == nullptr)
6090 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006092 return false;
6093 }
6094
6095 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6096
6097 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6098 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6099 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006101 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006102 return false;
6103 }
6104
6105 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006106 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6107 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6108 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006109 {
6110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6111 return false;
6112 }
6113
Geoff Lang536eca12017-09-13 11:23:35 -04006114 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6115 bool formatUnsized = !format.sized;
6116 bool formatColorRenderableAndFilterable =
6117 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6118 format.renderSupport(context->getClientVersion(), context->getExtensions());
6119 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006120 {
Geoff Lang536eca12017-09-13 11:23:35 -04006121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006122 return false;
6123 }
6124
Geoff Lang536eca12017-09-13 11:23:35 -04006125 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6126 // generation
6127 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6128 {
6129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6130 return false;
6131 }
6132
6133 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6134 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006135 bool supportsSRGBMipmapGeneration =
6136 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006137 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006138 {
Geoff Lang536eca12017-09-13 11:23:35 -04006139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006140 return false;
6141 }
6142
6143 // Non-power of 2 ES2 check
6144 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6145 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6146 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6147 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006148 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6149 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006151 return false;
6152 }
6153
6154 // Cube completeness check
6155 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006158 return false;
6159 }
6160
6161 return true;
6162}
6163
6164bool ValidateGetBufferParameteriv(ValidationContext *context,
6165 GLenum target,
6166 GLenum pname,
6167 GLint *params)
6168{
6169 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6170}
6171
6172bool ValidateGetRenderbufferParameteriv(Context *context,
6173 GLenum target,
6174 GLenum pname,
6175 GLint *params)
6176{
6177 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6178}
6179
6180bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6181{
6182 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6183}
6184
6185bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6186{
6187 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6188}
6189
6190bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6191{
6192 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6193}
6194
6195bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6196{
6197 return ValidateGetUniformBase(context, program, location);
6198}
6199
6200bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6201{
6202 return ValidateGetUniformBase(context, program, location);
6203}
6204
6205bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6206{
6207 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6208}
6209
6210bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6211{
6212 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6213}
6214
6215bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6216{
6217 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6218}
6219
6220bool ValidateIsEnabled(Context *context, GLenum cap)
6221{
6222 if (!ValidCap(context, cap, true))
6223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006225 return false;
6226 }
6227
6228 return true;
6229}
6230
6231bool ValidateLinkProgram(Context *context, GLuint program)
6232{
6233 if (context->hasActiveTransformFeedback(program))
6234 {
6235 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006236 context->handleError(InvalidOperation() << "Cannot link program while program is "
6237 "associated with an active transform "
6238 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006239 return false;
6240 }
6241
6242 Program *programObject = GetValidProgram(context, program);
6243 if (!programObject)
6244 {
6245 return false;
6246 }
6247
6248 return true;
6249}
6250
Jamie Madill4928b7c2017-06-20 12:57:39 -04006251bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006252 GLint x,
6253 GLint y,
6254 GLsizei width,
6255 GLsizei height,
6256 GLenum format,
6257 GLenum type,
6258 void *pixels)
6259{
6260 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6261 nullptr, pixels);
6262}
6263
6264bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6265{
6266 return ValidateTexParameterBase(context, target, pname, -1, &param);
6267}
6268
6269bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6270{
6271 return ValidateTexParameterBase(context, target, pname, -1, params);
6272}
6273
6274bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6275{
6276 return ValidateTexParameterBase(context, target, pname, -1, &param);
6277}
6278
6279bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6280{
6281 return ValidateTexParameterBase(context, target, pname, -1, params);
6282}
6283
6284bool ValidateUseProgram(Context *context, GLuint program)
6285{
6286 if (program != 0)
6287 {
6288 Program *programObject = context->getProgram(program);
6289 if (!programObject)
6290 {
6291 // ES 3.1.0 section 7.3 page 72
6292 if (context->getShader(program))
6293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006295 return false;
6296 }
6297 else
6298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006299 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006300 return false;
6301 }
6302 }
6303 if (!programObject->isLinked())
6304 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006306 return false;
6307 }
6308 }
6309 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6310 {
6311 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006312 context
6313 ->handleError(InvalidOperation()
6314 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006315 return false;
6316 }
6317
6318 return true;
6319}
6320
Jamie Madillc29968b2016-01-20 11:17:23 -05006321} // namespace gl