blob: 7737131414ea4de0cfe0268b272ea29146d4ed5c [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 }
Geoff Langfb052642017-10-24 13:42:09 -04001143
1144 if (width > 0 && height > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -04001145 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -04001146 {
1147 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
1148 return false;
1149 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001150 }
1151 else
1152 {
Geoff Lang69cce582015-09-17 13:20:36 -04001153 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001155 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001156 return false;
1157 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
1160 // Verify zero border
1161 if (border != 0)
1162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001163 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 }
1166
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 if (isCompressed)
1168 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001169 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001170 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1171 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 switch (actualInternalFormat)
1173 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001174 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1175 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1176 if (!context->getExtensions().textureCompressionDXT1)
1177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001179 return false;
1180 }
1181 break;
1182 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Lang86f81162017-10-30 15:10:45 -04001183 if (!context->getExtensions().textureCompressionDXT3)
He Yunchaoced53ae2016-11-29 15:00:51 +08001184 {
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;
1189 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1190 if (!context->getExtensions().textureCompressionDXT5)
1191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001193 return false;
1194 }
1195 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001196 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1197 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1198 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1199 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1200 if (!context->getExtensions().textureCompressionS3TCsRGB)
1201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001203 return false;
1204 }
1205 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 case GL_ETC1_RGB8_OES:
1207 if (!context->getExtensions().compressedETC1RGB8Texture)
1208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
1211 }
Geoff Lang86f81162017-10-30 15:10:45 -04001212 if (isSubImage)
1213 {
1214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
1215 return false;
1216 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 break;
1218 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001219 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1220 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1221 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1222 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001223 if (!context->getExtensions().lossyETCDecode)
1224 {
Geoff Lang86f81162017-10-30 15:10:45 -04001225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001226 return false;
1227 }
1228 break;
1229 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001230 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001232 }
Geoff Lang966c9402017-04-18 12:38:27 -04001233
1234 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001235 {
Geoff Lang966c9402017-04-18 12:38:27 -04001236 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1237 height, texture->getWidth(target, level),
1238 texture->getHeight(target, level)))
1239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001240 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001241 return false;
1242 }
1243
1244 if (format != actualInternalFormat)
1245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001247 return false;
1248 }
1249 }
1250 else
1251 {
1252 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001255 return false;
1256 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258 }
1259 else
1260 {
1261 // validate <type> by itself (used as secondary key below)
1262 switch (type)
1263 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001264 case GL_UNSIGNED_BYTE:
1265 case GL_UNSIGNED_SHORT_5_6_5:
1266 case GL_UNSIGNED_SHORT_4_4_4_4:
1267 case GL_UNSIGNED_SHORT_5_5_5_1:
1268 case GL_UNSIGNED_SHORT:
1269 case GL_UNSIGNED_INT:
1270 case GL_UNSIGNED_INT_24_8_OES:
1271 case GL_HALF_FLOAT_OES:
1272 case GL_FLOAT:
1273 break;
1274 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001276 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 }
1278
1279 // validate <format> + <type> combinations
1280 // - invalid <format> -> sets INVALID_ENUM
1281 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1282 switch (format)
1283 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001284 case GL_ALPHA:
1285 case GL_LUMINANCE:
1286 case GL_LUMINANCE_ALPHA:
1287 switch (type)
1288 {
1289 case GL_UNSIGNED_BYTE:
1290 case GL_FLOAT:
1291 case GL_HALF_FLOAT_OES:
1292 break;
1293 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001295 return false;
1296 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001298 case GL_RED:
1299 case GL_RG:
1300 if (!context->getExtensions().textureRG)
1301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001302 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001303 return false;
1304 }
1305 switch (type)
1306 {
1307 case GL_UNSIGNED_BYTE:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001308 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001309 case GL_FLOAT:
1310 case GL_HALF_FLOAT_OES:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001311 if (!context->getExtensions().textureFloat)
1312 {
1313 context->handleError(InvalidEnum());
1314 return false;
1315 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001316 break;
1317 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001319 return false;
1320 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001322 case GL_RGB:
1323 switch (type)
1324 {
1325 case GL_UNSIGNED_BYTE:
1326 case GL_UNSIGNED_SHORT_5_6_5:
1327 case GL_FLOAT:
1328 case GL_HALF_FLOAT_OES:
1329 break;
1330 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001332 return false;
1333 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 case GL_RGBA:
1336 switch (type)
1337 {
1338 case GL_UNSIGNED_BYTE:
1339 case GL_UNSIGNED_SHORT_4_4_4_4:
1340 case GL_UNSIGNED_SHORT_5_5_5_1:
1341 case GL_FLOAT:
1342 case GL_HALF_FLOAT_OES:
1343 break;
1344 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001345 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001346 return false;
1347 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001349 case GL_BGRA_EXT:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001350 if (!context->getExtensions().textureFormatBGRA8888)
1351 {
1352 context->handleError(InvalidEnum());
1353 return false;
1354 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001355 switch (type)
1356 {
1357 case GL_UNSIGNED_BYTE:
1358 break;
1359 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001360 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001361 return false;
1362 }
1363 break;
1364 case GL_SRGB_EXT:
1365 case GL_SRGB_ALPHA_EXT:
1366 if (!context->getExtensions().sRGB)
1367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001369 return false;
1370 }
1371 switch (type)
1372 {
1373 case GL_UNSIGNED_BYTE:
1374 break;
1375 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001376 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001377 return false;
1378 }
1379 break;
1380 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1381 // handled below
1382 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1383 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1384 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1385 break;
1386 case GL_DEPTH_COMPONENT:
1387 switch (type)
1388 {
1389 case GL_UNSIGNED_SHORT:
1390 case GL_UNSIGNED_INT:
1391 break;
1392 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001394 return false;
1395 }
1396 break;
1397 case GL_DEPTH_STENCIL_OES:
1398 switch (type)
1399 {
1400 case GL_UNSIGNED_INT_24_8_OES:
1401 break;
1402 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 return false;
1405 }
1406 break;
1407 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001408 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001409 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 }
1411
1412 switch (format)
1413 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001414 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1415 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1416 if (context->getExtensions().textureCompressionDXT1)
1417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001418 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 return false;
1420 }
1421 else
1422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001424 return false;
1425 }
1426 break;
1427 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1428 if (context->getExtensions().textureCompressionDXT3)
1429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001431 return false;
1432 }
1433 else
1434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001435 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001436 return false;
1437 }
1438 break;
1439 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1440 if (context->getExtensions().textureCompressionDXT5)
1441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001442 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001443 return false;
1444 }
1445 else
1446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001447 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 return false;
1449 }
1450 break;
1451 case GL_ETC1_RGB8_OES:
1452 if (context->getExtensions().compressedETC1RGB8Texture)
1453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001454 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001455 return false;
1456 }
1457 else
1458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001459 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 return false;
1461 }
1462 break;
1463 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001464 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1465 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1466 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1467 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001468 if (context->getExtensions().lossyETCDecode)
1469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001470 context->handleError(InvalidOperation()
1471 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 else
1475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001476 context->handleError(InvalidEnum()
1477 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
1479 }
1480 break;
1481 case GL_DEPTH_COMPONENT:
1482 case GL_DEPTH_STENCIL_OES:
1483 if (!context->getExtensions().depthTextures)
1484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 return false;
1487 }
1488 if (target != GL_TEXTURE_2D)
1489 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001491 return false;
1492 }
1493 // OES_depth_texture supports loading depth data and multiple levels,
1494 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001495 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001496 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1498 return false;
1499 }
1500 if (level != 0)
1501 {
1502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001503 return false;
1504 }
1505 break;
1506 default:
1507 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508 }
1509
Geoff Lang6e898aa2017-06-02 11:17:26 -04001510 if (!isSubImage)
1511 {
1512 switch (internalformat)
1513 {
1514 case GL_RGBA32F:
1515 if (!context->getExtensions().colorBufferFloatRGBA)
1516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidValue()
1518 << "Sized GL_RGBA32F internal format requires "
1519 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001520 return false;
1521 }
1522 if (type != GL_FLOAT)
1523 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001525 return false;
1526 }
1527 if (format != GL_RGBA)
1528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001530 return false;
1531 }
1532 break;
1533
1534 case GL_RGB32F:
1535 if (!context->getExtensions().colorBufferFloatRGB)
1536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001537 context->handleError(InvalidValue()
1538 << "Sized GL_RGB32F internal format requires "
1539 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001540 return false;
1541 }
1542 if (type != GL_FLOAT)
1543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001544 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001545 return false;
1546 }
1547 if (format != GL_RGB)
1548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001550 return false;
1551 }
1552 break;
1553
1554 default:
1555 break;
1556 }
1557 }
1558
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001559 if (type == GL_FLOAT)
1560 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001561 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001564 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001565 }
1566 }
1567 else if (type == GL_HALF_FLOAT_OES)
1568 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001569 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001571 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001572 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001573 }
1574 }
1575 }
1576
Geoff Langdbcced82017-06-06 15:55:54 -04001577 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1578 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001579 imageSize))
1580 {
1581 return false;
1582 }
1583
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001584 return true;
1585}
1586
He Yunchaoced53ae2016-11-29 15:00:51 +08001587bool ValidateES2TexStorageParameters(Context *context,
1588 GLenum target,
1589 GLsizei levels,
1590 GLenum internalformat,
1591 GLsizei width,
1592 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001593{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001594 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1595 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001598 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001599 }
1600
1601 if (width < 1 || height < 1 || levels < 1)
1602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001603 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001604 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001605 }
1606
1607 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001611 }
1612
1613 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001616 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001617 }
1618
Geoff Langca271392017-04-05 12:30:00 -04001619 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001620 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001622 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001623 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001624 }
1625
Geoff Langaae65a42014-05-26 12:43:44 -04001626 const gl::Caps &caps = context->getCaps();
1627
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001628 switch (target)
1629 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001630 case GL_TEXTURE_2D:
1631 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1632 static_cast<GLuint>(height) > caps.max2DTextureSize)
1633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001634 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001635 return false;
1636 }
1637 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001638 case GL_TEXTURE_RECTANGLE_ANGLE:
1639 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1640 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1641 {
1642 context->handleError(InvalidValue());
1643 return false;
1644 }
1645 if (formatInfo.compressed)
1646 {
1647 context->handleError(InvalidEnum()
1648 << "Rectangle texture cannot have a compressed format.");
1649 return false;
1650 }
1651 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001652 case GL_TEXTURE_CUBE_MAP:
1653 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1654 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001657 return false;
1658 }
1659 break;
1660 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001661 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001662 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663 }
1664
Geoff Langc0b9ef42014-07-02 10:02:37 -04001665 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001666 {
1667 if (!gl::isPow2(width) || !gl::isPow2(height))
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001670 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 }
1672 }
1673
1674 switch (internalformat)
1675 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001676 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1677 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1678 if (!context->getExtensions().textureCompressionDXT1)
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_DXT3_ANGLE:
1685 if (!context->getExtensions().textureCompressionDXT3)
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_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1692 if (!context->getExtensions().textureCompressionDXT5)
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_OES:
1699 if (!context->getExtensions().compressedETC1RGB8Texture)
1700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001701 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001702 return false;
1703 }
1704 break;
1705 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001706 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1707 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1708 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1709 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001710 if (!context->getExtensions().lossyETCDecode)
1711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001712 context->handleError(InvalidEnum()
1713 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001714 return false;
1715 }
1716 break;
1717 case GL_RGBA32F_EXT:
1718 case GL_RGB32F_EXT:
1719 case GL_ALPHA32F_EXT:
1720 case GL_LUMINANCE32F_EXT:
1721 case GL_LUMINANCE_ALPHA32F_EXT:
1722 if (!context->getExtensions().textureFloat)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001725 return false;
1726 }
1727 break;
1728 case GL_RGBA16F_EXT:
1729 case GL_RGB16F_EXT:
1730 case GL_ALPHA16F_EXT:
1731 case GL_LUMINANCE16F_EXT:
1732 case GL_LUMINANCE_ALPHA16F_EXT:
1733 if (!context->getExtensions().textureHalfFloat)
1734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001735 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001736 return false;
1737 }
1738 break;
1739 case GL_R8_EXT:
1740 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001741 if (!context->getExtensions().textureRG)
1742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001744 return false;
1745 }
1746 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001747 case GL_R16F_EXT:
1748 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001749 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001751 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001752 return false;
1753 }
1754 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001755 case GL_R32F_EXT:
1756 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001757 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001759 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001760 return false;
1761 }
1762 break;
1763 case GL_DEPTH_COMPONENT16:
1764 case GL_DEPTH_COMPONENT32_OES:
1765 case GL_DEPTH24_STENCIL8_OES:
1766 if (!context->getExtensions().depthTextures)
1767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001768 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001769 return false;
1770 }
1771 if (target != GL_TEXTURE_2D)
1772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001773 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001774 return false;
1775 }
1776 // ANGLE_depth_texture only supports 1-level textures
1777 if (levels != 1)
1778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001779 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001780 return false;
1781 }
1782 break;
1783 default:
1784 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001785 }
1786
Geoff Lang691e58c2014-12-19 17:03:25 -05001787 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001788 if (!texture || texture->id() == 0)
1789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001790 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001791 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 }
1793
Geoff Lang69cce582015-09-17 13:20:36 -04001794 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001796 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001797 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001798 }
1799
1800 return true;
1801}
1802
He Yunchaoced53ae2016-11-29 15:00:51 +08001803bool ValidateDiscardFramebufferEXT(Context *context,
1804 GLenum target,
1805 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001806 const GLenum *attachments)
1807{
Jamie Madillc29968b2016-01-20 11:17:23 -05001808 if (!context->getExtensions().discardFramebuffer)
1809 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001811 return false;
1812 }
1813
Austin Kinross08332632015-05-05 13:35:47 -07001814 bool defaultFramebuffer = false;
1815
1816 switch (target)
1817 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001818 case GL_FRAMEBUFFER:
1819 defaultFramebuffer =
1820 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1821 break;
1822 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001824 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001825 }
1826
He Yunchaoced53ae2016-11-29 15:00:51 +08001827 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1828 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001829}
1830
Austin Kinrossbc781f32015-10-26 09:27:38 -07001831bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1832{
1833 if (!context->getExtensions().vertexArrayObject)
1834 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001836 return false;
1837 }
1838
1839 return ValidateBindVertexArrayBase(context, array);
1840}
1841
Jamie Madilld7576732017-08-26 18:49:50 -04001842bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001843{
1844 if (!context->getExtensions().vertexArrayObject)
1845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001846 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001847 return false;
1848 }
1849
Olli Etuaho41997e72016-03-10 13:38:39 +02001850 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001851}
1852
Jamie Madilld7576732017-08-26 18:49:50 -04001853bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001854{
1855 if (!context->getExtensions().vertexArrayObject)
1856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001858 return false;
1859 }
1860
Olli Etuaho41997e72016-03-10 13:38:39 +02001861 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001862}
1863
Jamie Madilld7576732017-08-26 18:49:50 -04001864bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001865{
1866 if (!context->getExtensions().vertexArrayObject)
1867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001869 return false;
1870 }
1871
1872 return true;
1873}
Geoff Langc5629752015-12-07 16:29:04 -05001874
1875bool ValidateProgramBinaryOES(Context *context,
1876 GLuint program,
1877 GLenum binaryFormat,
1878 const void *binary,
1879 GLint length)
1880{
1881 if (!context->getExtensions().getProgramBinary)
1882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001883 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001884 return false;
1885 }
1886
1887 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1888}
1889
1890bool ValidateGetProgramBinaryOES(Context *context,
1891 GLuint program,
1892 GLsizei bufSize,
1893 GLsizei *length,
1894 GLenum *binaryFormat,
1895 void *binary)
1896{
1897 if (!context->getExtensions().getProgramBinary)
1898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001900 return false;
1901 }
1902
1903 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1904}
Geoff Lange102fee2015-12-10 11:23:30 -05001905
Geoff Lang70d0f492015-12-10 17:45:46 -05001906static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1907{
1908 switch (source)
1909 {
1910 case GL_DEBUG_SOURCE_API:
1911 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1912 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1913 case GL_DEBUG_SOURCE_OTHER:
1914 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1915 return !mustBeThirdPartyOrApplication;
1916
1917 case GL_DEBUG_SOURCE_THIRD_PARTY:
1918 case GL_DEBUG_SOURCE_APPLICATION:
1919 return true;
1920
1921 default:
1922 return false;
1923 }
1924}
1925
1926static bool ValidDebugType(GLenum type)
1927{
1928 switch (type)
1929 {
1930 case GL_DEBUG_TYPE_ERROR:
1931 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1932 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1933 case GL_DEBUG_TYPE_PERFORMANCE:
1934 case GL_DEBUG_TYPE_PORTABILITY:
1935 case GL_DEBUG_TYPE_OTHER:
1936 case GL_DEBUG_TYPE_MARKER:
1937 case GL_DEBUG_TYPE_PUSH_GROUP:
1938 case GL_DEBUG_TYPE_POP_GROUP:
1939 return true;
1940
1941 default:
1942 return false;
1943 }
1944}
1945
1946static bool ValidDebugSeverity(GLenum severity)
1947{
1948 switch (severity)
1949 {
1950 case GL_DEBUG_SEVERITY_HIGH:
1951 case GL_DEBUG_SEVERITY_MEDIUM:
1952 case GL_DEBUG_SEVERITY_LOW:
1953 case GL_DEBUG_SEVERITY_NOTIFICATION:
1954 return true;
1955
1956 default:
1957 return false;
1958 }
1959}
1960
Geoff Lange102fee2015-12-10 11:23:30 -05001961bool ValidateDebugMessageControlKHR(Context *context,
1962 GLenum source,
1963 GLenum type,
1964 GLenum severity,
1965 GLsizei count,
1966 const GLuint *ids,
1967 GLboolean enabled)
1968{
1969 if (!context->getExtensions().debug)
1970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001971 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001972 return false;
1973 }
1974
Geoff Lang70d0f492015-12-10 17:45:46 -05001975 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1976 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001977 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001978 return false;
1979 }
1980
1981 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1982 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001983 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001984 return false;
1985 }
1986
1987 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1988 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001989 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001990 return false;
1991 }
1992
1993 if (count > 0)
1994 {
1995 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001997 context->handleError(
1998 InvalidOperation()
1999 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002000 return false;
2001 }
2002
2003 if (severity != GL_DONT_CARE)
2004 {
Jamie Madill437fa652016-05-03 15:13:24 -04002005 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002006 InvalidOperation()
2007 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002008 return false;
2009 }
2010 }
2011
Geoff Lange102fee2015-12-10 11:23:30 -05002012 return true;
2013}
2014
2015bool ValidateDebugMessageInsertKHR(Context *context,
2016 GLenum source,
2017 GLenum type,
2018 GLuint id,
2019 GLenum severity,
2020 GLsizei length,
2021 const GLchar *buf)
2022{
2023 if (!context->getExtensions().debug)
2024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002026 return false;
2027 }
2028
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002029 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05002030 {
2031 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2032 // not generate an error.
2033 return false;
2034 }
2035
2036 if (!ValidDebugSeverity(severity))
2037 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002038 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002039 return false;
2040 }
2041
2042 if (!ValidDebugType(type))
2043 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002044 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05002045 return false;
2046 }
2047
2048 if (!ValidDebugSource(source, true))
2049 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002050 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002051 return false;
2052 }
2053
2054 size_t messageLength = (length < 0) ? strlen(buf) : length;
2055 if (messageLength > context->getExtensions().maxDebugMessageLength)
2056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidValue()
2058 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002059 return false;
2060 }
2061
Geoff Lange102fee2015-12-10 11:23:30 -05002062 return true;
2063}
2064
2065bool ValidateDebugMessageCallbackKHR(Context *context,
2066 GLDEBUGPROCKHR callback,
2067 const void *userParam)
2068{
2069 if (!context->getExtensions().debug)
2070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002072 return false;
2073 }
2074
Geoff Lange102fee2015-12-10 11:23:30 -05002075 return true;
2076}
2077
2078bool ValidateGetDebugMessageLogKHR(Context *context,
2079 GLuint count,
2080 GLsizei bufSize,
2081 GLenum *sources,
2082 GLenum *types,
2083 GLuint *ids,
2084 GLenum *severities,
2085 GLsizei *lengths,
2086 GLchar *messageLog)
2087{
2088 if (!context->getExtensions().debug)
2089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002090 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002091 return false;
2092 }
2093
Geoff Lang70d0f492015-12-10 17:45:46 -05002094 if (bufSize < 0 && messageLog != nullptr)
2095 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002096 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002097 return false;
2098 }
2099
Geoff Lange102fee2015-12-10 11:23:30 -05002100 return true;
2101}
2102
2103bool ValidatePushDebugGroupKHR(Context *context,
2104 GLenum source,
2105 GLuint id,
2106 GLsizei length,
2107 const GLchar *message)
2108{
2109 if (!context->getExtensions().debug)
2110 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002112 return false;
2113 }
2114
Geoff Lang70d0f492015-12-10 17:45:46 -05002115 if (!ValidDebugSource(source, true))
2116 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002118 return false;
2119 }
2120
2121 size_t messageLength = (length < 0) ? strlen(message) : length;
2122 if (messageLength > context->getExtensions().maxDebugMessageLength)
2123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002124 context->handleError(InvalidValue()
2125 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002126 return false;
2127 }
2128
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002129 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002130 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002132 context
2133 ->handleError(StackOverflow()
2134 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002135 return false;
2136 }
2137
Geoff Lange102fee2015-12-10 11:23:30 -05002138 return true;
2139}
2140
2141bool ValidatePopDebugGroupKHR(Context *context)
2142{
2143 if (!context->getExtensions().debug)
2144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002146 return false;
2147 }
2148
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002149 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002150 if (currentStackSize <= 1)
2151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002152 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002153 return false;
2154 }
2155
2156 return true;
2157}
2158
2159static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2160{
2161 switch (identifier)
2162 {
2163 case GL_BUFFER:
2164 if (context->getBuffer(name) == nullptr)
2165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002166 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002167 return false;
2168 }
2169 return true;
2170
2171 case GL_SHADER:
2172 if (context->getShader(name) == nullptr)
2173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002175 return false;
2176 }
2177 return true;
2178
2179 case GL_PROGRAM:
2180 if (context->getProgram(name) == nullptr)
2181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002182 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002183 return false;
2184 }
2185 return true;
2186
2187 case GL_VERTEX_ARRAY:
2188 if (context->getVertexArray(name) == nullptr)
2189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002190 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002191 return false;
2192 }
2193 return true;
2194
2195 case GL_QUERY:
2196 if (context->getQuery(name) == nullptr)
2197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002198 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002199 return false;
2200 }
2201 return true;
2202
2203 case GL_TRANSFORM_FEEDBACK:
2204 if (context->getTransformFeedback(name) == nullptr)
2205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002207 return false;
2208 }
2209 return true;
2210
2211 case GL_SAMPLER:
2212 if (context->getSampler(name) == nullptr)
2213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002214 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002215 return false;
2216 }
2217 return true;
2218
2219 case GL_TEXTURE:
2220 if (context->getTexture(name) == nullptr)
2221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002223 return false;
2224 }
2225 return true;
2226
2227 case GL_RENDERBUFFER:
2228 if (context->getRenderbuffer(name) == nullptr)
2229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002230 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002231 return false;
2232 }
2233 return true;
2234
2235 case GL_FRAMEBUFFER:
2236 if (context->getFramebuffer(name) == nullptr)
2237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002238 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002239 return false;
2240 }
2241 return true;
2242
2243 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002245 return false;
2246 }
Geoff Lange102fee2015-12-10 11:23:30 -05002247}
2248
Martin Radev9d901792016-07-15 15:58:58 +03002249static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2250{
2251 size_t labelLength = 0;
2252
2253 if (length < 0)
2254 {
2255 if (label != nullptr)
2256 {
2257 labelLength = strlen(label);
2258 }
2259 }
2260 else
2261 {
2262 labelLength = static_cast<size_t>(length);
2263 }
2264
2265 if (labelLength > context->getExtensions().maxLabelLength)
2266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002267 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002268 return false;
2269 }
2270
2271 return true;
2272}
2273
Geoff Lange102fee2015-12-10 11:23:30 -05002274bool ValidateObjectLabelKHR(Context *context,
2275 GLenum identifier,
2276 GLuint name,
2277 GLsizei length,
2278 const GLchar *label)
2279{
2280 if (!context->getExtensions().debug)
2281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002283 return false;
2284 }
2285
Geoff Lang70d0f492015-12-10 17:45:46 -05002286 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2287 {
2288 return false;
2289 }
2290
Martin Radev9d901792016-07-15 15:58:58 +03002291 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002292 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002293 return false;
2294 }
2295
Geoff Lange102fee2015-12-10 11:23:30 -05002296 return true;
2297}
2298
2299bool ValidateGetObjectLabelKHR(Context *context,
2300 GLenum identifier,
2301 GLuint name,
2302 GLsizei bufSize,
2303 GLsizei *length,
2304 GLchar *label)
2305{
2306 if (!context->getExtensions().debug)
2307 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002308 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002309 return false;
2310 }
2311
Geoff Lang70d0f492015-12-10 17:45:46 -05002312 if (bufSize < 0)
2313 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002314 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002315 return false;
2316 }
2317
2318 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2319 {
2320 return false;
2321 }
2322
Martin Radev9d901792016-07-15 15:58:58 +03002323 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002324}
2325
2326static bool ValidateObjectPtrName(Context *context, const void *ptr)
2327{
Jamie Madill70b5bb02017-08-28 13:32:37 -04002328 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
Geoff Lang70d0f492015-12-10 17:45:46 -05002329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002330 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002331 return false;
2332 }
2333
Geoff Lange102fee2015-12-10 11:23:30 -05002334 return true;
2335}
2336
2337bool ValidateObjectPtrLabelKHR(Context *context,
2338 const void *ptr,
2339 GLsizei length,
2340 const GLchar *label)
2341{
2342 if (!context->getExtensions().debug)
2343 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002344 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002345 return false;
2346 }
2347
Geoff Lang70d0f492015-12-10 17:45:46 -05002348 if (!ValidateObjectPtrName(context, ptr))
2349 {
2350 return false;
2351 }
2352
Martin Radev9d901792016-07-15 15:58:58 +03002353 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002354 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002355 return false;
2356 }
2357
Geoff Lange102fee2015-12-10 11:23:30 -05002358 return true;
2359}
2360
2361bool ValidateGetObjectPtrLabelKHR(Context *context,
2362 const void *ptr,
2363 GLsizei bufSize,
2364 GLsizei *length,
2365 GLchar *label)
2366{
2367 if (!context->getExtensions().debug)
2368 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002370 return false;
2371 }
2372
Geoff Lang70d0f492015-12-10 17:45:46 -05002373 if (bufSize < 0)
2374 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002375 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002376 return false;
2377 }
2378
2379 if (!ValidateObjectPtrName(context, ptr))
2380 {
2381 return false;
2382 }
2383
Martin Radev9d901792016-07-15 15:58:58 +03002384 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002385}
2386
2387bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2388{
2389 if (!context->getExtensions().debug)
2390 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002391 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002392 return false;
2393 }
2394
Geoff Lang70d0f492015-12-10 17:45:46 -05002395 // TODO: represent this in Context::getQueryParameterInfo.
2396 switch (pname)
2397 {
2398 case GL_DEBUG_CALLBACK_FUNCTION:
2399 case GL_DEBUG_CALLBACK_USER_PARAM:
2400 break;
2401
2402 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002404 return false;
2405 }
2406
Geoff Lange102fee2015-12-10 11:23:30 -05002407 return true;
2408}
Jamie Madillc29968b2016-01-20 11:17:23 -05002409
2410bool ValidateBlitFramebufferANGLE(Context *context,
2411 GLint srcX0,
2412 GLint srcY0,
2413 GLint srcX1,
2414 GLint srcY1,
2415 GLint dstX0,
2416 GLint dstY0,
2417 GLint dstX1,
2418 GLint dstY1,
2419 GLbitfield mask,
2420 GLenum filter)
2421{
2422 if (!context->getExtensions().framebufferBlit)
2423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002424 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002425 return false;
2426 }
2427
2428 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2429 {
2430 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002431 context->handleError(InvalidOperation() << "Scaling and flipping in "
2432 "BlitFramebufferANGLE not supported by this "
2433 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002434 return false;
2435 }
2436
2437 if (filter == GL_LINEAR)
2438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002439 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002440 return false;
2441 }
2442
Jamie Madill51f40ec2016-06-15 14:06:00 -04002443 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2444 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002445
2446 if (mask & GL_COLOR_BUFFER_BIT)
2447 {
2448 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2449 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2450
2451 if (readColorAttachment && drawColorAttachment)
2452 {
2453 if (!(readColorAttachment->type() == GL_TEXTURE &&
2454 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2455 readColorAttachment->type() != GL_RENDERBUFFER &&
2456 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002458 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002459 return false;
2460 }
2461
Geoff Langa15472a2015-08-11 11:48:03 -04002462 for (size_t drawbufferIdx = 0;
2463 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002464 {
Geoff Langa15472a2015-08-11 11:48:03 -04002465 const FramebufferAttachment *attachment =
2466 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2467 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002468 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002469 if (!(attachment->type() == GL_TEXTURE &&
2470 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2471 attachment->type() != GL_RENDERBUFFER &&
2472 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002474 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002475 return false;
2476 }
2477
2478 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002479 if (!Format::EquivalentForBlit(attachment->getFormat(),
2480 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002482 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002483 return false;
2484 }
2485 }
2486 }
2487
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002488 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002489 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2490 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002492 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002493 return false;
2494 }
2495 }
2496 }
2497
2498 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2499 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2500 for (size_t i = 0; i < 2; i++)
2501 {
2502 if (mask & masks[i])
2503 {
2504 const FramebufferAttachment *readBuffer =
2505 readFramebuffer->getAttachment(attachments[i]);
2506 const FramebufferAttachment *drawBuffer =
2507 drawFramebuffer->getAttachment(attachments[i]);
2508
2509 if (readBuffer && drawBuffer)
2510 {
2511 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2512 dstX0, dstY0, dstX1, dstY1))
2513 {
2514 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002515 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2516 "stencil blits are supported by "
2517 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002518 return false;
2519 }
2520
2521 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002523 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002524 return false;
2525 }
2526 }
2527 }
2528 }
2529
2530 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2531 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002532}
Jamie Madillc29968b2016-01-20 11:17:23 -05002533
2534bool ValidateClear(ValidationContext *context, GLbitfield mask)
2535{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002536 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002537 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002540 return false;
2541 }
2542
2543 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002545 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002546 return false;
2547 }
2548
Geoff Lang76e65652017-03-27 14:58:02 -04002549 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2550 {
2551 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2552 GL_SIGNED_NORMALIZED};
2553
Corentin Wallez59c41592017-07-11 13:19:54 -04002554 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002555 drawBufferIdx++)
2556 {
2557 if (!ValidateWebGLFramebufferAttachmentClearType(
2558 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2559 {
2560 return false;
2561 }
2562 }
2563 }
2564
Jamie Madillc29968b2016-01-20 11:17:23 -05002565 return true;
2566}
2567
2568bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2569{
2570 if (!context->getExtensions().drawBuffers)
2571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002572 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002573 return false;
2574 }
2575
2576 return ValidateDrawBuffersBase(context, n, bufs);
2577}
2578
Jamie Madill73a84962016-02-12 09:27:23 -05002579bool ValidateTexImage2D(Context *context,
2580 GLenum target,
2581 GLint level,
2582 GLint internalformat,
2583 GLsizei width,
2584 GLsizei height,
2585 GLint border,
2586 GLenum format,
2587 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002588 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002589{
Martin Radev1be913c2016-07-11 17:59:16 +03002590 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002591 {
2592 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002593 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002594 }
2595
Martin Radev1be913c2016-07-11 17:59:16 +03002596 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002597 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002598 0, 0, width, height, 1, border, format, type, -1,
2599 pixels);
2600}
2601
2602bool ValidateTexImage2DRobust(Context *context,
2603 GLenum target,
2604 GLint level,
2605 GLint internalformat,
2606 GLsizei width,
2607 GLsizei height,
2608 GLint border,
2609 GLenum format,
2610 GLenum type,
2611 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002612 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002613{
2614 if (!ValidateRobustEntryPoint(context, bufSize))
2615 {
2616 return false;
2617 }
2618
2619 if (context->getClientMajorVersion() < 3)
2620 {
2621 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2622 0, 0, width, height, border, format, type, bufSize,
2623 pixels);
2624 }
2625
2626 ASSERT(context->getClientMajorVersion() >= 3);
2627 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2628 0, 0, width, height, 1, border, format, type, bufSize,
2629 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002630}
2631
2632bool ValidateTexSubImage2D(Context *context,
2633 GLenum target,
2634 GLint level,
2635 GLint xoffset,
2636 GLint yoffset,
2637 GLsizei width,
2638 GLsizei height,
2639 GLenum format,
2640 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002641 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002642{
2643
Martin Radev1be913c2016-07-11 17:59:16 +03002644 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002645 {
2646 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002647 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002648 }
2649
Martin Radev1be913c2016-07-11 17:59:16 +03002650 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002651 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002652 yoffset, 0, width, height, 1, 0, format, type, -1,
2653 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002654}
2655
Geoff Langc52f6f12016-10-14 10:18:00 -04002656bool ValidateTexSubImage2DRobustANGLE(Context *context,
2657 GLenum target,
2658 GLint level,
2659 GLint xoffset,
2660 GLint yoffset,
2661 GLsizei width,
2662 GLsizei height,
2663 GLenum format,
2664 GLenum type,
2665 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002666 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002667{
2668 if (!ValidateRobustEntryPoint(context, bufSize))
2669 {
2670 return false;
2671 }
2672
2673 if (context->getClientMajorVersion() < 3)
2674 {
2675 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2676 yoffset, width, height, 0, format, type, bufSize,
2677 pixels);
2678 }
2679
2680 ASSERT(context->getClientMajorVersion() >= 3);
2681 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2682 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2683 pixels);
2684}
2685
Jamie Madill73a84962016-02-12 09:27:23 -05002686bool ValidateCompressedTexImage2D(Context *context,
2687 GLenum target,
2688 GLint level,
2689 GLenum internalformat,
2690 GLsizei width,
2691 GLsizei height,
2692 GLint border,
2693 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002694 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002695{
Martin Radev1be913c2016-07-11 17:59:16 +03002696 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002697 {
2698 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002699 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002700 {
2701 return false;
2702 }
2703 }
2704 else
2705 {
Martin Radev1be913c2016-07-11 17:59:16 +03002706 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002707 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002708 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002709 data))
2710 {
2711 return false;
2712 }
2713 }
2714
Geoff Langca271392017-04-05 12:30:00 -04002715 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jeff Gilbert48590352017-11-07 16:03:38 -08002716 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002717 if (blockSizeOrErr.isError())
2718 {
2719 context->handleError(blockSizeOrErr.getError());
2720 return false;
2721 }
2722
2723 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002724 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002725 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002726 return false;
2727 }
2728
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002729 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2730 {
2731 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2732 return false;
2733 }
2734
Jamie Madill73a84962016-02-12 09:27:23 -05002735 return true;
2736}
2737
Corentin Wallezb2931602017-04-11 15:58:57 -04002738bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2739 GLenum target,
2740 GLint level,
2741 GLenum internalformat,
2742 GLsizei width,
2743 GLsizei height,
2744 GLint border,
2745 GLsizei imageSize,
2746 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002747 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002748{
2749 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2750 {
2751 return false;
2752 }
2753
2754 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2755 border, imageSize, data);
2756}
2757bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2758 GLenum target,
2759 GLint level,
2760 GLint xoffset,
2761 GLint yoffset,
2762 GLsizei width,
2763 GLsizei height,
2764 GLenum format,
2765 GLsizei imageSize,
2766 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002767 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002768{
2769 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2770 {
2771 return false;
2772 }
2773
2774 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2775 format, imageSize, data);
2776}
2777
Jamie Madill73a84962016-02-12 09:27:23 -05002778bool ValidateCompressedTexSubImage2D(Context *context,
2779 GLenum target,
2780 GLint level,
2781 GLint xoffset,
2782 GLint yoffset,
2783 GLsizei width,
2784 GLsizei height,
2785 GLenum format,
2786 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002787 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002788{
Martin Radev1be913c2016-07-11 17:59:16 +03002789 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002790 {
2791 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002792 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002793 {
2794 return false;
2795 }
2796 }
2797 else
2798 {
Martin Radev1be913c2016-07-11 17:59:16 +03002799 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002800 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002801 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002802 data))
2803 {
2804 return false;
2805 }
2806 }
2807
Geoff Langca271392017-04-05 12:30:00 -04002808 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jeff Gilbert48590352017-11-07 16:03:38 -08002809 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002810 if (blockSizeOrErr.isError())
2811 {
2812 context->handleError(blockSizeOrErr.getError());
2813 return false;
2814 }
2815
2816 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002818 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002819 return false;
2820 }
2821
2822 return true;
2823}
2824
Corentin Wallez336129f2017-10-17 15:55:40 -04002825bool ValidateGetBufferPointervOES(Context *context,
2826 BufferBinding target,
2827 GLenum pname,
2828 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002829{
Geoff Lang496c02d2016-10-20 11:38:11 -07002830 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002831}
2832
Corentin Wallez336129f2017-10-17 15:55:40 -04002833bool ValidateMapBufferOES(Context *context, BufferBinding target, GLenum access)
Olli Etuaho4f667482016-03-30 15:56:35 +03002834{
2835 if (!context->getExtensions().mapBuffer)
2836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002837 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002838 return false;
2839 }
2840
Corentin Wallez336129f2017-10-17 15:55:40 -04002841 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03002842 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002843 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002844 return false;
2845 }
2846
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002847 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002848
2849 if (buffer == nullptr)
2850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002851 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002852 return false;
2853 }
2854
2855 if (access != GL_WRITE_ONLY_OES)
2856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002857 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002858 return false;
2859 }
2860
2861 if (buffer->isMapped())
2862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002863 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002864 return false;
2865 }
2866
Geoff Lang79f71042017-08-14 16:43:43 -04002867 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002868}
2869
Corentin Wallez336129f2017-10-17 15:55:40 -04002870bool ValidateUnmapBufferOES(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002871{
2872 if (!context->getExtensions().mapBuffer)
2873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002874 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002875 return false;
2876 }
2877
2878 return ValidateUnmapBufferBase(context, target);
2879}
2880
2881bool ValidateMapBufferRangeEXT(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002882 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002883 GLintptr offset,
2884 GLsizeiptr length,
2885 GLbitfield access)
2886{
2887 if (!context->getExtensions().mapBufferRange)
2888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002889 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002890 return false;
2891 }
2892
2893 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2894}
2895
Corentin Wallez336129f2017-10-17 15:55:40 -04002896bool ValidateMapBufferBase(Context *context, BufferBinding target)
Geoff Lang79f71042017-08-14 16:43:43 -04002897{
2898 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2899 ASSERT(buffer != nullptr);
2900
2901 // Check if this buffer is currently being used as a transform feedback output buffer
2902 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2903 if (transformFeedback != nullptr && transformFeedback->isActive())
2904 {
2905 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2906 {
2907 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2908 if (transformFeedbackBuffer.get() == buffer)
2909 {
2910 context->handleError(InvalidOperation()
2911 << "Buffer is currently bound for transform feedback.");
2912 return false;
2913 }
2914 }
2915 }
2916
2917 return true;
2918}
2919
Olli Etuaho4f667482016-03-30 15:56:35 +03002920bool ValidateFlushMappedBufferRangeEXT(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002921 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002922 GLintptr offset,
2923 GLsizeiptr length)
2924{
2925 if (!context->getExtensions().mapBufferRange)
2926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002927 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002928 return false;
2929 }
2930
2931 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2932}
2933
Ian Ewell54f87462016-03-10 13:47:21 -05002934bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2935{
2936 Texture *textureObject = context->getTexture(texture);
2937 if (textureObject && textureObject->getTarget() != target && texture != 0)
2938 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002940 return false;
2941 }
2942
Geoff Langf41a7152016-09-19 15:11:17 -04002943 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2944 !context->isTextureGenerated(texture))
2945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002946 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002947 return false;
2948 }
2949
Ian Ewell54f87462016-03-10 13:47:21 -05002950 switch (target)
2951 {
2952 case GL_TEXTURE_2D:
2953 case GL_TEXTURE_CUBE_MAP:
2954 break;
2955
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002956 case GL_TEXTURE_RECTANGLE_ANGLE:
2957 if (!context->getExtensions().textureRectangle)
2958 {
2959 context->handleError(InvalidEnum()
2960 << "Context does not support GL_ANGLE_texture_rectangle");
2961 return false;
2962 }
2963 break;
2964
Ian Ewell54f87462016-03-10 13:47:21 -05002965 case GL_TEXTURE_3D:
2966 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002967 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002968 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002970 return false;
2971 }
2972 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002973
2974 case GL_TEXTURE_2D_MULTISAMPLE:
2975 if (context->getClientVersion() < Version(3, 1))
2976 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002977 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002978 return false;
2979 }
Geoff Lang3b573612016-10-31 14:08:10 -04002980 break;
2981
Ian Ewell54f87462016-03-10 13:47:21 -05002982 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002983 if (!context->getExtensions().eglImageExternal &&
2984 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002986 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002987 return false;
2988 }
2989 break;
2990 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002991 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002992 return false;
2993 }
2994
2995 return true;
2996}
2997
Geoff Langd8605522016-04-13 10:19:12 -04002998bool ValidateBindUniformLocationCHROMIUM(Context *context,
2999 GLuint program,
3000 GLint location,
3001 const GLchar *name)
3002{
3003 if (!context->getExtensions().bindUniformLocation)
3004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003005 context->handleError(InvalidOperation()
3006 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04003007 return false;
3008 }
3009
3010 Program *programObject = GetValidProgram(context, program);
3011 if (!programObject)
3012 {
3013 return false;
3014 }
3015
3016 if (location < 0)
3017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04003019 return false;
3020 }
3021
3022 const Caps &caps = context->getCaps();
3023 if (static_cast<size_t>(location) >=
3024 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003026 context->handleError(InvalidValue() << "Location must be less than "
3027 "(MAX_VERTEX_UNIFORM_VECTORS + "
3028 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04003029 return false;
3030 }
3031
Geoff Langfc32e8b2017-05-31 14:16:59 -04003032 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3033 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04003034 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04003035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003036 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04003037 return false;
3038 }
3039
Geoff Langd8605522016-04-13 10:19:12 -04003040 if (strncmp(name, "gl_", 3) == 0)
3041 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003042 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04003043 return false;
3044 }
3045
3046 return true;
3047}
3048
Jamie Madille2e406c2016-06-02 13:04:10 -04003049bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03003050{
3051 if (!context->getExtensions().framebufferMixedSamples)
3052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003053 context->handleError(InvalidOperation()
3054 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03003055 return false;
3056 }
3057 switch (components)
3058 {
3059 case GL_RGB:
3060 case GL_RGBA:
3061 case GL_ALPHA:
3062 case GL_NONE:
3063 break;
3064 default:
3065 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003066 InvalidEnum()
3067 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03003068 return false;
3069 }
3070
3071 return true;
3072}
3073
Sami Väisänene45e53b2016-05-25 10:36:04 +03003074// CHROMIUM_path_rendering
3075
3076bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3077{
3078 if (!context->getExtensions().pathRendering)
3079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003080 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003081 return false;
3082 }
3083 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3084 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003085 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003086 return false;
3087 }
3088 if (matrix == nullptr)
3089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003090 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003091 return false;
3092 }
3093 return true;
3094}
3095
3096bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3097{
3098 if (!context->getExtensions().pathRendering)
3099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003100 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003101 return false;
3102 }
3103 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3104 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003106 return false;
3107 }
3108 return true;
3109}
3110
3111bool ValidateGenPaths(Context *context, GLsizei range)
3112{
3113 if (!context->getExtensions().pathRendering)
3114 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003115 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003116 return false;
3117 }
3118
3119 // range = 0 is undefined in NV_path_rendering.
3120 // we add stricter semantic check here and require a non zero positive range.
3121 if (range <= 0)
3122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003123 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003124 return false;
3125 }
3126
3127 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003130 return false;
3131 }
3132
3133 return true;
3134}
3135
3136bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3137{
3138 if (!context->getExtensions().pathRendering)
3139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003140 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003141 return false;
3142 }
3143
3144 // range = 0 is undefined in NV_path_rendering.
3145 // we add stricter semantic check here and require a non zero positive range.
3146 if (range <= 0)
3147 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003148 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003149 return false;
3150 }
3151
3152 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3153 checkedRange += range;
3154
3155 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003158 return false;
3159 }
3160 return true;
3161}
3162
3163bool ValidatePathCommands(Context *context,
3164 GLuint path,
3165 GLsizei numCommands,
3166 const GLubyte *commands,
3167 GLsizei numCoords,
3168 GLenum coordType,
3169 const void *coords)
3170{
3171 if (!context->getExtensions().pathRendering)
3172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003173 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003174 return false;
3175 }
3176 if (!context->hasPath(path))
3177 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003179 return false;
3180 }
3181
3182 if (numCommands < 0)
3183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003184 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003185 return false;
3186 }
3187 else if (numCommands > 0)
3188 {
3189 if (!commands)
3190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003191 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003192 return false;
3193 }
3194 }
3195
3196 if (numCoords < 0)
3197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003198 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003199 return false;
3200 }
3201 else if (numCoords > 0)
3202 {
3203 if (!coords)
3204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003205 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003206 return false;
3207 }
3208 }
3209
3210 std::uint32_t coordTypeSize = 0;
3211 switch (coordType)
3212 {
3213 case GL_BYTE:
3214 coordTypeSize = sizeof(GLbyte);
3215 break;
3216
3217 case GL_UNSIGNED_BYTE:
3218 coordTypeSize = sizeof(GLubyte);
3219 break;
3220
3221 case GL_SHORT:
3222 coordTypeSize = sizeof(GLshort);
3223 break;
3224
3225 case GL_UNSIGNED_SHORT:
3226 coordTypeSize = sizeof(GLushort);
3227 break;
3228
3229 case GL_FLOAT:
3230 coordTypeSize = sizeof(GLfloat);
3231 break;
3232
3233 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003234 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003235 return false;
3236 }
3237
3238 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3239 checkedSize += (coordTypeSize * numCoords);
3240 if (!checkedSize.IsValid())
3241 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003242 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003243 return false;
3244 }
3245
3246 // early return skips command data validation when it doesn't exist.
3247 if (!commands)
3248 return true;
3249
3250 GLsizei expectedNumCoords = 0;
3251 for (GLsizei i = 0; i < numCommands; ++i)
3252 {
3253 switch (commands[i])
3254 {
3255 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3256 break;
3257 case GL_MOVE_TO_CHROMIUM:
3258 case GL_LINE_TO_CHROMIUM:
3259 expectedNumCoords += 2;
3260 break;
3261 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3262 expectedNumCoords += 4;
3263 break;
3264 case GL_CUBIC_CURVE_TO_CHROMIUM:
3265 expectedNumCoords += 6;
3266 break;
3267 case GL_CONIC_CURVE_TO_CHROMIUM:
3268 expectedNumCoords += 5;
3269 break;
3270 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003271 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003272 return false;
3273 }
3274 }
3275 if (expectedNumCoords != numCoords)
3276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003277 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003278 return false;
3279 }
3280
3281 return true;
3282}
3283
3284bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3285{
3286 if (!context->getExtensions().pathRendering)
3287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003288 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003289 return false;
3290 }
3291 if (!context->hasPath(path))
3292 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003294 return false;
3295 }
3296
3297 switch (pname)
3298 {
3299 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3300 if (value < 0.0f)
3301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003302 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003303 return false;
3304 }
3305 break;
3306 case GL_PATH_END_CAPS_CHROMIUM:
3307 switch (static_cast<GLenum>(value))
3308 {
3309 case GL_FLAT_CHROMIUM:
3310 case GL_SQUARE_CHROMIUM:
3311 case GL_ROUND_CHROMIUM:
3312 break;
3313 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003314 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003315 return false;
3316 }
3317 break;
3318 case GL_PATH_JOIN_STYLE_CHROMIUM:
3319 switch (static_cast<GLenum>(value))
3320 {
3321 case GL_MITER_REVERT_CHROMIUM:
3322 case GL_BEVEL_CHROMIUM:
3323 case GL_ROUND_CHROMIUM:
3324 break;
3325 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003327 return false;
3328 }
3329 case GL_PATH_MITER_LIMIT_CHROMIUM:
3330 if (value < 0.0f)
3331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003332 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003333 return false;
3334 }
3335 break;
3336
3337 case GL_PATH_STROKE_BOUND_CHROMIUM:
3338 // no errors, only clamping.
3339 break;
3340
3341 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003342 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003343 return false;
3344 }
3345 return true;
3346}
3347
3348bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3349{
3350 if (!context->getExtensions().pathRendering)
3351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003352 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003353 return false;
3354 }
3355
3356 if (!context->hasPath(path))
3357 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003358 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003359 return false;
3360 }
3361 if (!value)
3362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003363 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003364 return false;
3365 }
3366
3367 switch (pname)
3368 {
3369 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3370 case GL_PATH_END_CAPS_CHROMIUM:
3371 case GL_PATH_JOIN_STYLE_CHROMIUM:
3372 case GL_PATH_MITER_LIMIT_CHROMIUM:
3373 case GL_PATH_STROKE_BOUND_CHROMIUM:
3374 break;
3375
3376 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003377 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003378 return false;
3379 }
3380
3381 return true;
3382}
3383
3384bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3385{
3386 if (!context->getExtensions().pathRendering)
3387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003388 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003389 return false;
3390 }
3391
3392 switch (func)
3393 {
3394 case GL_NEVER:
3395 case GL_ALWAYS:
3396 case GL_LESS:
3397 case GL_LEQUAL:
3398 case GL_EQUAL:
3399 case GL_GEQUAL:
3400 case GL_GREATER:
3401 case GL_NOTEQUAL:
3402 break;
3403 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003405 return false;
3406 }
3407
3408 return true;
3409}
3410
3411// Note that the spec specifies that for the path drawing commands
3412// if the path object is not an existing path object the command
3413// does nothing and no error is generated.
3414// However if the path object exists but has not been specified any
3415// commands then an error is generated.
3416
3417bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3418{
3419 if (!context->getExtensions().pathRendering)
3420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003421 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003422 return false;
3423 }
3424 if (context->hasPath(path) && !context->hasPathData(path))
3425 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003427 return false;
3428 }
3429
3430 switch (fillMode)
3431 {
3432 case GL_COUNT_UP_CHROMIUM:
3433 case GL_COUNT_DOWN_CHROMIUM:
3434 break;
3435 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003437 return false;
3438 }
3439
3440 if (!isPow2(mask + 1))
3441 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003442 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003443 return false;
3444 }
3445
3446 return true;
3447}
3448
3449bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3450{
3451 if (!context->getExtensions().pathRendering)
3452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003453 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003454 return false;
3455 }
3456 if (context->hasPath(path) && !context->hasPathData(path))
3457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003458 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003459 return false;
3460 }
3461
3462 return true;
3463}
3464
3465bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3466{
3467 if (!context->getExtensions().pathRendering)
3468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003469 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003470 return false;
3471 }
3472 if (context->hasPath(path) && !context->hasPathData(path))
3473 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003475 return false;
3476 }
3477
3478 switch (coverMode)
3479 {
3480 case GL_CONVEX_HULL_CHROMIUM:
3481 case GL_BOUNDING_BOX_CHROMIUM:
3482 break;
3483 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003484 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003485 return false;
3486 }
3487 return true;
3488}
3489
3490bool ValidateStencilThenCoverFillPath(Context *context,
3491 GLuint path,
3492 GLenum fillMode,
3493 GLuint mask,
3494 GLenum coverMode)
3495{
3496 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3497 ValidateCoverPath(context, path, coverMode);
3498}
3499
3500bool ValidateStencilThenCoverStrokePath(Context *context,
3501 GLuint path,
3502 GLint reference,
3503 GLuint mask,
3504 GLenum coverMode)
3505{
3506 return ValidateStencilStrokePath(context, path, reference, mask) &&
3507 ValidateCoverPath(context, path, coverMode);
3508}
3509
3510bool ValidateIsPath(Context *context)
3511{
3512 if (!context->getExtensions().pathRendering)
3513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003515 return false;
3516 }
3517 return true;
3518}
3519
Sami Väisänend59ca052016-06-21 16:10:00 +03003520bool ValidateCoverFillPathInstanced(Context *context,
3521 GLsizei numPaths,
3522 GLenum pathNameType,
3523 const void *paths,
3524 GLuint pathBase,
3525 GLenum coverMode,
3526 GLenum transformType,
3527 const GLfloat *transformValues)
3528{
3529 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3530 transformType, transformValues))
3531 return false;
3532
3533 switch (coverMode)
3534 {
3535 case GL_CONVEX_HULL_CHROMIUM:
3536 case GL_BOUNDING_BOX_CHROMIUM:
3537 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3538 break;
3539 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003540 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003541 return false;
3542 }
3543
3544 return true;
3545}
3546
3547bool ValidateCoverStrokePathInstanced(Context *context,
3548 GLsizei numPaths,
3549 GLenum pathNameType,
3550 const void *paths,
3551 GLuint pathBase,
3552 GLenum coverMode,
3553 GLenum transformType,
3554 const GLfloat *transformValues)
3555{
3556 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3557 transformType, transformValues))
3558 return false;
3559
3560 switch (coverMode)
3561 {
3562 case GL_CONVEX_HULL_CHROMIUM:
3563 case GL_BOUNDING_BOX_CHROMIUM:
3564 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3565 break;
3566 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003568 return false;
3569 }
3570
3571 return true;
3572}
3573
3574bool ValidateStencilFillPathInstanced(Context *context,
3575 GLsizei numPaths,
3576 GLenum pathNameType,
3577 const void *paths,
3578 GLuint pathBase,
3579 GLenum fillMode,
3580 GLuint mask,
3581 GLenum transformType,
3582 const GLfloat *transformValues)
3583{
3584
3585 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3586 transformType, transformValues))
3587 return false;
3588
3589 switch (fillMode)
3590 {
3591 case GL_COUNT_UP_CHROMIUM:
3592 case GL_COUNT_DOWN_CHROMIUM:
3593 break;
3594 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003596 return false;
3597 }
3598 if (!isPow2(mask + 1))
3599 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003600 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003601 return false;
3602 }
3603 return true;
3604}
3605
3606bool ValidateStencilStrokePathInstanced(Context *context,
3607 GLsizei numPaths,
3608 GLenum pathNameType,
3609 const void *paths,
3610 GLuint pathBase,
3611 GLint reference,
3612 GLuint mask,
3613 GLenum transformType,
3614 const GLfloat *transformValues)
3615{
3616 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3617 transformType, transformValues))
3618 return false;
3619
3620 // no more validation here.
3621
3622 return true;
3623}
3624
3625bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3626 GLsizei numPaths,
3627 GLenum pathNameType,
3628 const void *paths,
3629 GLuint pathBase,
3630 GLenum fillMode,
3631 GLuint mask,
3632 GLenum coverMode,
3633 GLenum transformType,
3634 const GLfloat *transformValues)
3635{
3636 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3637 transformType, transformValues))
3638 return false;
3639
3640 switch (coverMode)
3641 {
3642 case GL_CONVEX_HULL_CHROMIUM:
3643 case GL_BOUNDING_BOX_CHROMIUM:
3644 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3645 break;
3646 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003648 return false;
3649 }
3650
3651 switch (fillMode)
3652 {
3653 case GL_COUNT_UP_CHROMIUM:
3654 case GL_COUNT_DOWN_CHROMIUM:
3655 break;
3656 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003657 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003658 return false;
3659 }
3660 if (!isPow2(mask + 1))
3661 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003662 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003663 return false;
3664 }
3665
3666 return true;
3667}
3668
3669bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3670 GLsizei numPaths,
3671 GLenum pathNameType,
3672 const void *paths,
3673 GLuint pathBase,
3674 GLint reference,
3675 GLuint mask,
3676 GLenum coverMode,
3677 GLenum transformType,
3678 const GLfloat *transformValues)
3679{
3680 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3681 transformType, transformValues))
3682 return false;
3683
3684 switch (coverMode)
3685 {
3686 case GL_CONVEX_HULL_CHROMIUM:
3687 case GL_BOUNDING_BOX_CHROMIUM:
3688 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3689 break;
3690 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003691 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003692 return false;
3693 }
3694
3695 return true;
3696}
3697
Sami Väisänen46eaa942016-06-29 10:26:37 +03003698bool ValidateBindFragmentInputLocation(Context *context,
3699 GLuint program,
3700 GLint location,
3701 const GLchar *name)
3702{
3703 if (!context->getExtensions().pathRendering)
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003706 return false;
3707 }
3708
3709 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3710 if (location >= MaxLocation)
3711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003713 return false;
3714 }
3715
3716 const auto *programObject = context->getProgram(program);
3717 if (!programObject)
3718 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003720 return false;
3721 }
3722
3723 if (!name)
3724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003726 return false;
3727 }
3728
3729 if (angle::BeginsWith(name, "gl_"))
3730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003731 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003732 return false;
3733 }
3734
3735 return true;
3736}
3737
3738bool ValidateProgramPathFragmentInputGen(Context *context,
3739 GLuint program,
3740 GLint location,
3741 GLenum genMode,
3742 GLint components,
3743 const GLfloat *coeffs)
3744{
3745 if (!context->getExtensions().pathRendering)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003748 return false;
3749 }
3750
3751 const auto *programObject = context->getProgram(program);
3752 if (!programObject || programObject->isFlaggedForDeletion())
3753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003755 return false;
3756 }
3757
3758 if (!programObject->isLinked())
3759 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003760 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003761 return false;
3762 }
3763
3764 switch (genMode)
3765 {
3766 case GL_NONE:
3767 if (components != 0)
3768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003770 return false;
3771 }
3772 break;
3773
3774 case GL_OBJECT_LINEAR_CHROMIUM:
3775 case GL_EYE_LINEAR_CHROMIUM:
3776 case GL_CONSTANT_CHROMIUM:
3777 if (components < 1 || components > 4)
3778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003779 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003780 return false;
3781 }
3782 if (!coeffs)
3783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003784 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003785 return false;
3786 }
3787 break;
3788
3789 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003791 return false;
3792 }
3793
3794 // If the location is -1 then the command is silently ignored
3795 // and no further validation is needed.
3796 if (location == -1)
3797 return true;
3798
Jamie Madillbd044ed2017-06-05 12:59:21 -04003799 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003800
3801 if (!binding.valid)
3802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003804 return false;
3805 }
3806
3807 if (binding.type != GL_NONE)
3808 {
3809 GLint expectedComponents = 0;
3810 switch (binding.type)
3811 {
3812 case GL_FLOAT:
3813 expectedComponents = 1;
3814 break;
3815 case GL_FLOAT_VEC2:
3816 expectedComponents = 2;
3817 break;
3818 case GL_FLOAT_VEC3:
3819 expectedComponents = 3;
3820 break;
3821 case GL_FLOAT_VEC4:
3822 expectedComponents = 4;
3823 break;
3824 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003825 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003826 InvalidOperation()
3827 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003828 return false;
3829 }
3830 if (expectedComponents != components && genMode != GL_NONE)
3831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003832 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003833 return false;
3834 }
3835 }
3836 return true;
3837}
3838
Geoff Lang97073d12016-04-20 10:42:34 -07003839bool ValidateCopyTextureCHROMIUM(Context *context,
3840 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003841 GLint sourceLevel,
3842 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003843 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003844 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003845 GLint internalFormat,
3846 GLenum destType,
3847 GLboolean unpackFlipY,
3848 GLboolean unpackPremultiplyAlpha,
3849 GLboolean unpackUnmultiplyAlpha)
3850{
3851 if (!context->getExtensions().copyTexture)
3852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003853 context->handleError(InvalidOperation()
3854 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003855 return false;
3856 }
3857
Geoff Lang4f0e0032017-05-01 16:04:35 -04003858 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003859 if (source == nullptr)
3860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003862 return false;
3863 }
3864
3865 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003867 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003868 return false;
3869 }
3870
3871 GLenum sourceTarget = source->getTarget();
3872 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003873
3874 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003876 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003877 return false;
3878 }
3879
Geoff Lang4f0e0032017-05-01 16:04:35 -04003880 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3881 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3882 if (sourceWidth == 0 || sourceHeight == 0)
3883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003885 return false;
3886 }
3887
3888 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3889 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003892 return false;
3893 }
3894
Geoff Lang63458a32017-10-30 15:16:53 -04003895 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3896 {
3897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
3898 return false;
3899 }
3900
Geoff Lang4f0e0032017-05-01 16:04:35 -04003901 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003902 if (dest == nullptr)
3903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003904 context->handleError(InvalidValue()
3905 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003906 return false;
3907 }
3908
Geoff Lang4f0e0032017-05-01 16:04:35 -04003909 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003911 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003912 return false;
3913 }
3914
Geoff Lang4f0e0032017-05-01 16:04:35 -04003915 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3916 sourceHeight))
3917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003918 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003919 return false;
3920 }
3921
Geoff Lang97073d12016-04-20 10:42:34 -07003922 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003925 return false;
3926 }
3927
Geoff Lang4f0e0032017-05-01 16:04:35 -04003928 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(
3931 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003932 return false;
3933 }
3934
Geoff Lang97073d12016-04-20 10:42:34 -07003935 if (dest->getImmutableFormat())
3936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003937 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003938 return false;
3939 }
3940
3941 return true;
3942}
3943
3944bool ValidateCopySubTextureCHROMIUM(Context *context,
3945 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003946 GLint sourceLevel,
3947 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003948 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003949 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003950 GLint xoffset,
3951 GLint yoffset,
3952 GLint x,
3953 GLint y,
3954 GLsizei width,
3955 GLsizei height,
3956 GLboolean unpackFlipY,
3957 GLboolean unpackPremultiplyAlpha,
3958 GLboolean unpackUnmultiplyAlpha)
3959{
3960 if (!context->getExtensions().copyTexture)
3961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003962 context->handleError(InvalidOperation()
3963 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003964 return false;
3965 }
3966
Geoff Lang4f0e0032017-05-01 16:04:35 -04003967 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003968 if (source == nullptr)
3969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003971 return false;
3972 }
3973
3974 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003976 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003977 return false;
3978 }
3979
3980 GLenum sourceTarget = source->getTarget();
3981 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003982
3983 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003985 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003986 return false;
3987 }
3988
3989 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3990 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003992 context->handleError(InvalidValue()
3993 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003994 return false;
3995 }
3996
3997 if (x < 0 || y < 0)
3998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003999 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07004000 return false;
4001 }
4002
4003 if (width < 0 || height < 0)
4004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004005 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07004006 return false;
4007 }
4008
Geoff Lang4f0e0032017-05-01 16:04:35 -04004009 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
4010 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004011 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004012 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07004013 return false;
4014 }
4015
Geoff Lang4f0e0032017-05-01 16:04:35 -04004016 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
4017 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07004020 return false;
4021 }
4022
Geoff Lang63458a32017-10-30 15:16:53 -04004023 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
4024 {
4025 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
4026 return false;
4027 }
4028
Geoff Lang4f0e0032017-05-01 16:04:35 -04004029 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07004030 if (dest == nullptr)
4031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004032 context->handleError(InvalidValue()
4033 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07004034 return false;
4035 }
4036
Geoff Lang4f0e0032017-05-01 16:04:35 -04004037 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07004038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004039 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07004040 return false;
4041 }
4042
Geoff Lang4f0e0032017-05-01 16:04:35 -04004043 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07004044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004045 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004046 return false;
4047 }
4048
Geoff Lang4f0e0032017-05-01 16:04:35 -04004049 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
4050 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04004051 context
4052 ->handleError(InvalidOperation()
4053 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04004054 return false;
4055 }
4056
4057 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
4058 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004060 context->handleError(InvalidOperation()
4061 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004062 return false;
4063 }
4064
4065 if (xoffset < 0 || yoffset < 0)
4066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004067 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07004068 return false;
4069 }
4070
Geoff Lang4f0e0032017-05-01 16:04:35 -04004071 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
4072 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004074 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07004075 return false;
4076 }
4077
4078 return true;
4079}
4080
Geoff Lang47110bf2016-04-20 11:13:22 -07004081bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
4082{
4083 if (!context->getExtensions().copyCompressedTexture)
4084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004085 context->handleError(InvalidOperation()
4086 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004087 return false;
4088 }
4089
4090 const gl::Texture *source = context->getTexture(sourceId);
4091 if (source == nullptr)
4092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004093 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004094 return false;
4095 }
4096
4097 if (source->getTarget() != GL_TEXTURE_2D)
4098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004099 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004100 return false;
4101 }
4102
4103 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004105 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004106 return false;
4107 }
4108
4109 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4110 if (!sourceFormat.info->compressed)
4111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004112 context->handleError(InvalidOperation()
4113 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004114 return false;
4115 }
4116
4117 const gl::Texture *dest = context->getTexture(destId);
4118 if (dest == nullptr)
4119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004120 context->handleError(InvalidValue()
4121 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004122 return false;
4123 }
4124
4125 if (dest->getTarget() != GL_TEXTURE_2D)
4126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004127 context->handleError(InvalidValue()
4128 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004129 return false;
4130 }
4131
4132 if (dest->getImmutableFormat())
4133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004134 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004135 return false;
4136 }
4137
4138 return true;
4139}
4140
Martin Radev4c4c8e72016-08-04 12:25:34 +03004141bool ValidateCreateShader(Context *context, GLenum type)
4142{
4143 switch (type)
4144 {
4145 case GL_VERTEX_SHADER:
4146 case GL_FRAGMENT_SHADER:
4147 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004148
Martin Radev4c4c8e72016-08-04 12:25:34 +03004149 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004150 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004151 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004152 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Langeb66a6e2016-10-31 13:06:12 -04004153 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004154 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004155 break;
4156
Martin Radev4c4c8e72016-08-04 12:25:34 +03004157 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004159 return false;
4160 }
Jamie Madill29639852016-09-02 15:00:09 -04004161
4162 return true;
4163}
4164
4165bool ValidateBufferData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004166 BufferBinding target,
Jamie Madill29639852016-09-02 15:00:09 -04004167 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004168 const void *data,
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004169 BufferUsage usage)
Jamie Madill29639852016-09-02 15:00:09 -04004170{
4171 if (size < 0)
4172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004173 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004174 return false;
4175 }
4176
4177 switch (usage)
4178 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004179 case BufferUsage::StreamDraw:
4180 case BufferUsage::StaticDraw:
4181 case BufferUsage::DynamicDraw:
Jamie Madill29639852016-09-02 15:00:09 -04004182 break;
4183
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004184 case BufferUsage::StreamRead:
4185 case BufferUsage::StaticRead:
4186 case BufferUsage::DynamicRead:
4187 case BufferUsage::StreamCopy:
4188 case BufferUsage::StaticCopy:
4189 case BufferUsage::DynamicCopy:
Jamie Madill29639852016-09-02 15:00:09 -04004190 if (context->getClientMajorVersion() < 3)
4191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004193 return false;
4194 }
4195 break;
4196
4197 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004198 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004199 return false;
4200 }
4201
Corentin Wallez336129f2017-10-17 15:55:40 -04004202 if (!ValidBufferType(context, target))
Jamie Madill29639852016-09-02 15:00:09 -04004203 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004205 return false;
4206 }
4207
4208 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4209
4210 if (!buffer)
4211 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004213 return false;
4214 }
4215
4216 return true;
4217}
4218
4219bool ValidateBufferSubData(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004220 BufferBinding target,
Jamie Madill29639852016-09-02 15:00:09 -04004221 GLintptr offset,
4222 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004223 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004224{
Brandon Jones6cad5662017-06-14 13:25:13 -07004225 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4228 return false;
4229 }
4230
4231 if (offset < 0)
4232 {
4233 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004234 return false;
4235 }
4236
Corentin Wallez336129f2017-10-17 15:55:40 -04004237 if (!ValidBufferType(context, target))
Jamie Madill29639852016-09-02 15:00:09 -04004238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004240 return false;
4241 }
4242
4243 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4244
4245 if (!buffer)
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004248 return false;
4249 }
4250
4251 if (buffer->isMapped())
4252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004253 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004254 return false;
4255 }
4256
4257 // Check for possible overflow of size + offset
4258 angle::CheckedNumeric<size_t> checkedSize(size);
4259 checkedSize += offset;
4260 if (!checkedSize.IsValid())
4261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004262 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004263 return false;
4264 }
4265
4266 if (size + offset > buffer->getSize())
4267 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004268 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004269 return false;
4270 }
4271
Martin Radev4c4c8e72016-08-04 12:25:34 +03004272 return true;
4273}
4274
Geoff Lang111a99e2017-10-17 10:58:41 -04004275bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004276{
Geoff Langc339c4e2016-11-29 10:37:36 -05004277 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004279 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004280 return false;
4281 }
4282
Geoff Lang111a99e2017-10-17 10:58:41 -04004283 if (!context->isExtensionRequestable(name))
Geoff Langc287ea62016-09-16 14:46:51 -04004284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004285 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004286 return false;
4287 }
4288
4289 return true;
4290}
4291
Jamie Madillef300b12016-10-07 15:12:09 -04004292bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4293{
4294 if (texture < GL_TEXTURE0 ||
4295 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004297 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004298 return false;
4299 }
4300
4301 return true;
4302}
4303
4304bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4305{
4306 Program *programObject = GetValidProgram(context, program);
4307 if (!programObject)
4308 {
4309 return false;
4310 }
4311
4312 Shader *shaderObject = GetValidShader(context, shader);
4313 if (!shaderObject)
4314 {
4315 return false;
4316 }
4317
4318 switch (shaderObject->getType())
4319 {
4320 case GL_VERTEX_SHADER:
4321 {
4322 if (programObject->getAttachedVertexShader())
4323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004325 return false;
4326 }
4327 break;
4328 }
4329 case GL_FRAGMENT_SHADER:
4330 {
4331 if (programObject->getAttachedFragmentShader())
4332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004334 return false;
4335 }
4336 break;
4337 }
4338 case GL_COMPUTE_SHADER:
4339 {
4340 if (programObject->getAttachedComputeShader())
4341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004343 return false;
4344 }
4345 break;
4346 }
4347 default:
4348 UNREACHABLE();
4349 break;
4350 }
4351
4352 return true;
4353}
4354
Jamie Madill01a80ee2016-11-07 12:06:18 -05004355bool ValidateBindAttribLocation(ValidationContext *context,
4356 GLuint program,
4357 GLuint index,
4358 const GLchar *name)
4359{
4360 if (index >= MAX_VERTEX_ATTRIBS)
4361 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004362 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004363 return false;
4364 }
4365
4366 if (strncmp(name, "gl_", 3) == 0)
4367 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004369 return false;
4370 }
4371
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004372 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004373 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004374 const size_t length = strlen(name);
4375
4376 if (!IsValidESSLString(name, length))
4377 {
4378 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4379 // for shader-related entry points
4380 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4381 return false;
4382 }
4383
4384 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4385 {
4386 return false;
4387 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004388 }
4389
Jamie Madill01a80ee2016-11-07 12:06:18 -05004390 return GetValidProgram(context, program) != nullptr;
4391}
4392
Corentin Wallez336129f2017-10-17 15:55:40 -04004393bool ValidateBindBuffer(ValidationContext *context, BufferBinding target, GLuint buffer)
Jamie Madill01a80ee2016-11-07 12:06:18 -05004394{
Corentin Wallez336129f2017-10-17 15:55:40 -04004395 if (!ValidBufferType(context, target))
Jamie Madill01a80ee2016-11-07 12:06:18 -05004396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004398 return false;
4399 }
4400
4401 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4402 !context->isBufferGenerated(buffer))
4403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004405 return false;
4406 }
4407
4408 return true;
4409}
4410
4411bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4412{
Geoff Lange8afa902017-09-27 15:00:43 -04004413 if (!ValidFramebufferTarget(context, target))
Jamie Madill01a80ee2016-11-07 12:06:18 -05004414 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004416 return false;
4417 }
4418
4419 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4420 !context->isFramebufferGenerated(framebuffer))
4421 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004423 return false;
4424 }
4425
4426 return true;
4427}
4428
4429bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4430{
4431 if (target != GL_RENDERBUFFER)
4432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004434 return false;
4435 }
4436
4437 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4438 !context->isRenderbufferGenerated(renderbuffer))
4439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004441 return false;
4442 }
4443
4444 return true;
4445}
4446
Geoff Lang50cac572017-09-26 17:37:43 -04004447static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004448{
4449 switch (mode)
4450 {
4451 case GL_FUNC_ADD:
4452 case GL_FUNC_SUBTRACT:
4453 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004454 return true;
4455
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004456 case GL_MIN:
4457 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004458 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004459
4460 default:
4461 return false;
4462 }
4463}
4464
Jamie Madillc1d770e2017-04-13 17:31:24 -04004465bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004466 GLfloat red,
4467 GLfloat green,
4468 GLfloat blue,
4469 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004470{
4471 return true;
4472}
4473
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004474bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4475{
Geoff Lang50cac572017-09-26 17:37:43 -04004476 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004477 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004479 return false;
4480 }
4481
4482 return true;
4483}
4484
4485bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4486{
Geoff Lang50cac572017-09-26 17:37:43 -04004487 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004490 return false;
4491 }
4492
Geoff Lang50cac572017-09-26 17:37:43 -04004493 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004494 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004495 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004496 return false;
4497 }
4498
4499 return true;
4500}
4501
4502bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4503{
4504 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4505}
4506
4507static bool ValidSrcBlendFunc(GLenum srcBlend)
4508{
4509 switch (srcBlend)
4510 {
4511 case GL_ZERO:
4512 case GL_ONE:
4513 case GL_SRC_COLOR:
4514 case GL_ONE_MINUS_SRC_COLOR:
4515 case GL_DST_COLOR:
4516 case GL_ONE_MINUS_DST_COLOR:
4517 case GL_SRC_ALPHA:
4518 case GL_ONE_MINUS_SRC_ALPHA:
4519 case GL_DST_ALPHA:
4520 case GL_ONE_MINUS_DST_ALPHA:
4521 case GL_CONSTANT_COLOR:
4522 case GL_ONE_MINUS_CONSTANT_COLOR:
4523 case GL_CONSTANT_ALPHA:
4524 case GL_ONE_MINUS_CONSTANT_ALPHA:
4525 case GL_SRC_ALPHA_SATURATE:
4526 return true;
4527
4528 default:
4529 return false;
4530 }
4531}
4532
4533static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4534{
4535 switch (dstBlend)
4536 {
4537 case GL_ZERO:
4538 case GL_ONE:
4539 case GL_SRC_COLOR:
4540 case GL_ONE_MINUS_SRC_COLOR:
4541 case GL_DST_COLOR:
4542 case GL_ONE_MINUS_DST_COLOR:
4543 case GL_SRC_ALPHA:
4544 case GL_ONE_MINUS_SRC_ALPHA:
4545 case GL_DST_ALPHA:
4546 case GL_ONE_MINUS_DST_ALPHA:
4547 case GL_CONSTANT_COLOR:
4548 case GL_ONE_MINUS_CONSTANT_COLOR:
4549 case GL_CONSTANT_ALPHA:
4550 case GL_ONE_MINUS_CONSTANT_ALPHA:
4551 return true;
4552
4553 case GL_SRC_ALPHA_SATURATE:
4554 return (contextMajorVersion >= 3);
4555
4556 default:
4557 return false;
4558 }
4559}
4560
4561bool ValidateBlendFuncSeparate(ValidationContext *context,
4562 GLenum srcRGB,
4563 GLenum dstRGB,
4564 GLenum srcAlpha,
4565 GLenum dstAlpha)
4566{
4567 if (!ValidSrcBlendFunc(srcRGB))
4568 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004569 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004570 return false;
4571 }
4572
4573 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004576 return false;
4577 }
4578
4579 if (!ValidSrcBlendFunc(srcAlpha))
4580 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004582 return false;
4583 }
4584
4585 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004588 return false;
4589 }
4590
Frank Henigman146e8a12017-03-02 23:22:37 -05004591 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4592 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004593 {
4594 bool constantColorUsed =
4595 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4596 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4597
4598 bool constantAlphaUsed =
4599 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4600 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4601
4602 if (constantColorUsed && constantAlphaUsed)
4603 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004604 const char *msg;
4605 if (context->getExtensions().webglCompatibility)
4606 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004607 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004608 }
4609 else
4610 {
4611 msg =
4612 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4613 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4614 "implementation.";
4615 ERR() << msg;
4616 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004617 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004618 return false;
4619 }
4620 }
4621
4622 return true;
4623}
4624
Geoff Langc339c4e2016-11-29 10:37:36 -05004625bool ValidateGetString(Context *context, GLenum name)
4626{
4627 switch (name)
4628 {
4629 case GL_VENDOR:
4630 case GL_RENDERER:
4631 case GL_VERSION:
4632 case GL_SHADING_LANGUAGE_VERSION:
4633 case GL_EXTENSIONS:
4634 break;
4635
4636 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4637 if (!context->getExtensions().requestExtension)
4638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004640 return false;
4641 }
4642 break;
4643
4644 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004646 return false;
4647 }
4648
4649 return true;
4650}
4651
Geoff Lang47c48082016-12-07 15:38:13 -05004652bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4653{
4654 if (width <= 0.0f || isNaN(width))
4655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004656 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004657 return false;
4658 }
4659
4660 return true;
4661}
4662
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004663bool ValidateVertexAttribPointer(ValidationContext *context,
4664 GLuint index,
4665 GLint size,
4666 GLenum type,
4667 GLboolean normalized,
4668 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004669 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004670{
Shao80957d92017-02-20 21:25:59 +08004671 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004672 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004673 return false;
4674 }
4675
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004676 if (stride < 0)
4677 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004678 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004679 return false;
4680 }
4681
Shao80957d92017-02-20 21:25:59 +08004682 const Caps &caps = context->getCaps();
4683 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004684 {
Shao80957d92017-02-20 21:25:59 +08004685 if (stride > caps.maxVertexAttribStride)
4686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004687 context->handleError(InvalidValue()
4688 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004689 return false;
4690 }
4691
4692 if (index >= caps.maxVertexAttribBindings)
4693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004694 context->handleError(InvalidValue()
4695 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004696 return false;
4697 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004698 }
4699
4700 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4701 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4702 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4703 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004704 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4705 context->getGLState().getVertexArray()->id() == 0;
Corentin Wallez336129f2017-10-17 15:55:40 -04004706 if (!nullBufferAllowed && context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 &&
4707 ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004709 context
4710 ->handleError(InvalidOperation()
4711 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004712 return false;
4713 }
4714
4715 if (context->getExtensions().webglCompatibility)
4716 {
4717 // WebGL 1.0 [Section 6.14] Fixed point support
4718 // The WebGL API does not support the GL_FIXED data type.
4719 if (type == GL_FIXED)
4720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004721 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004722 return false;
4723 }
4724
Geoff Lang2d62ab72017-03-23 16:54:40 -04004725 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004726 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004727 return false;
4728 }
4729 }
4730
4731 return true;
4732}
4733
Jamie Madill876429b2017-04-20 15:46:24 -04004734bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004735{
4736 if (context->getExtensions().webglCompatibility && zNear > zFar)
4737 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004739 return false;
4740 }
4741
4742 return true;
4743}
4744
Jamie Madille8fb6402017-02-14 17:56:40 -05004745bool ValidateRenderbufferStorage(ValidationContext *context,
4746 GLenum target,
4747 GLenum internalformat,
4748 GLsizei width,
4749 GLsizei height)
4750{
4751 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4752 height);
4753}
4754
4755bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4756 GLenum target,
4757 GLsizei samples,
4758 GLenum internalformat,
4759 GLsizei width,
4760 GLsizei height)
4761{
4762 if (!context->getExtensions().framebufferMultisample)
4763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004764 context->handleError(InvalidOperation()
4765 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004766 return false;
4767 }
4768
4769 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4770 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4771 // generated.
4772 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004774 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004775 return false;
4776 }
4777
4778 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4779 // the specified storage. This is different than ES 3.0 in which a sample number higher
4780 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4781 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4782 if (context->getClientMajorVersion() >= 3)
4783 {
4784 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4785 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004787 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004788 return false;
4789 }
4790 }
4791
4792 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4793 width, height);
4794}
4795
Jamie Madillc1d770e2017-04-13 17:31:24 -04004796bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4797{
Geoff Lange8afa902017-09-27 15:00:43 -04004798 if (!ValidFramebufferTarget(context, target))
Jamie Madillc1d770e2017-04-13 17:31:24 -04004799 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004801 return false;
4802 }
4803
4804 return true;
4805}
4806
4807bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004808 GLfloat red,
4809 GLfloat green,
4810 GLfloat blue,
4811 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004812{
4813 return true;
4814}
4815
Jamie Madill876429b2017-04-20 15:46:24 -04004816bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004817{
4818 return true;
4819}
4820
4821bool ValidateClearStencil(ValidationContext *context, GLint s)
4822{
4823 return true;
4824}
4825
4826bool ValidateColorMask(ValidationContext *context,
4827 GLboolean red,
4828 GLboolean green,
4829 GLboolean blue,
4830 GLboolean alpha)
4831{
4832 return true;
4833}
4834
4835bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4836{
4837 return true;
4838}
4839
4840bool ValidateCreateProgram(ValidationContext *context)
4841{
4842 return true;
4843}
4844
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004845bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004846{
4847 switch (mode)
4848 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004849 case CullFaceMode::Front:
4850 case CullFaceMode::Back:
4851 case CullFaceMode::FrontAndBack:
Jamie Madillc1d770e2017-04-13 17:31:24 -04004852 break;
4853
4854 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004856 return false;
4857 }
4858
4859 return true;
4860}
4861
4862bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4863{
4864 if (program == 0)
4865 {
4866 return false;
4867 }
4868
4869 if (!context->getProgram(program))
4870 {
4871 if (context->getShader(program))
4872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004874 return false;
4875 }
4876 else
4877 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004878 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004879 return false;
4880 }
4881 }
4882
4883 return true;
4884}
4885
4886bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4887{
4888 if (shader == 0)
4889 {
4890 return false;
4891 }
4892
4893 if (!context->getShader(shader))
4894 {
4895 if (context->getProgram(shader))
4896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004898 return false;
4899 }
4900 else
4901 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004902 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004903 return false;
4904 }
4905 }
4906
4907 return true;
4908}
4909
4910bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4911{
4912 switch (func)
4913 {
4914 case GL_NEVER:
4915 case GL_ALWAYS:
4916 case GL_LESS:
4917 case GL_LEQUAL:
4918 case GL_EQUAL:
4919 case GL_GREATER:
4920 case GL_GEQUAL:
4921 case GL_NOTEQUAL:
4922 break;
4923
4924 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004926 return false;
4927 }
4928
4929 return true;
4930}
4931
4932bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4933{
4934 return true;
4935}
4936
4937bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4938{
4939 Program *programObject = GetValidProgram(context, program);
4940 if (!programObject)
4941 {
4942 return false;
4943 }
4944
4945 Shader *shaderObject = GetValidShader(context, shader);
4946 if (!shaderObject)
4947 {
4948 return false;
4949 }
4950
4951 const Shader *attachedShader = nullptr;
4952
4953 switch (shaderObject->getType())
4954 {
4955 case GL_VERTEX_SHADER:
4956 {
4957 attachedShader = programObject->getAttachedVertexShader();
4958 break;
4959 }
4960 case GL_FRAGMENT_SHADER:
4961 {
4962 attachedShader = programObject->getAttachedFragmentShader();
4963 break;
4964 }
4965 case GL_COMPUTE_SHADER:
4966 {
4967 attachedShader = programObject->getAttachedComputeShader();
4968 break;
4969 }
4970 default:
4971 UNREACHABLE();
4972 return false;
4973 }
4974
4975 if (attachedShader != shaderObject)
4976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004978 return false;
4979 }
4980
4981 return true;
4982}
4983
4984bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4985{
4986 if (index >= MAX_VERTEX_ATTRIBS)
4987 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004988 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004989 return false;
4990 }
4991
4992 return true;
4993}
4994
4995bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4996{
4997 if (index >= MAX_VERTEX_ATTRIBS)
4998 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004999 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005000 return false;
5001 }
5002
5003 return true;
5004}
5005
5006bool ValidateFinish(ValidationContext *context)
5007{
5008 return true;
5009}
5010
5011bool ValidateFlush(ValidationContext *context)
5012{
5013 return true;
5014}
5015
5016bool ValidateFrontFace(ValidationContext *context, GLenum mode)
5017{
5018 switch (mode)
5019 {
5020 case GL_CW:
5021 case GL_CCW:
5022 break;
5023 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005024 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005025 return false;
5026 }
5027
5028 return true;
5029}
5030
5031bool ValidateGetActiveAttrib(ValidationContext *context,
5032 GLuint program,
5033 GLuint index,
5034 GLsizei bufsize,
5035 GLsizei *length,
5036 GLint *size,
5037 GLenum *type,
5038 GLchar *name)
5039{
5040 if (bufsize < 0)
5041 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005042 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005043 return false;
5044 }
5045
5046 Program *programObject = GetValidProgram(context, program);
5047
5048 if (!programObject)
5049 {
5050 return false;
5051 }
5052
5053 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5054 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005055 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005056 return false;
5057 }
5058
5059 return true;
5060}
5061
5062bool ValidateGetActiveUniform(ValidationContext *context,
5063 GLuint program,
5064 GLuint index,
5065 GLsizei bufsize,
5066 GLsizei *length,
5067 GLint *size,
5068 GLenum *type,
5069 GLchar *name)
5070{
5071 if (bufsize < 0)
5072 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005073 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005074 return false;
5075 }
5076
5077 Program *programObject = GetValidProgram(context, program);
5078
5079 if (!programObject)
5080 {
5081 return false;
5082 }
5083
5084 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5085 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005086 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005087 return false;
5088 }
5089
5090 return true;
5091}
5092
5093bool ValidateGetAttachedShaders(ValidationContext *context,
5094 GLuint program,
5095 GLsizei maxcount,
5096 GLsizei *count,
5097 GLuint *shaders)
5098{
5099 if (maxcount < 0)
5100 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005101 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005102 return false;
5103 }
5104
5105 Program *programObject = GetValidProgram(context, program);
5106
5107 if (!programObject)
5108 {
5109 return false;
5110 }
5111
5112 return true;
5113}
5114
5115bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5116{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005117 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5118 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005119 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005121 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005122 return false;
5123 }
5124
Jamie Madillc1d770e2017-04-13 17:31:24 -04005125 Program *programObject = GetValidProgram(context, program);
5126
5127 if (!programObject)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005130 return false;
5131 }
5132
5133 if (!programObject->isLinked())
5134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005136 return false;
5137 }
5138
5139 return true;
5140}
5141
5142bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5143{
5144 GLenum nativeType;
5145 unsigned int numParams = 0;
5146 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5147}
5148
5149bool ValidateGetError(ValidationContext *context)
5150{
5151 return true;
5152}
5153
5154bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5155{
5156 GLenum nativeType;
5157 unsigned int numParams = 0;
5158 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5159}
5160
5161bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5162{
5163 GLenum nativeType;
5164 unsigned int numParams = 0;
5165 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5166}
5167
5168bool ValidateGetProgramInfoLog(ValidationContext *context,
5169 GLuint program,
5170 GLsizei bufsize,
5171 GLsizei *length,
5172 GLchar *infolog)
5173{
5174 if (bufsize < 0)
5175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005177 return false;
5178 }
5179
5180 Program *programObject = GetValidProgram(context, program);
5181 if (!programObject)
5182 {
5183 return false;
5184 }
5185
5186 return true;
5187}
5188
5189bool ValidateGetShaderInfoLog(ValidationContext *context,
5190 GLuint shader,
5191 GLsizei bufsize,
5192 GLsizei *length,
5193 GLchar *infolog)
5194{
5195 if (bufsize < 0)
5196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005197 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005198 return false;
5199 }
5200
5201 Shader *shaderObject = GetValidShader(context, shader);
5202 if (!shaderObject)
5203 {
5204 return false;
5205 }
5206
5207 return true;
5208}
5209
5210bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5211 GLenum shadertype,
5212 GLenum precisiontype,
5213 GLint *range,
5214 GLint *precision)
5215{
5216 switch (shadertype)
5217 {
5218 case GL_VERTEX_SHADER:
5219 case GL_FRAGMENT_SHADER:
5220 break;
5221 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005222 context->handleError(InvalidOperation()
5223 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005224 return false;
5225 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005227 return false;
5228 }
5229
5230 switch (precisiontype)
5231 {
5232 case GL_LOW_FLOAT:
5233 case GL_MEDIUM_FLOAT:
5234 case GL_HIGH_FLOAT:
5235 case GL_LOW_INT:
5236 case GL_MEDIUM_INT:
5237 case GL_HIGH_INT:
5238 break;
5239
5240 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005241 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005242 return false;
5243 }
5244
5245 return true;
5246}
5247
5248bool ValidateGetShaderSource(ValidationContext *context,
5249 GLuint shader,
5250 GLsizei bufsize,
5251 GLsizei *length,
5252 GLchar *source)
5253{
5254 if (bufsize < 0)
5255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005256 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005257 return false;
5258 }
5259
5260 Shader *shaderObject = GetValidShader(context, shader);
5261 if (!shaderObject)
5262 {
5263 return false;
5264 }
5265
5266 return true;
5267}
5268
5269bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5270{
5271 if (strstr(name, "gl_") == name)
5272 {
5273 return false;
5274 }
5275
Geoff Langfc32e8b2017-05-31 14:16:59 -04005276 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5277 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005278 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005281 return false;
5282 }
5283
Jamie Madillc1d770e2017-04-13 17:31:24 -04005284 Program *programObject = GetValidProgram(context, program);
5285
5286 if (!programObject)
5287 {
5288 return false;
5289 }
5290
5291 if (!programObject->isLinked())
5292 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005294 return false;
5295 }
5296
5297 return true;
5298}
5299
5300bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5301{
5302 switch (mode)
5303 {
5304 case GL_FASTEST:
5305 case GL_NICEST:
5306 case GL_DONT_CARE:
5307 break;
5308
5309 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005311 return false;
5312 }
5313
5314 switch (target)
5315 {
5316 case GL_GENERATE_MIPMAP_HINT:
5317 break;
5318
Geoff Lange7bd2182017-06-16 16:13:13 -04005319 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5320 if (context->getClientVersion() < ES_3_0 &&
5321 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005322 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005323 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005324 return false;
5325 }
5326 break;
5327
5328 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005329 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005330 return false;
5331 }
5332
5333 return true;
5334}
5335
5336bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5337{
5338 return true;
5339}
5340
5341bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5342{
5343 return true;
5344}
5345
5346bool ValidateIsProgram(ValidationContext *context, GLuint program)
5347{
5348 return true;
5349}
5350
5351bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5352{
5353 return true;
5354}
5355
5356bool ValidateIsShader(ValidationContext *context, GLuint shader)
5357{
5358 return true;
5359}
5360
5361bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5362{
5363 return true;
5364}
5365
5366bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5367{
5368 if (context->getClientMajorVersion() < 3)
5369 {
5370 switch (pname)
5371 {
5372 case GL_UNPACK_IMAGE_HEIGHT:
5373 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005374 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005375 return false;
5376
5377 case GL_UNPACK_ROW_LENGTH:
5378 case GL_UNPACK_SKIP_ROWS:
5379 case GL_UNPACK_SKIP_PIXELS:
5380 if (!context->getExtensions().unpackSubimage)
5381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005382 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005383 return false;
5384 }
5385 break;
5386
5387 case GL_PACK_ROW_LENGTH:
5388 case GL_PACK_SKIP_ROWS:
5389 case GL_PACK_SKIP_PIXELS:
5390 if (!context->getExtensions().packSubimage)
5391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005392 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005393 return false;
5394 }
5395 break;
5396 }
5397 }
5398
5399 if (param < 0)
5400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005401 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005402 return false;
5403 }
5404
5405 switch (pname)
5406 {
5407 case GL_UNPACK_ALIGNMENT:
5408 if (param != 1 && param != 2 && param != 4 && param != 8)
5409 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005410 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005411 return false;
5412 }
5413 break;
5414
5415 case GL_PACK_ALIGNMENT:
5416 if (param != 1 && param != 2 && param != 4 && param != 8)
5417 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005418 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005419 return false;
5420 }
5421 break;
5422
5423 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005424 if (!context->getExtensions().packReverseRowOrder)
5425 {
5426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5427 }
5428 break;
5429
Jamie Madillc1d770e2017-04-13 17:31:24 -04005430 case GL_UNPACK_ROW_LENGTH:
5431 case GL_UNPACK_IMAGE_HEIGHT:
5432 case GL_UNPACK_SKIP_IMAGES:
5433 case GL_UNPACK_SKIP_ROWS:
5434 case GL_UNPACK_SKIP_PIXELS:
5435 case GL_PACK_ROW_LENGTH:
5436 case GL_PACK_SKIP_ROWS:
5437 case GL_PACK_SKIP_PIXELS:
5438 break;
5439
5440 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005441 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005442 return false;
5443 }
5444
5445 return true;
5446}
5447
5448bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5449{
5450 return true;
5451}
5452
5453bool ValidateReleaseShaderCompiler(ValidationContext *context)
5454{
5455 return true;
5456}
5457
Jamie Madill876429b2017-04-20 15:46:24 -04005458bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005459{
5460 return true;
5461}
5462
5463bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5464{
5465 if (width < 0 || height < 0)
5466 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005467 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005468 return false;
5469 }
5470
5471 return true;
5472}
5473
5474bool ValidateShaderBinary(ValidationContext *context,
5475 GLsizei n,
5476 const GLuint *shaders,
5477 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005478 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005479 GLsizei length)
5480{
5481 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5482 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5483 shaderBinaryFormats.end())
5484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005485 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005486 return false;
5487 }
5488
5489 return true;
5490}
5491
5492bool ValidateShaderSource(ValidationContext *context,
5493 GLuint shader,
5494 GLsizei count,
5495 const GLchar *const *string,
5496 const GLint *length)
5497{
5498 if (count < 0)
5499 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005500 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005501 return false;
5502 }
5503
Geoff Langfc32e8b2017-05-31 14:16:59 -04005504 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5505 // shader-related entry points
5506 if (context->getExtensions().webglCompatibility)
5507 {
5508 for (GLsizei i = 0; i < count; i++)
5509 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005510 size_t len =
5511 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005512
5513 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005514 if (!IsValidESSLShaderSourceString(string[i], len,
5515 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005516 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005517 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005518 return false;
5519 }
5520 }
5521 }
5522
Jamie Madillc1d770e2017-04-13 17:31:24 -04005523 Shader *shaderObject = GetValidShader(context, shader);
5524 if (!shaderObject)
5525 {
5526 return false;
5527 }
5528
5529 return true;
5530}
5531
5532bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5533{
5534 if (!IsValidStencilFunc(func))
5535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005537 return false;
5538 }
5539
5540 return true;
5541}
5542
5543bool ValidateStencilFuncSeparate(ValidationContext *context,
5544 GLenum face,
5545 GLenum func,
5546 GLint ref,
5547 GLuint mask)
5548{
5549 if (!IsValidStencilFace(face))
5550 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005551 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005552 return false;
5553 }
5554
5555 if (!IsValidStencilFunc(func))
5556 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005558 return false;
5559 }
5560
5561 return true;
5562}
5563
5564bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5565{
5566 return true;
5567}
5568
5569bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5570{
5571 if (!IsValidStencilFace(face))
5572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005574 return false;
5575 }
5576
5577 return true;
5578}
5579
5580bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5581{
5582 if (!IsValidStencilOp(fail))
5583 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005584 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005585 return false;
5586 }
5587
5588 if (!IsValidStencilOp(zfail))
5589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005591 return false;
5592 }
5593
5594 if (!IsValidStencilOp(zpass))
5595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005597 return false;
5598 }
5599
5600 return true;
5601}
5602
5603bool ValidateStencilOpSeparate(ValidationContext *context,
5604 GLenum face,
5605 GLenum fail,
5606 GLenum zfail,
5607 GLenum zpass)
5608{
5609 if (!IsValidStencilFace(face))
5610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005612 return false;
5613 }
5614
5615 return ValidateStencilOp(context, fail, zfail, zpass);
5616}
5617
5618bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5619{
5620 return ValidateUniform(context, GL_FLOAT, location, 1);
5621}
5622
5623bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5624{
5625 return ValidateUniform(context, GL_FLOAT, location, count);
5626}
5627
Jamie Madillbe849e42017-05-02 15:49:00 -04005628bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5629{
5630 return ValidateUniform1iv(context, location, 1, &x);
5631}
5632
Jamie Madillc1d770e2017-04-13 17:31:24 -04005633bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5634{
5635 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5636}
5637
5638bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5639{
5640 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5641}
5642
5643bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5644{
5645 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5646}
5647
5648bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5649{
5650 return ValidateUniform(context, GL_INT_VEC2, location, count);
5651}
5652
5653bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5654{
5655 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5656}
5657
5658bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5659{
5660 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5661}
5662
5663bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5664{
5665 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5666}
5667
5668bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5669{
5670 return ValidateUniform(context, GL_INT_VEC3, location, count);
5671}
5672
5673bool ValidateUniform4f(ValidationContext *context,
5674 GLint location,
5675 GLfloat x,
5676 GLfloat y,
5677 GLfloat z,
5678 GLfloat w)
5679{
5680 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5681}
5682
5683bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5684{
5685 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5686}
5687
5688bool ValidateUniform4i(ValidationContext *context,
5689 GLint location,
5690 GLint x,
5691 GLint y,
5692 GLint z,
5693 GLint w)
5694{
5695 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5696}
5697
5698bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5699{
5700 return ValidateUniform(context, GL_INT_VEC4, location, count);
5701}
5702
5703bool ValidateUniformMatrix2fv(ValidationContext *context,
5704 GLint location,
5705 GLsizei count,
5706 GLboolean transpose,
5707 const GLfloat *value)
5708{
5709 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5710}
5711
5712bool ValidateUniformMatrix3fv(ValidationContext *context,
5713 GLint location,
5714 GLsizei count,
5715 GLboolean transpose,
5716 const GLfloat *value)
5717{
5718 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5719}
5720
5721bool ValidateUniformMatrix4fv(ValidationContext *context,
5722 GLint location,
5723 GLsizei count,
5724 GLboolean transpose,
5725 const GLfloat *value)
5726{
5727 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5728}
5729
5730bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5731{
5732 Program *programObject = GetValidProgram(context, program);
5733
5734 if (!programObject)
5735 {
5736 return false;
5737 }
5738
5739 return true;
5740}
5741
Jamie Madillc1d770e2017-04-13 17:31:24 -04005742bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5743{
5744 return ValidateVertexAttribIndex(context, index);
5745}
5746
5747bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5748{
5749 return ValidateVertexAttribIndex(context, index);
5750}
5751
5752bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5753{
5754 return ValidateVertexAttribIndex(context, index);
5755}
5756
5757bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5758{
5759 return ValidateVertexAttribIndex(context, index);
5760}
5761
5762bool ValidateVertexAttrib3f(ValidationContext *context,
5763 GLuint index,
5764 GLfloat x,
5765 GLfloat y,
5766 GLfloat z)
5767{
5768 return ValidateVertexAttribIndex(context, index);
5769}
5770
5771bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5772{
5773 return ValidateVertexAttribIndex(context, index);
5774}
5775
5776bool ValidateVertexAttrib4f(ValidationContext *context,
5777 GLuint index,
5778 GLfloat x,
5779 GLfloat y,
5780 GLfloat z,
5781 GLfloat w)
5782{
5783 return ValidateVertexAttribIndex(context, index);
5784}
5785
5786bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5787{
5788 return ValidateVertexAttribIndex(context, index);
5789}
5790
5791bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5792{
5793 if (width < 0 || height < 0)
5794 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005795 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005796 return false;
5797 }
5798
5799 return true;
5800}
5801
5802bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5803{
5804 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5805}
5806
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005807bool ValidateDrawElements(ValidationContext *context,
5808 GLenum mode,
5809 GLsizei count,
5810 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005811 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005812{
5813 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5814}
5815
Jamie Madillbe849e42017-05-02 15:49:00 -04005816bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5817 GLenum target,
5818 GLenum attachment,
5819 GLenum pname,
5820 GLint *params)
5821{
5822 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5823 nullptr);
5824}
5825
5826bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5827{
5828 return ValidateGetProgramivBase(context, program, pname, nullptr);
5829}
5830
5831bool ValidateCopyTexImage2D(ValidationContext *context,
5832 GLenum target,
5833 GLint level,
5834 GLenum internalformat,
5835 GLint x,
5836 GLint y,
5837 GLsizei width,
5838 GLsizei height,
5839 GLint border)
5840{
5841 if (context->getClientMajorVersion() < 3)
5842 {
5843 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5844 0, x, y, width, height, border);
5845 }
5846
5847 ASSERT(context->getClientMajorVersion() == 3);
5848 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5849 0, x, y, width, height, border);
5850}
5851
5852bool ValidateCopyTexSubImage2D(Context *context,
5853 GLenum target,
5854 GLint level,
5855 GLint xoffset,
5856 GLint yoffset,
5857 GLint x,
5858 GLint y,
5859 GLsizei width,
5860 GLsizei height)
5861{
5862 if (context->getClientMajorVersion() < 3)
5863 {
5864 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5865 yoffset, x, y, width, height, 0);
5866 }
5867
5868 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5869 yoffset, 0, x, y, width, height, 0);
5870}
5871
5872bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5873{
5874 return ValidateGenOrDelete(context, n);
5875}
5876
5877bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5878{
5879 return ValidateGenOrDelete(context, n);
5880}
5881
5882bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5883{
5884 return ValidateGenOrDelete(context, n);
5885}
5886
5887bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5888{
5889 return ValidateGenOrDelete(context, n);
5890}
5891
5892bool ValidateDisable(Context *context, GLenum cap)
5893{
5894 if (!ValidCap(context, cap, false))
5895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005896 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 return false;
5898 }
5899
5900 return true;
5901}
5902
5903bool ValidateEnable(Context *context, GLenum cap)
5904{
5905 if (!ValidCap(context, cap, false))
5906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 return false;
5909 }
5910
5911 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5912 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5913 {
5914 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005915 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005916
5917 // We also output an error message to the debugger window if tracing is active, so that
5918 // developers can see the error message.
5919 ERR() << errorMessage;
5920 return false;
5921 }
5922
5923 return true;
5924}
5925
5926bool ValidateFramebufferRenderbuffer(Context *context,
5927 GLenum target,
5928 GLenum attachment,
5929 GLenum renderbuffertarget,
5930 GLuint renderbuffer)
5931{
Geoff Lange8afa902017-09-27 15:00:43 -04005932 if (!ValidFramebufferTarget(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005933 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005934 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5935 return false;
5936 }
5937
5938 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5939 {
5940 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005941 return false;
5942 }
5943
5944 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5945 renderbuffertarget, renderbuffer);
5946}
5947
5948bool ValidateFramebufferTexture2D(Context *context,
5949 GLenum target,
5950 GLenum attachment,
5951 GLenum textarget,
5952 GLuint texture,
5953 GLint level)
5954{
5955 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5956 // extension
5957 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5958 level != 0)
5959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005960 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005961 return false;
5962 }
5963
5964 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5965 {
5966 return false;
5967 }
5968
5969 if (texture != 0)
5970 {
5971 gl::Texture *tex = context->getTexture(texture);
5972 ASSERT(tex);
5973
5974 const gl::Caps &caps = context->getCaps();
5975
5976 switch (textarget)
5977 {
5978 case GL_TEXTURE_2D:
5979 {
5980 if (level > gl::log2(caps.max2DTextureSize))
5981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005982 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 return false;
5984 }
5985 if (tex->getTarget() != GL_TEXTURE_2D)
5986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005988 return false;
5989 }
5990 }
5991 break;
5992
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005993 case GL_TEXTURE_RECTANGLE_ANGLE:
5994 {
5995 if (level != 0)
5996 {
5997 context->handleError(InvalidValue());
5998 return false;
5999 }
6000 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
6001 {
6002 context->handleError(InvalidOperation()
6003 << "Textarget must match the texture target type.");
6004 return false;
6005 }
6006 }
6007 break;
6008
Jamie Madillbe849e42017-05-02 15:49:00 -04006009 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
6010 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
6011 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
6012 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
6013 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
6014 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
6015 {
6016 if (level > gl::log2(caps.maxCubeMapTextureSize))
6017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006018 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04006019 return false;
6020 }
6021 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
6022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006023 context->handleError(InvalidOperation()
6024 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 return false;
6026 }
6027 }
6028 break;
6029
6030 case GL_TEXTURE_2D_MULTISAMPLE:
6031 {
6032 if (context->getClientVersion() < ES_3_1)
6033 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04006035 return false;
6036 }
6037
6038 if (level != 0)
6039 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006040 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04006041 return false;
6042 }
6043 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
6044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006045 context->handleError(InvalidOperation()
6046 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006047 return false;
6048 }
6049 }
6050 break;
6051
6052 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006054 return false;
6055 }
6056
6057 const Format &format = tex->getFormat(textarget, level);
6058 if (format.info->compressed)
6059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006060 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 return false;
6062 }
6063 }
6064
6065 return true;
6066}
6067
6068bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6069{
6070 return ValidateGenOrDelete(context, n);
6071}
6072
6073bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6074{
6075 return ValidateGenOrDelete(context, n);
6076}
6077
6078bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6079{
6080 return ValidateGenOrDelete(context, n);
6081}
6082
6083bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6084{
6085 return ValidateGenOrDelete(context, n);
6086}
6087
6088bool ValidateGenerateMipmap(Context *context, GLenum target)
6089{
6090 if (!ValidTextureTarget(context, target))
6091 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006093 return false;
6094 }
6095
6096 Texture *texture = context->getTargetTexture(target);
6097
6098 if (texture == nullptr)
6099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006101 return false;
6102 }
6103
6104 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6105
6106 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6107 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6108 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006110 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006111 return false;
6112 }
6113
6114 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006115 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6116 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6117 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006118 {
6119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6120 return false;
6121 }
6122
Geoff Lang536eca12017-09-13 11:23:35 -04006123 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6124 bool formatUnsized = !format.sized;
6125 bool formatColorRenderableAndFilterable =
6126 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6127 format.renderSupport(context->getClientVersion(), context->getExtensions());
6128 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006129 {
Geoff Lang536eca12017-09-13 11:23:35 -04006130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006131 return false;
6132 }
6133
Geoff Lang536eca12017-09-13 11:23:35 -04006134 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6135 // generation
6136 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6137 {
6138 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6139 return false;
6140 }
6141
6142 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6143 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006144 bool supportsSRGBMipmapGeneration =
6145 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006146 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006147 {
Geoff Lang536eca12017-09-13 11:23:35 -04006148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006149 return false;
6150 }
6151
6152 // Non-power of 2 ES2 check
6153 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6154 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6155 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6156 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006157 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6158 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006160 return false;
6161 }
6162
6163 // Cube completeness check
6164 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006167 return false;
6168 }
6169
6170 return true;
6171}
6172
6173bool ValidateGetBufferParameteriv(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04006174 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04006175 GLenum pname,
6176 GLint *params)
6177{
6178 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6179}
6180
6181bool ValidateGetRenderbufferParameteriv(Context *context,
6182 GLenum target,
6183 GLenum pname,
6184 GLint *params)
6185{
6186 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6187}
6188
6189bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6190{
6191 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6192}
6193
6194bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6195{
6196 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6197}
6198
6199bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6200{
6201 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6202}
6203
6204bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6205{
6206 return ValidateGetUniformBase(context, program, location);
6207}
6208
6209bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6210{
6211 return ValidateGetUniformBase(context, program, location);
6212}
6213
6214bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6215{
6216 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6217}
6218
6219bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6220{
6221 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6222}
6223
6224bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6225{
6226 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6227}
6228
6229bool ValidateIsEnabled(Context *context, GLenum cap)
6230{
6231 if (!ValidCap(context, cap, true))
6232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006233 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006234 return false;
6235 }
6236
6237 return true;
6238}
6239
6240bool ValidateLinkProgram(Context *context, GLuint program)
6241{
6242 if (context->hasActiveTransformFeedback(program))
6243 {
6244 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006245 context->handleError(InvalidOperation() << "Cannot link program while program is "
6246 "associated with an active transform "
6247 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006248 return false;
6249 }
6250
6251 Program *programObject = GetValidProgram(context, program);
6252 if (!programObject)
6253 {
6254 return false;
6255 }
6256
6257 return true;
6258}
6259
Jamie Madill4928b7c2017-06-20 12:57:39 -04006260bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006261 GLint x,
6262 GLint y,
6263 GLsizei width,
6264 GLsizei height,
6265 GLenum format,
6266 GLenum type,
6267 void *pixels)
6268{
6269 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6270 nullptr, pixels);
6271}
6272
6273bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6274{
6275 return ValidateTexParameterBase(context, target, pname, -1, &param);
6276}
6277
6278bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6279{
6280 return ValidateTexParameterBase(context, target, pname, -1, params);
6281}
6282
6283bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6284{
6285 return ValidateTexParameterBase(context, target, pname, -1, &param);
6286}
6287
6288bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6289{
6290 return ValidateTexParameterBase(context, target, pname, -1, params);
6291}
6292
6293bool ValidateUseProgram(Context *context, GLuint program)
6294{
6295 if (program != 0)
6296 {
6297 Program *programObject = context->getProgram(program);
6298 if (!programObject)
6299 {
6300 // ES 3.1.0 section 7.3 page 72
6301 if (context->getShader(program))
6302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006303 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006304 return false;
6305 }
6306 else
6307 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006308 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006309 return false;
6310 }
6311 }
6312 if (!programObject->isLinked())
6313 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006314 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006315 return false;
6316 }
6317 }
6318 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6319 {
6320 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006321 context
6322 ->handleError(InvalidOperation()
6323 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006324 return false;
6325 }
6326
6327 return true;
6328}
6329
Jamie Madillc29968b2016-01-20 11:17:23 -05006330} // namespace gl