blob: a997e03dd67a34cb95d5d74e5cbf4bcf4aca969b [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 Lang4f0e0032017-05-01 16:04:35 -0400309bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, 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 return textureType == GL_TEXTURE_2D;
315
316 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
317 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
318 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
319 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
320 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
321 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
322 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700323
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400324 case GL_TEXTURE_RECTANGLE_ANGLE:
325 return textureType == GL_TEXTURE_RECTANGLE_ANGLE &&
326 context->getExtensions().textureRectangle;
Geoff Lang97073d12016-04-20 10:42:34 -0700327
328 default:
329 return false;
330 }
331}
332
333bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
334{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400335 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700336 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400337 case GL_TEXTURE_2D:
338 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400339 case GL_TEXTURE_RECTANGLE_ANGLE:
340 return context->getExtensions().textureRectangle;
Geoff Lang4f0e0032017-05-01 16:04:35 -0400341
342 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
343 // supported
344
345 default:
346 return false;
347 }
348}
349
350bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
351{
Geoff Lang3847f942017-07-12 11:17:28 -0400352 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400353 {
354 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700355 }
356
Geoff Lang4f0e0032017-05-01 16:04:35 -0400357 if (level > 0 && context->getClientVersion() < ES_3_0)
358 {
359 return false;
360 }
Geoff Lang97073d12016-04-20 10:42:34 -0700361
Geoff Lang4f0e0032017-05-01 16:04:35 -0400362 return true;
363}
364
365bool IsValidCopyTextureDestinationLevel(Context *context,
366 GLenum target,
367 GLint level,
368 GLsizei width,
369 GLsizei height)
370{
Geoff Lang3847f942017-07-12 11:17:28 -0400371 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400372 {
373 return false;
374 }
375
Geoff Lang4f0e0032017-05-01 16:04:35 -0400376 const Caps &caps = context->getCaps();
377 if (target == GL_TEXTURE_2D)
378 {
379 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
380 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
381 {
382 return false;
383 }
384 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400385 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
386 {
387 ASSERT(level == 0);
388 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
389 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
390 {
391 return false;
392 }
393 }
Geoff Lang4f0e0032017-05-01 16:04:35 -0400394 else if (IsCubeMapTextureTarget(target))
395 {
396 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
397 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
398 {
399 return false;
400 }
401 }
402
403 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700404}
405
Jamie Madillc1d770e2017-04-13 17:31:24 -0400406bool IsValidStencilFunc(GLenum func)
407{
408 switch (func)
409 {
410 case GL_NEVER:
411 case GL_ALWAYS:
412 case GL_LESS:
413 case GL_LEQUAL:
414 case GL_EQUAL:
415 case GL_GEQUAL:
416 case GL_GREATER:
417 case GL_NOTEQUAL:
418 return true;
419
420 default:
421 return false;
422 }
423}
424
425bool IsValidStencilFace(GLenum face)
426{
427 switch (face)
428 {
429 case GL_FRONT:
430 case GL_BACK:
431 case GL_FRONT_AND_BACK:
432 return true;
433
434 default:
435 return false;
436 }
437}
438
439bool IsValidStencilOp(GLenum op)
440{
441 switch (op)
442 {
443 case GL_ZERO:
444 case GL_KEEP:
445 case GL_REPLACE:
446 case GL_INCR:
447 case GL_DECR:
448 case GL_INVERT:
449 case GL_INCR_WRAP:
450 case GL_DECR_WRAP:
451 return true;
452
453 default:
454 return false;
455 }
456}
457
Jamie Madillbe849e42017-05-02 15:49:00 -0400458bool ValidateES2CopyTexImageParameters(ValidationContext *context,
459 GLenum target,
460 GLint level,
461 GLenum internalformat,
462 bool isSubImage,
463 GLint xoffset,
464 GLint yoffset,
465 GLint x,
466 GLint y,
467 GLsizei width,
468 GLsizei height,
469 GLint border)
470{
471 if (!ValidTexture2DDestinationTarget(context, target))
472 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400474 return false;
475 }
476
477 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500479 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400480 return false;
481 }
482
483 Format textureFormat = Format::Invalid();
484 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
485 xoffset, yoffset, 0, x, y, width, height, border,
486 &textureFormat))
487 {
488 return false;
489 }
490
491 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
492 GLenum colorbufferFormat =
493 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
494 const auto &formatInfo = *textureFormat.info;
495
496 // [OpenGL ES 2.0.24] table 3.9
497 if (isSubImage)
498 {
499 switch (formatInfo.format)
500 {
501 case GL_ALPHA:
502 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400503 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
504 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400505 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700506 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400507 return false;
508 }
509 break;
510 case GL_LUMINANCE:
511 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
512 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
513 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400514 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
515 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400516 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400518 return false;
519 }
520 break;
521 case GL_RED_EXT:
522 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
523 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
524 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
525 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
526 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400527 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
528 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400529 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400531 return false;
532 }
533 break;
534 case GL_RG_EXT:
535 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
536 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
537 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
538 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400539 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
540 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400541 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700542 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400543 return false;
544 }
545 break;
546 case GL_RGB:
547 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
548 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
549 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400550 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
551 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400552 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700553 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400554 return false;
555 }
556 break;
557 case GL_LUMINANCE_ALPHA:
558 case GL_RGBA:
559 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400560 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
561 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700563 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400564 return false;
565 }
566 break;
567 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
568 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
569 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
570 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
571 case GL_ETC1_RGB8_OES:
572 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
573 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
574 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
575 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
576 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400578 return false;
579 case GL_DEPTH_COMPONENT:
580 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400582 return false;
583 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700584 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400585 return false;
586 }
587
588 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
589 {
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 }
593 }
594 else
595 {
596 switch (internalformat)
597 {
598 case GL_ALPHA:
599 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
600 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
601 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
602 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700603 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400604 return false;
605 }
606 break;
607 case GL_LUMINANCE:
608 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
609 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
610 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
611 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
612 colorbufferFormat != GL_BGR5_A1_ANGLEX)
613 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700614 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400615 return false;
616 }
617 break;
618 case GL_RED_EXT:
619 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
620 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
621 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
622 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
623 colorbufferFormat != GL_BGR5_A1_ANGLEX)
624 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 return false;
627 }
628 break;
629 case GL_RG_EXT:
630 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
631 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
632 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
633 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
634 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400636 return false;
637 }
638 break;
639 case GL_RGB:
640 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
641 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
642 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
643 colorbufferFormat != GL_BGR5_A1_ANGLEX)
644 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700645 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400646 return false;
647 }
648 break;
649 case GL_LUMINANCE_ALPHA:
650 case GL_RGBA:
651 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
652 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
653 colorbufferFormat != GL_BGR5_A1_ANGLEX)
654 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400656 return false;
657 }
658 break;
659 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
660 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
661 if (context->getExtensions().textureCompressionDXT1)
662 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 return false;
665 }
666 else
667 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400669 return false;
670 }
671 break;
672 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
673 if (context->getExtensions().textureCompressionDXT3)
674 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400676 return false;
677 }
678 else
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400681 return false;
682 }
683 break;
684 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
685 if (context->getExtensions().textureCompressionDXT5)
686 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400688 return false;
689 }
690 else
691 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700692 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400693 return false;
694 }
695 break;
696 case GL_ETC1_RGB8_OES:
697 if (context->getExtensions().compressedETC1RGB8Texture)
698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400700 return false;
701 }
702 else
703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500704 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400705 return false;
706 }
707 break;
708 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
709 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
710 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
711 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
712 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
713 if (context->getExtensions().lossyETCDecode)
714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500715 context->handleError(InvalidOperation()
716 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400717 return false;
718 }
719 else
720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500721 context->handleError(InvalidEnum()
722 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 break;
726 case GL_DEPTH_COMPONENT:
727 case GL_DEPTH_COMPONENT16:
728 case GL_DEPTH_COMPONENT32_OES:
729 case GL_DEPTH_STENCIL_OES:
730 case GL_DEPTH24_STENCIL8_OES:
731 if (context->getExtensions().depthTextures)
732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500733 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400734 return false;
735 }
736 else
737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500738 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400739 return false;
740 }
741 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500742 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400743 return false;
744 }
745 }
746
747 // If width or height is zero, it is a no-op. Return false without setting an error.
748 return (width > 0 && height > 0);
749}
750
751bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
752{
753 switch (cap)
754 {
755 // EXT_multisample_compatibility
756 case GL_MULTISAMPLE_EXT:
757 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
758 return context->getExtensions().multisampleCompatibility;
759
760 case GL_CULL_FACE:
761 case GL_POLYGON_OFFSET_FILL:
762 case GL_SAMPLE_ALPHA_TO_COVERAGE:
763 case GL_SAMPLE_COVERAGE:
764 case GL_SCISSOR_TEST:
765 case GL_STENCIL_TEST:
766 case GL_DEPTH_TEST:
767 case GL_BLEND:
768 case GL_DITHER:
769 return true;
770
771 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
772 case GL_RASTERIZER_DISCARD:
773 return (context->getClientMajorVersion() >= 3);
774
775 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
776 case GL_DEBUG_OUTPUT:
777 return context->getExtensions().debug;
778
779 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
780 return queryOnly && context->getExtensions().bindGeneratesResource;
781
782 case GL_CLIENT_ARRAYS_ANGLE:
783 return queryOnly && context->getExtensions().clientArrays;
784
785 case GL_FRAMEBUFFER_SRGB_EXT:
786 return context->getExtensions().sRGBWriteControl;
787
788 case GL_SAMPLE_MASK:
789 return context->getClientVersion() >= Version(3, 1);
790
791 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
792 return queryOnly && context->getExtensions().robustResourceInitialization;
793
794 default:
795 return false;
796 }
797}
798
Geoff Langfc32e8b2017-05-31 14:16:59 -0400799// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
800// 3.1.
Geoff Langcab92ee2017-07-19 17:32:07 -0400801bool IsValidESSLCharacter(unsigned char c)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400802{
803 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langcab92ee2017-07-19 17:32:07 -0400804 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
805 c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400806 {
807 return true;
808 }
809
810 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
811 if (c >= 9 && c <= 13)
812 {
813 return true;
814 }
815
816 return false;
817}
818
Geoff Langcab92ee2017-07-19 17:32:07 -0400819bool IsValidESSLString(const char *str, size_t len)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400820{
Geoff Langa71a98e2017-06-19 15:15:00 -0400821 for (size_t i = 0; i < len; i++)
822 {
Geoff Langcab92ee2017-07-19 17:32:07 -0400823 if (!IsValidESSLCharacter(str[i]))
Geoff Langa71a98e2017-06-19 15:15:00 -0400824 {
825 return false;
826 }
827 }
828
829 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400830}
831
Geoff Langcab92ee2017-07-19 17:32:07 -0400832bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
833{
834 enum class ParseState
835 {
836 // Have not seen an ASCII non-whitespace character yet on
837 // this line. Possible that we might see a preprocessor
838 // directive.
839 BEGINING_OF_LINE,
840
841 // Have seen at least one ASCII non-whitespace character
842 // on this line.
843 MIDDLE_OF_LINE,
844
845 // Handling a preprocessor directive. Passes through all
846 // characters up to the end of the line. Disables comment
847 // processing.
848 IN_PREPROCESSOR_DIRECTIVE,
849
850 // Handling a single-line comment. The comment text is
851 // replaced with a single space.
852 IN_SINGLE_LINE_COMMENT,
853
854 // Handling a multi-line comment. Newlines are passed
855 // through to preserve line numbers.
856 IN_MULTI_LINE_COMMENT
857 };
858
859 ParseState state = ParseState::BEGINING_OF_LINE;
860 size_t pos = 0;
861
862 while (pos < len)
863 {
864 char c = str[pos];
865 char next = pos + 1 < len ? str[pos + 1] : 0;
866
867 // Check for newlines
868 if (c == '\n' || c == '\r')
869 {
870 if (state != ParseState::IN_MULTI_LINE_COMMENT)
871 {
872 state = ParseState::BEGINING_OF_LINE;
873 }
874
875 pos++;
876 continue;
877 }
878
879 switch (state)
880 {
881 case ParseState::BEGINING_OF_LINE:
882 if (c == ' ')
883 {
884 // Maintain the BEGINING_OF_LINE state until a non-space is seen
885 pos++;
886 }
887 else if (c == '#')
888 {
889 state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
890 pos++;
891 }
892 else
893 {
894 // Don't advance, re-process this character with the MIDDLE_OF_LINE state
895 state = ParseState::MIDDLE_OF_LINE;
896 }
897 break;
898
899 case ParseState::MIDDLE_OF_LINE:
900 if (c == '/' && next == '/')
901 {
902 state = ParseState::IN_SINGLE_LINE_COMMENT;
903 pos++;
904 }
905 else if (c == '/' && next == '*')
906 {
907 state = ParseState::IN_MULTI_LINE_COMMENT;
908 pos++;
909 }
910 else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
911 {
912 // Skip line continuation characters
913 }
914 else if (!IsValidESSLCharacter(c))
915 {
916 return false;
917 }
918 pos++;
919 break;
920
921 case ParseState::IN_PREPROCESSOR_DIRECTIVE:
922 // No matter what the character is, just pass it
923 // through. Do not parse comments in this state.
924 pos++;
925 break;
926
927 case ParseState::IN_SINGLE_LINE_COMMENT:
928 // Line-continuation characters are processed before comment processing.
929 // Advance string if a new line character is immediately behind
930 // line-continuation character.
931 if (c == '\\' && (next == '\n' || next == '\r'))
932 {
933 pos++;
934 }
935 pos++;
936 break;
937
938 case ParseState::IN_MULTI_LINE_COMMENT:
939 if (c == '*' && next == '/')
940 {
941 state = ParseState::MIDDLE_OF_LINE;
942 pos++;
943 }
944 pos++;
945 break;
946 }
947 }
948
949 return true;
950}
951
Jamie Madillc29968b2016-01-20 11:17:23 -0500952} // anonymous namespace
953
Geoff Langff5b2d52016-09-07 11:32:23 -0400954bool ValidateES2TexImageParameters(Context *context,
955 GLenum target,
956 GLint level,
957 GLenum internalformat,
958 bool isCompressed,
959 bool isSubImage,
960 GLint xoffset,
961 GLint yoffset,
962 GLsizei width,
963 GLsizei height,
964 GLint border,
965 GLenum format,
966 GLenum type,
967 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400968 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969{
Jamie Madill6f38f822014-06-06 17:12:20 -0400970 if (!ValidTexture2DDestinationTarget(context, target))
971 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -0400973 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400974 }
975
Austin Kinross08528e12015-10-07 16:24:40 -0700976 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500978 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400979 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 }
981
Brandon Jones6cad5662017-06-14 13:25:13 -0700982 if (!ValidMipLevel(context, target, level))
983 {
984 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
985 return false;
986 }
987
988 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 std::numeric_limits<GLsizei>::max() - yoffset < height)
990 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700991 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -0400992 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 }
994
Geoff Lang6e898aa2017-06-02 11:17:26 -0400995 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
996 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
997 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
998 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
999 // case.
1000 bool nonEqualFormatsAllowed =
1001 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
1002 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
1003
1004 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009
Geoff Langaae65a42014-05-26 12:43:44 -04001010 const gl::Caps &caps = context->getCaps();
1011
Geoff Langa9be0dc2014-12-17 12:34:40 -05001012 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001014 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
1015 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001020 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001021 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
1022 {
1023 ASSERT(level == 0);
1024 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1025 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
1026 {
1027 context->handleError(InvalidValue());
1028 return false;
1029 }
1030 if (isCompressed)
1031 {
1032 context->handleError(InvalidEnum()
1033 << "Rectangle texture cannot have a compressed format.");
1034 return false;
1035 }
1036 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001037 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001038 {
1039 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001041 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001042 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001043 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001044
Geoff Langa9be0dc2014-12-17 12:34:40 -05001045 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1046 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001049 return false;
1050 }
1051 }
1052 else
1053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001054 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001055 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 }
1057
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 gl::Texture *texture =
1059 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 if (!texture)
1061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001063 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001064 }
1065
Geoff Langa9be0dc2014-12-17 12:34:40 -05001066 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001067 {
Geoff Langca271392017-04-05 12:30:00 -04001068 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1069 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001071 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001072 return false;
1073 }
1074
Geoff Langa9be0dc2014-12-17 12:34:40 -05001075 if (format != GL_NONE)
1076 {
Geoff Langca271392017-04-05 12:30:00 -04001077 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1078 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001079 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001081 return false;
1082 }
1083 }
1084
1085 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1086 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001088 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001089 return false;
1090 }
1091 }
1092 else
1093 {
Geoff Lang69cce582015-09-17 13:20:36 -04001094 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001096 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001097 return false;
1098 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 }
1100
1101 // Verify zero border
1102 if (border != 0)
1103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001104 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001105 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 }
1107
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 if (isCompressed)
1109 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001110 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001111 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1112 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 switch (actualInternalFormat)
1114 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1116 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1117 if (!context->getExtensions().textureCompressionDXT1)
1118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
1121 }
1122 break;
1123 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1124 if (!context->getExtensions().textureCompressionDXT1)
1125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 return false;
1128 }
1129 break;
1130 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1131 if (!context->getExtensions().textureCompressionDXT5)
1132 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001133 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 return false;
1135 }
1136 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001137 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1138 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1139 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1140 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1141 if (!context->getExtensions().textureCompressionS3TCsRGB)
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001144 return false;
1145 }
1146 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001147 case GL_ETC1_RGB8_OES:
1148 if (!context->getExtensions().compressedETC1RGB8Texture)
1149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001151 return false;
1152 }
1153 break;
1154 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001155 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1156 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1157 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1158 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001159 if (!context->getExtensions().lossyETCDecode)
1160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001161 context->handleError(InvalidEnum()
1162 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 return false;
1164 }
1165 break;
1166 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001168 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001169 }
Geoff Lang966c9402017-04-18 12:38:27 -04001170
1171 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001172 {
Geoff Lang966c9402017-04-18 12:38:27 -04001173 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1174 height, texture->getWidth(target, level),
1175 texture->getHeight(target, level)))
1176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001177 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001178 return false;
1179 }
1180
1181 if (format != actualInternalFormat)
1182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001184 return false;
1185 }
1186 }
1187 else
1188 {
1189 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001191 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001192 return false;
1193 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194 }
1195 }
1196 else
1197 {
1198 // validate <type> by itself (used as secondary key below)
1199 switch (type)
1200 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001201 case GL_UNSIGNED_BYTE:
1202 case GL_UNSIGNED_SHORT_5_6_5:
1203 case GL_UNSIGNED_SHORT_4_4_4_4:
1204 case GL_UNSIGNED_SHORT_5_5_5_1:
1205 case GL_UNSIGNED_SHORT:
1206 case GL_UNSIGNED_INT:
1207 case GL_UNSIGNED_INT_24_8_OES:
1208 case GL_HALF_FLOAT_OES:
1209 case GL_FLOAT:
1210 break;
1211 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001212 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001213 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001214 }
1215
1216 // validate <format> + <type> combinations
1217 // - invalid <format> -> sets INVALID_ENUM
1218 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1219 switch (format)
1220 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 case GL_ALPHA:
1222 case GL_LUMINANCE:
1223 case GL_LUMINANCE_ALPHA:
1224 switch (type)
1225 {
1226 case GL_UNSIGNED_BYTE:
1227 case GL_FLOAT:
1228 case GL_HALF_FLOAT_OES:
1229 break;
1230 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001232 return false;
1233 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001235 case GL_RED:
1236 case GL_RG:
1237 if (!context->getExtensions().textureRG)
1238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001239 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001240 return false;
1241 }
1242 switch (type)
1243 {
1244 case GL_UNSIGNED_BYTE:
1245 case GL_FLOAT:
1246 case GL_HALF_FLOAT_OES:
1247 break;
1248 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001250 return false;
1251 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001252 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001253 case GL_RGB:
1254 switch (type)
1255 {
1256 case GL_UNSIGNED_BYTE:
1257 case GL_UNSIGNED_SHORT_5_6_5:
1258 case GL_FLOAT:
1259 case GL_HALF_FLOAT_OES:
1260 break;
1261 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001263 return false;
1264 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001266 case GL_RGBA:
1267 switch (type)
1268 {
1269 case GL_UNSIGNED_BYTE:
1270 case GL_UNSIGNED_SHORT_4_4_4_4:
1271 case GL_UNSIGNED_SHORT_5_5_5_1:
1272 case GL_FLOAT:
1273 case GL_HALF_FLOAT_OES:
1274 break;
1275 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001277 return false;
1278 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001279 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001280 case GL_BGRA_EXT:
1281 switch (type)
1282 {
1283 case GL_UNSIGNED_BYTE:
1284 break;
1285 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001287 return false;
1288 }
1289 break;
1290 case GL_SRGB_EXT:
1291 case GL_SRGB_ALPHA_EXT:
1292 if (!context->getExtensions().sRGB)
1293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001294 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001295 return false;
1296 }
1297 switch (type)
1298 {
1299 case GL_UNSIGNED_BYTE:
1300 break;
1301 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001302 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001303 return false;
1304 }
1305 break;
1306 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1307 // handled below
1308 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1309 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1310 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1311 break;
1312 case GL_DEPTH_COMPONENT:
1313 switch (type)
1314 {
1315 case GL_UNSIGNED_SHORT:
1316 case GL_UNSIGNED_INT:
1317 break;
1318 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001320 return false;
1321 }
1322 break;
1323 case GL_DEPTH_STENCIL_OES:
1324 switch (type)
1325 {
1326 case GL_UNSIGNED_INT_24_8_OES:
1327 break;
1328 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001330 return false;
1331 }
1332 break;
1333 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001334 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001335 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 }
1337
1338 switch (format)
1339 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001340 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1341 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1342 if (context->getExtensions().textureCompressionDXT1)
1343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001344 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001345 return false;
1346 }
1347 else
1348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001350 return false;
1351 }
1352 break;
1353 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1354 if (context->getExtensions().textureCompressionDXT3)
1355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001356 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001357 return false;
1358 }
1359 else
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001362 return false;
1363 }
1364 break;
1365 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1366 if (context->getExtensions().textureCompressionDXT5)
1367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001369 return false;
1370 }
1371 else
1372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001374 return false;
1375 }
1376 break;
1377 case GL_ETC1_RGB8_OES:
1378 if (context->getExtensions().compressedETC1RGB8Texture)
1379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001380 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001381 return false;
1382 }
1383 else
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001386 return false;
1387 }
1388 break;
1389 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001390 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1391 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1392 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1393 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001394 if (context->getExtensions().lossyETCDecode)
1395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation()
1397 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 return false;
1399 }
1400 else
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidEnum()
1403 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 return false;
1405 }
1406 break;
1407 case GL_DEPTH_COMPONENT:
1408 case GL_DEPTH_STENCIL_OES:
1409 if (!context->getExtensions().depthTextures)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 return false;
1413 }
1414 if (target != GL_TEXTURE_2D)
1415 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001416 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 return false;
1418 }
1419 // OES_depth_texture supports loading depth data and multiple levels,
1420 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001421 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001422 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001423 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1424 return false;
1425 }
1426 if (level != 0)
1427 {
1428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 return false;
1430 }
1431 break;
1432 default:
1433 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434 }
1435
Geoff Lang6e898aa2017-06-02 11:17:26 -04001436 if (!isSubImage)
1437 {
1438 switch (internalformat)
1439 {
1440 case GL_RGBA32F:
1441 if (!context->getExtensions().colorBufferFloatRGBA)
1442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(InvalidValue()
1444 << "Sized GL_RGBA32F internal format requires "
1445 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001446 return false;
1447 }
1448 if (type != GL_FLOAT)
1449 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001450 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001451 return false;
1452 }
1453 if (format != GL_RGBA)
1454 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001456 return false;
1457 }
1458 break;
1459
1460 case GL_RGB32F:
1461 if (!context->getExtensions().colorBufferFloatRGB)
1462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidValue()
1464 << "Sized GL_RGB32F internal format requires "
1465 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001466 return false;
1467 }
1468 if (type != GL_FLOAT)
1469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001471 return false;
1472 }
1473 if (format != GL_RGB)
1474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001476 return false;
1477 }
1478 break;
1479
1480 default:
1481 break;
1482 }
1483 }
1484
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001485 if (type == GL_FLOAT)
1486 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001487 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001490 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491 }
1492 }
1493 else if (type == GL_HALF_FLOAT_OES)
1494 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001495 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500 }
1501 }
1502
Geoff Langdbcced82017-06-06 15:55:54 -04001503 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1504 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001505 imageSize))
1506 {
1507 return false;
1508 }
1509
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 return true;
1511}
1512
He Yunchaoced53ae2016-11-29 15:00:51 +08001513bool ValidateES2TexStorageParameters(Context *context,
1514 GLenum target,
1515 GLsizei levels,
1516 GLenum internalformat,
1517 GLsizei width,
1518 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001519{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001520 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1521 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
1527 if (width < 1 || height < 1 || levels < 1)
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
1533 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001536 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 }
1538
1539 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001542 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001543 }
1544
Geoff Langca271392017-04-05 12:30:00 -04001545 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001546 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001548 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001549 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001550 }
1551
Geoff Langaae65a42014-05-26 12:43:44 -04001552 const gl::Caps &caps = context->getCaps();
1553
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001554 switch (target)
1555 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001556 case GL_TEXTURE_2D:
1557 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1558 static_cast<GLuint>(height) > caps.max2DTextureSize)
1559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001561 return false;
1562 }
1563 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001564 case GL_TEXTURE_RECTANGLE_ANGLE:
1565 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1566 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1567 {
1568 context->handleError(InvalidValue());
1569 return false;
1570 }
1571 if (formatInfo.compressed)
1572 {
1573 context->handleError(InvalidEnum()
1574 << "Rectangle texture cannot have a compressed format.");
1575 return false;
1576 }
1577 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001578 case GL_TEXTURE_CUBE_MAP:
1579 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1580 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001583 return false;
1584 }
1585 break;
1586 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001588 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001589 }
1590
Geoff Langc0b9ef42014-07-02 10:02:37 -04001591 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001592 {
1593 if (!gl::isPow2(width) || !gl::isPow2(height))
1594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001595 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001596 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001597 }
1598 }
1599
1600 switch (internalformat)
1601 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001602 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1603 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1604 if (!context->getExtensions().textureCompressionDXT1)
1605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001606 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001607 return false;
1608 }
1609 break;
1610 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1611 if (!context->getExtensions().textureCompressionDXT3)
1612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001613 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001614 return false;
1615 }
1616 break;
1617 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1618 if (!context->getExtensions().textureCompressionDXT5)
1619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001620 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001621 return false;
1622 }
1623 break;
1624 case GL_ETC1_RGB8_OES:
1625 if (!context->getExtensions().compressedETC1RGB8Texture)
1626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001627 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001628 return false;
1629 }
1630 break;
1631 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001632 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1633 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1634 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1635 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001636 if (!context->getExtensions().lossyETCDecode)
1637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidEnum()
1639 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001640 return false;
1641 }
1642 break;
1643 case GL_RGBA32F_EXT:
1644 case GL_RGB32F_EXT:
1645 case GL_ALPHA32F_EXT:
1646 case GL_LUMINANCE32F_EXT:
1647 case GL_LUMINANCE_ALPHA32F_EXT:
1648 if (!context->getExtensions().textureFloat)
1649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001650 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001651 return false;
1652 }
1653 break;
1654 case GL_RGBA16F_EXT:
1655 case GL_RGB16F_EXT:
1656 case GL_ALPHA16F_EXT:
1657 case GL_LUMINANCE16F_EXT:
1658 case GL_LUMINANCE_ALPHA16F_EXT:
1659 if (!context->getExtensions().textureHalfFloat)
1660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001661 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001662 return false;
1663 }
1664 break;
1665 case GL_R8_EXT:
1666 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001667 if (!context->getExtensions().textureRG)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001670 return false;
1671 }
1672 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001673 case GL_R16F_EXT:
1674 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001675 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001678 return false;
1679 }
1680 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001681 case GL_R32F_EXT:
1682 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001683 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001685 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001686 return false;
1687 }
1688 break;
1689 case GL_DEPTH_COMPONENT16:
1690 case GL_DEPTH_COMPONENT32_OES:
1691 case GL_DEPTH24_STENCIL8_OES:
1692 if (!context->getExtensions().depthTextures)
1693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001694 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001695 return false;
1696 }
1697 if (target != GL_TEXTURE_2D)
1698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001700 return false;
1701 }
1702 // ANGLE_depth_texture only supports 1-level textures
1703 if (levels != 1)
1704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001706 return false;
1707 }
1708 break;
1709 default:
1710 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001711 }
1712
Geoff Lang691e58c2014-12-19 17:03:25 -05001713 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001714 if (!texture || texture->id() == 0)
1715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001717 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718 }
1719
Geoff Lang69cce582015-09-17 13:20:36 -04001720 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001722 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001723 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724 }
1725
1726 return true;
1727}
1728
He Yunchaoced53ae2016-11-29 15:00:51 +08001729bool ValidateDiscardFramebufferEXT(Context *context,
1730 GLenum target,
1731 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001732 const GLenum *attachments)
1733{
Jamie Madillc29968b2016-01-20 11:17:23 -05001734 if (!context->getExtensions().discardFramebuffer)
1735 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001736 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 return false;
1738 }
1739
Austin Kinross08332632015-05-05 13:35:47 -07001740 bool defaultFramebuffer = false;
1741
1742 switch (target)
1743 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001744 case GL_FRAMEBUFFER:
1745 defaultFramebuffer =
1746 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1747 break;
1748 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001750 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001751 }
1752
He Yunchaoced53ae2016-11-29 15:00:51 +08001753 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1754 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001755}
1756
Austin Kinrossbc781f32015-10-26 09:27:38 -07001757bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1758{
1759 if (!context->getExtensions().vertexArrayObject)
1760 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001762 return false;
1763 }
1764
1765 return ValidateBindVertexArrayBase(context, array);
1766}
1767
Jamie Madilld7576732017-08-26 18:49:50 -04001768bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001769{
1770 if (!context->getExtensions().vertexArrayObject)
1771 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001772 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001773 return false;
1774 }
1775
Olli Etuaho41997e72016-03-10 13:38:39 +02001776 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001777}
1778
Jamie Madilld7576732017-08-26 18:49:50 -04001779bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001780{
1781 if (!context->getExtensions().vertexArrayObject)
1782 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001784 return false;
1785 }
1786
Olli Etuaho41997e72016-03-10 13:38:39 +02001787 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001788}
1789
Jamie Madilld7576732017-08-26 18:49:50 -04001790bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001791{
1792 if (!context->getExtensions().vertexArrayObject)
1793 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001794 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001795 return false;
1796 }
1797
1798 return true;
1799}
Geoff Langc5629752015-12-07 16:29:04 -05001800
1801bool ValidateProgramBinaryOES(Context *context,
1802 GLuint program,
1803 GLenum binaryFormat,
1804 const void *binary,
1805 GLint length)
1806{
1807 if (!context->getExtensions().getProgramBinary)
1808 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001809 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001810 return false;
1811 }
1812
1813 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1814}
1815
1816bool ValidateGetProgramBinaryOES(Context *context,
1817 GLuint program,
1818 GLsizei bufSize,
1819 GLsizei *length,
1820 GLenum *binaryFormat,
1821 void *binary)
1822{
1823 if (!context->getExtensions().getProgramBinary)
1824 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001825 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001826 return false;
1827 }
1828
1829 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1830}
Geoff Lange102fee2015-12-10 11:23:30 -05001831
Geoff Lang70d0f492015-12-10 17:45:46 -05001832static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1833{
1834 switch (source)
1835 {
1836 case GL_DEBUG_SOURCE_API:
1837 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1838 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1839 case GL_DEBUG_SOURCE_OTHER:
1840 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1841 return !mustBeThirdPartyOrApplication;
1842
1843 case GL_DEBUG_SOURCE_THIRD_PARTY:
1844 case GL_DEBUG_SOURCE_APPLICATION:
1845 return true;
1846
1847 default:
1848 return false;
1849 }
1850}
1851
1852static bool ValidDebugType(GLenum type)
1853{
1854 switch (type)
1855 {
1856 case GL_DEBUG_TYPE_ERROR:
1857 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1858 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1859 case GL_DEBUG_TYPE_PERFORMANCE:
1860 case GL_DEBUG_TYPE_PORTABILITY:
1861 case GL_DEBUG_TYPE_OTHER:
1862 case GL_DEBUG_TYPE_MARKER:
1863 case GL_DEBUG_TYPE_PUSH_GROUP:
1864 case GL_DEBUG_TYPE_POP_GROUP:
1865 return true;
1866
1867 default:
1868 return false;
1869 }
1870}
1871
1872static bool ValidDebugSeverity(GLenum severity)
1873{
1874 switch (severity)
1875 {
1876 case GL_DEBUG_SEVERITY_HIGH:
1877 case GL_DEBUG_SEVERITY_MEDIUM:
1878 case GL_DEBUG_SEVERITY_LOW:
1879 case GL_DEBUG_SEVERITY_NOTIFICATION:
1880 return true;
1881
1882 default:
1883 return false;
1884 }
1885}
1886
Geoff Lange102fee2015-12-10 11:23:30 -05001887bool ValidateDebugMessageControlKHR(Context *context,
1888 GLenum source,
1889 GLenum type,
1890 GLenum severity,
1891 GLsizei count,
1892 const GLuint *ids,
1893 GLboolean enabled)
1894{
1895 if (!context->getExtensions().debug)
1896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001898 return false;
1899 }
1900
Geoff Lang70d0f492015-12-10 17:45:46 -05001901 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1902 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 return false;
1905 }
1906
1907 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1908 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001910 return false;
1911 }
1912
1913 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1914 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001916 return false;
1917 }
1918
1919 if (count > 0)
1920 {
1921 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001923 context->handleError(
1924 InvalidOperation()
1925 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001926 return false;
1927 }
1928
1929 if (severity != GL_DONT_CARE)
1930 {
Jamie Madill437fa652016-05-03 15:13:24 -04001931 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001932 InvalidOperation()
1933 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001934 return false;
1935 }
1936 }
1937
Geoff Lange102fee2015-12-10 11:23:30 -05001938 return true;
1939}
1940
1941bool ValidateDebugMessageInsertKHR(Context *context,
1942 GLenum source,
1943 GLenum type,
1944 GLuint id,
1945 GLenum severity,
1946 GLsizei length,
1947 const GLchar *buf)
1948{
1949 if (!context->getExtensions().debug)
1950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001952 return false;
1953 }
1954
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001955 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001956 {
1957 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1958 // not generate an error.
1959 return false;
1960 }
1961
1962 if (!ValidDebugSeverity(severity))
1963 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001965 return false;
1966 }
1967
1968 if (!ValidDebugType(type))
1969 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001970 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001971 return false;
1972 }
1973
1974 if (!ValidDebugSource(source, true))
1975 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001977 return false;
1978 }
1979
1980 size_t messageLength = (length < 0) ? strlen(buf) : length;
1981 if (messageLength > context->getExtensions().maxDebugMessageLength)
1982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001983 context->handleError(InvalidValue()
1984 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001985 return false;
1986 }
1987
Geoff Lange102fee2015-12-10 11:23:30 -05001988 return true;
1989}
1990
1991bool ValidateDebugMessageCallbackKHR(Context *context,
1992 GLDEBUGPROCKHR callback,
1993 const void *userParam)
1994{
1995 if (!context->getExtensions().debug)
1996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001998 return false;
1999 }
2000
Geoff Lange102fee2015-12-10 11:23:30 -05002001 return true;
2002}
2003
2004bool ValidateGetDebugMessageLogKHR(Context *context,
2005 GLuint count,
2006 GLsizei bufSize,
2007 GLenum *sources,
2008 GLenum *types,
2009 GLuint *ids,
2010 GLenum *severities,
2011 GLsizei *lengths,
2012 GLchar *messageLog)
2013{
2014 if (!context->getExtensions().debug)
2015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002016 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002017 return false;
2018 }
2019
Geoff Lang70d0f492015-12-10 17:45:46 -05002020 if (bufSize < 0 && messageLog != nullptr)
2021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002022 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002023 return false;
2024 }
2025
Geoff Lange102fee2015-12-10 11:23:30 -05002026 return true;
2027}
2028
2029bool ValidatePushDebugGroupKHR(Context *context,
2030 GLenum source,
2031 GLuint id,
2032 GLsizei length,
2033 const GLchar *message)
2034{
2035 if (!context->getExtensions().debug)
2036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002037 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002038 return false;
2039 }
2040
Geoff Lang70d0f492015-12-10 17:45:46 -05002041 if (!ValidDebugSource(source, true))
2042 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002044 return false;
2045 }
2046
2047 size_t messageLength = (length < 0) ? strlen(message) : length;
2048 if (messageLength > context->getExtensions().maxDebugMessageLength)
2049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002050 context->handleError(InvalidValue()
2051 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002052 return false;
2053 }
2054
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002055 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002056 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002058 context
2059 ->handleError(StackOverflow()
2060 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002061 return false;
2062 }
2063
Geoff Lange102fee2015-12-10 11:23:30 -05002064 return true;
2065}
2066
2067bool ValidatePopDebugGroupKHR(Context *context)
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
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002075 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002076 if (currentStackSize <= 1)
2077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002078 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002079 return false;
2080 }
2081
2082 return true;
2083}
2084
2085static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2086{
2087 switch (identifier)
2088 {
2089 case GL_BUFFER:
2090 if (context->getBuffer(name) == nullptr)
2091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002092 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002093 return false;
2094 }
2095 return true;
2096
2097 case GL_SHADER:
2098 if (context->getShader(name) == nullptr)
2099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002100 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002101 return false;
2102 }
2103 return true;
2104
2105 case GL_PROGRAM:
2106 if (context->getProgram(name) == nullptr)
2107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002108 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002109 return false;
2110 }
2111 return true;
2112
2113 case GL_VERTEX_ARRAY:
2114 if (context->getVertexArray(name) == nullptr)
2115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002116 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002117 return false;
2118 }
2119 return true;
2120
2121 case GL_QUERY:
2122 if (context->getQuery(name) == nullptr)
2123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002124 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002125 return false;
2126 }
2127 return true;
2128
2129 case GL_TRANSFORM_FEEDBACK:
2130 if (context->getTransformFeedback(name) == nullptr)
2131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002132 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002133 return false;
2134 }
2135 return true;
2136
2137 case GL_SAMPLER:
2138 if (context->getSampler(name) == nullptr)
2139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002140 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002141 return false;
2142 }
2143 return true;
2144
2145 case GL_TEXTURE:
2146 if (context->getTexture(name) == nullptr)
2147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002148 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002149 return false;
2150 }
2151 return true;
2152
2153 case GL_RENDERBUFFER:
2154 if (context->getRenderbuffer(name) == nullptr)
2155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002156 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002157 return false;
2158 }
2159 return true;
2160
2161 case GL_FRAMEBUFFER:
2162 if (context->getFramebuffer(name) == nullptr)
2163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002164 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002165 return false;
2166 }
2167 return true;
2168
2169 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002170 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002171 return false;
2172 }
Geoff Lange102fee2015-12-10 11:23:30 -05002173}
2174
Martin Radev9d901792016-07-15 15:58:58 +03002175static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2176{
2177 size_t labelLength = 0;
2178
2179 if (length < 0)
2180 {
2181 if (label != nullptr)
2182 {
2183 labelLength = strlen(label);
2184 }
2185 }
2186 else
2187 {
2188 labelLength = static_cast<size_t>(length);
2189 }
2190
2191 if (labelLength > context->getExtensions().maxLabelLength)
2192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002193 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002194 return false;
2195 }
2196
2197 return true;
2198}
2199
Geoff Lange102fee2015-12-10 11:23:30 -05002200bool ValidateObjectLabelKHR(Context *context,
2201 GLenum identifier,
2202 GLuint name,
2203 GLsizei length,
2204 const GLchar *label)
2205{
2206 if (!context->getExtensions().debug)
2207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002209 return false;
2210 }
2211
Geoff Lang70d0f492015-12-10 17:45:46 -05002212 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2213 {
2214 return false;
2215 }
2216
Martin Radev9d901792016-07-15 15:58:58 +03002217 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002218 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002219 return false;
2220 }
2221
Geoff Lange102fee2015-12-10 11:23:30 -05002222 return true;
2223}
2224
2225bool ValidateGetObjectLabelKHR(Context *context,
2226 GLenum identifier,
2227 GLuint name,
2228 GLsizei bufSize,
2229 GLsizei *length,
2230 GLchar *label)
2231{
2232 if (!context->getExtensions().debug)
2233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002235 return false;
2236 }
2237
Geoff Lang70d0f492015-12-10 17:45:46 -05002238 if (bufSize < 0)
2239 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002240 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002241 return false;
2242 }
2243
2244 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2245 {
2246 return false;
2247 }
2248
Martin Radev9d901792016-07-15 15:58:58 +03002249 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002250}
2251
2252static bool ValidateObjectPtrName(Context *context, const void *ptr)
2253{
2254 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002256 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002257 return false;
2258 }
2259
Geoff Lange102fee2015-12-10 11:23:30 -05002260 return true;
2261}
2262
2263bool ValidateObjectPtrLabelKHR(Context *context,
2264 const void *ptr,
2265 GLsizei length,
2266 const GLchar *label)
2267{
2268 if (!context->getExtensions().debug)
2269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002271 return false;
2272 }
2273
Geoff Lang70d0f492015-12-10 17:45:46 -05002274 if (!ValidateObjectPtrName(context, ptr))
2275 {
2276 return false;
2277 }
2278
Martin Radev9d901792016-07-15 15:58:58 +03002279 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002280 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002281 return false;
2282 }
2283
Geoff Lange102fee2015-12-10 11:23:30 -05002284 return true;
2285}
2286
2287bool ValidateGetObjectPtrLabelKHR(Context *context,
2288 const void *ptr,
2289 GLsizei bufSize,
2290 GLsizei *length,
2291 GLchar *label)
2292{
2293 if (!context->getExtensions().debug)
2294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002296 return false;
2297 }
2298
Geoff Lang70d0f492015-12-10 17:45:46 -05002299 if (bufSize < 0)
2300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002301 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002302 return false;
2303 }
2304
2305 if (!ValidateObjectPtrName(context, ptr))
2306 {
2307 return false;
2308 }
2309
Martin Radev9d901792016-07-15 15:58:58 +03002310 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002311}
2312
2313bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2314{
2315 if (!context->getExtensions().debug)
2316 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002317 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002318 return false;
2319 }
2320
Geoff Lang70d0f492015-12-10 17:45:46 -05002321 // TODO: represent this in Context::getQueryParameterInfo.
2322 switch (pname)
2323 {
2324 case GL_DEBUG_CALLBACK_FUNCTION:
2325 case GL_DEBUG_CALLBACK_USER_PARAM:
2326 break;
2327
2328 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002329 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002330 return false;
2331 }
2332
Geoff Lange102fee2015-12-10 11:23:30 -05002333 return true;
2334}
Jamie Madillc29968b2016-01-20 11:17:23 -05002335
2336bool ValidateBlitFramebufferANGLE(Context *context,
2337 GLint srcX0,
2338 GLint srcY0,
2339 GLint srcX1,
2340 GLint srcY1,
2341 GLint dstX0,
2342 GLint dstY0,
2343 GLint dstX1,
2344 GLint dstY1,
2345 GLbitfield mask,
2346 GLenum filter)
2347{
2348 if (!context->getExtensions().framebufferBlit)
2349 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002350 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002351 return false;
2352 }
2353
2354 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2355 {
2356 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002357 context->handleError(InvalidOperation() << "Scaling and flipping in "
2358 "BlitFramebufferANGLE not supported by this "
2359 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002360 return false;
2361 }
2362
2363 if (filter == GL_LINEAR)
2364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002366 return false;
2367 }
2368
Jamie Madill51f40ec2016-06-15 14:06:00 -04002369 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2370 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002371
2372 if (mask & GL_COLOR_BUFFER_BIT)
2373 {
2374 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2375 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2376
2377 if (readColorAttachment && drawColorAttachment)
2378 {
2379 if (!(readColorAttachment->type() == GL_TEXTURE &&
2380 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2381 readColorAttachment->type() != GL_RENDERBUFFER &&
2382 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002384 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002385 return false;
2386 }
2387
Geoff Langa15472a2015-08-11 11:48:03 -04002388 for (size_t drawbufferIdx = 0;
2389 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002390 {
Geoff Langa15472a2015-08-11 11:48:03 -04002391 const FramebufferAttachment *attachment =
2392 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2393 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002394 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002395 if (!(attachment->type() == GL_TEXTURE &&
2396 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2397 attachment->type() != GL_RENDERBUFFER &&
2398 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002400 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002401 return false;
2402 }
2403
2404 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002405 if (!Format::EquivalentForBlit(attachment->getFormat(),
2406 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002408 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002409 return false;
2410 }
2411 }
2412 }
2413
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002414 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002415 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2416 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002418 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002419 return false;
2420 }
2421 }
2422 }
2423
2424 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2425 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2426 for (size_t i = 0; i < 2; i++)
2427 {
2428 if (mask & masks[i])
2429 {
2430 const FramebufferAttachment *readBuffer =
2431 readFramebuffer->getAttachment(attachments[i]);
2432 const FramebufferAttachment *drawBuffer =
2433 drawFramebuffer->getAttachment(attachments[i]);
2434
2435 if (readBuffer && drawBuffer)
2436 {
2437 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2438 dstX0, dstY0, dstX1, dstY1))
2439 {
2440 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002441 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2442 "stencil blits are supported by "
2443 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002444 return false;
2445 }
2446
2447 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002449 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002450 return false;
2451 }
2452 }
2453 }
2454 }
2455
2456 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2457 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002458}
Jamie Madillc29968b2016-01-20 11:17:23 -05002459
2460bool ValidateClear(ValidationContext *context, GLbitfield mask)
2461{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002462 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002463 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002465 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002466 return false;
2467 }
2468
2469 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002471 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002472 return false;
2473 }
2474
Geoff Lang76e65652017-03-27 14:58:02 -04002475 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2476 {
2477 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2478 GL_SIGNED_NORMALIZED};
2479
Corentin Wallez59c41592017-07-11 13:19:54 -04002480 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002481 drawBufferIdx++)
2482 {
2483 if (!ValidateWebGLFramebufferAttachmentClearType(
2484 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2485 {
2486 return false;
2487 }
2488 }
2489 }
2490
Jamie Madillc29968b2016-01-20 11:17:23 -05002491 return true;
2492}
2493
2494bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2495{
2496 if (!context->getExtensions().drawBuffers)
2497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002499 return false;
2500 }
2501
2502 return ValidateDrawBuffersBase(context, n, bufs);
2503}
2504
Jamie Madill73a84962016-02-12 09:27:23 -05002505bool ValidateTexImage2D(Context *context,
2506 GLenum target,
2507 GLint level,
2508 GLint internalformat,
2509 GLsizei width,
2510 GLsizei height,
2511 GLint border,
2512 GLenum format,
2513 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002514 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002515{
Martin Radev1be913c2016-07-11 17:59:16 +03002516 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002517 {
2518 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002519 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002520 }
2521
Martin Radev1be913c2016-07-11 17:59:16 +03002522 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002523 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002524 0, 0, width, height, 1, border, format, type, -1,
2525 pixels);
2526}
2527
2528bool ValidateTexImage2DRobust(Context *context,
2529 GLenum target,
2530 GLint level,
2531 GLint internalformat,
2532 GLsizei width,
2533 GLsizei height,
2534 GLint border,
2535 GLenum format,
2536 GLenum type,
2537 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002538 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002539{
2540 if (!ValidateRobustEntryPoint(context, bufSize))
2541 {
2542 return false;
2543 }
2544
2545 if (context->getClientMajorVersion() < 3)
2546 {
2547 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2548 0, 0, width, height, border, format, type, bufSize,
2549 pixels);
2550 }
2551
2552 ASSERT(context->getClientMajorVersion() >= 3);
2553 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2554 0, 0, width, height, 1, border, format, type, bufSize,
2555 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002556}
2557
2558bool ValidateTexSubImage2D(Context *context,
2559 GLenum target,
2560 GLint level,
2561 GLint xoffset,
2562 GLint yoffset,
2563 GLsizei width,
2564 GLsizei height,
2565 GLenum format,
2566 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002567 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002568{
2569
Martin Radev1be913c2016-07-11 17:59:16 +03002570 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002571 {
2572 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002573 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002574 }
2575
Martin Radev1be913c2016-07-11 17:59:16 +03002576 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002577 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002578 yoffset, 0, width, height, 1, 0, format, type, -1,
2579 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002580}
2581
Geoff Langc52f6f12016-10-14 10:18:00 -04002582bool ValidateTexSubImage2DRobustANGLE(Context *context,
2583 GLenum target,
2584 GLint level,
2585 GLint xoffset,
2586 GLint yoffset,
2587 GLsizei width,
2588 GLsizei height,
2589 GLenum format,
2590 GLenum type,
2591 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002592 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002593{
2594 if (!ValidateRobustEntryPoint(context, bufSize))
2595 {
2596 return false;
2597 }
2598
2599 if (context->getClientMajorVersion() < 3)
2600 {
2601 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2602 yoffset, width, height, 0, format, type, bufSize,
2603 pixels);
2604 }
2605
2606 ASSERT(context->getClientMajorVersion() >= 3);
2607 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2608 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2609 pixels);
2610}
2611
Jamie Madill73a84962016-02-12 09:27:23 -05002612bool ValidateCompressedTexImage2D(Context *context,
2613 GLenum target,
2614 GLint level,
2615 GLenum internalformat,
2616 GLsizei width,
2617 GLsizei height,
2618 GLint border,
2619 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002620 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002621{
Martin Radev1be913c2016-07-11 17:59:16 +03002622 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002623 {
2624 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002625 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002626 {
2627 return false;
2628 }
2629 }
2630 else
2631 {
Martin Radev1be913c2016-07-11 17:59:16 +03002632 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002633 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002634 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002635 data))
2636 {
2637 return false;
2638 }
2639 }
2640
Geoff Langca271392017-04-05 12:30:00 -04002641 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002642 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002643 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002644 if (blockSizeOrErr.isError())
2645 {
2646 context->handleError(blockSizeOrErr.getError());
2647 return false;
2648 }
2649
2650 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002651 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002652 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002653 return false;
2654 }
2655
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002656 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2657 {
2658 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2659 return false;
2660 }
2661
Jamie Madill73a84962016-02-12 09:27:23 -05002662 return true;
2663}
2664
Corentin Wallezb2931602017-04-11 15:58:57 -04002665bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2666 GLenum target,
2667 GLint level,
2668 GLenum internalformat,
2669 GLsizei width,
2670 GLsizei height,
2671 GLint border,
2672 GLsizei imageSize,
2673 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002674 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002675{
2676 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2677 {
2678 return false;
2679 }
2680
2681 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2682 border, imageSize, data);
2683}
2684bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2685 GLenum target,
2686 GLint level,
2687 GLint xoffset,
2688 GLint yoffset,
2689 GLsizei width,
2690 GLsizei height,
2691 GLenum format,
2692 GLsizei imageSize,
2693 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002694 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002695{
2696 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2697 {
2698 return false;
2699 }
2700
2701 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2702 format, imageSize, data);
2703}
2704
Jamie Madill73a84962016-02-12 09:27:23 -05002705bool ValidateCompressedTexSubImage2D(Context *context,
2706 GLenum target,
2707 GLint level,
2708 GLint xoffset,
2709 GLint yoffset,
2710 GLsizei width,
2711 GLsizei height,
2712 GLenum format,
2713 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002714 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002715{
Martin Radev1be913c2016-07-11 17:59:16 +03002716 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002717 {
2718 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002719 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002720 {
2721 return false;
2722 }
2723 }
2724 else
2725 {
Martin Radev1be913c2016-07-11 17:59:16 +03002726 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002727 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002728 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002729 data))
2730 {
2731 return false;
2732 }
2733 }
2734
Geoff Langca271392017-04-05 12:30:00 -04002735 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002736 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002737 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002738 if (blockSizeOrErr.isError())
2739 {
2740 context->handleError(blockSizeOrErr.getError());
2741 return false;
2742 }
2743
2744 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002746 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002747 return false;
2748 }
2749
2750 return true;
2751}
2752
Olli Etuaho4f667482016-03-30 15:56:35 +03002753bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2754{
Geoff Lang496c02d2016-10-20 11:38:11 -07002755 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002756}
2757
2758bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2759{
2760 if (!context->getExtensions().mapBuffer)
2761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002762 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002763 return false;
2764 }
2765
2766 if (!ValidBufferTarget(context, target))
2767 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002769 return false;
2770 }
2771
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002772 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002773
2774 if (buffer == nullptr)
2775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002776 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002777 return false;
2778 }
2779
2780 if (access != GL_WRITE_ONLY_OES)
2781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002782 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002783 return false;
2784 }
2785
2786 if (buffer->isMapped())
2787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002788 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002789 return false;
2790 }
2791
Geoff Lang79f71042017-08-14 16:43:43 -04002792 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002793}
2794
2795bool ValidateUnmapBufferOES(Context *context, GLenum target)
2796{
2797 if (!context->getExtensions().mapBuffer)
2798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002799 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002800 return false;
2801 }
2802
2803 return ValidateUnmapBufferBase(context, target);
2804}
2805
2806bool ValidateMapBufferRangeEXT(Context *context,
2807 GLenum target,
2808 GLintptr offset,
2809 GLsizeiptr length,
2810 GLbitfield access)
2811{
2812 if (!context->getExtensions().mapBufferRange)
2813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002814 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002815 return false;
2816 }
2817
2818 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2819}
2820
Geoff Lang79f71042017-08-14 16:43:43 -04002821bool ValidateMapBufferBase(Context *context, GLenum target)
2822{
2823 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2824 ASSERT(buffer != nullptr);
2825
2826 // Check if this buffer is currently being used as a transform feedback output buffer
2827 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2828 if (transformFeedback != nullptr && transformFeedback->isActive())
2829 {
2830 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2831 {
2832 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2833 if (transformFeedbackBuffer.get() == buffer)
2834 {
2835 context->handleError(InvalidOperation()
2836 << "Buffer is currently bound for transform feedback.");
2837 return false;
2838 }
2839 }
2840 }
2841
2842 return true;
2843}
2844
Olli Etuaho4f667482016-03-30 15:56:35 +03002845bool ValidateFlushMappedBufferRangeEXT(Context *context,
2846 GLenum target,
2847 GLintptr offset,
2848 GLsizeiptr length)
2849{
2850 if (!context->getExtensions().mapBufferRange)
2851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002852 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002853 return false;
2854 }
2855
2856 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2857}
2858
Ian Ewell54f87462016-03-10 13:47:21 -05002859bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2860{
2861 Texture *textureObject = context->getTexture(texture);
2862 if (textureObject && textureObject->getTarget() != target && texture != 0)
2863 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002865 return false;
2866 }
2867
Geoff Langf41a7152016-09-19 15:11:17 -04002868 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2869 !context->isTextureGenerated(texture))
2870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002871 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002872 return false;
2873 }
2874
Ian Ewell54f87462016-03-10 13:47:21 -05002875 switch (target)
2876 {
2877 case GL_TEXTURE_2D:
2878 case GL_TEXTURE_CUBE_MAP:
2879 break;
2880
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002881 case GL_TEXTURE_RECTANGLE_ANGLE:
2882 if (!context->getExtensions().textureRectangle)
2883 {
2884 context->handleError(InvalidEnum()
2885 << "Context does not support GL_ANGLE_texture_rectangle");
2886 return false;
2887 }
2888 break;
2889
Ian Ewell54f87462016-03-10 13:47:21 -05002890 case GL_TEXTURE_3D:
2891 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002892 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002893 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002895 return false;
2896 }
2897 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002898
2899 case GL_TEXTURE_2D_MULTISAMPLE:
2900 if (context->getClientVersion() < Version(3, 1))
2901 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002902 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002903 return false;
2904 }
Geoff Lang3b573612016-10-31 14:08:10 -04002905 break;
2906
Ian Ewell54f87462016-03-10 13:47:21 -05002907 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002908 if (!context->getExtensions().eglImageExternal &&
2909 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002911 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002912 return false;
2913 }
2914 break;
2915 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002917 return false;
2918 }
2919
2920 return true;
2921}
2922
Geoff Langd8605522016-04-13 10:19:12 -04002923bool ValidateBindUniformLocationCHROMIUM(Context *context,
2924 GLuint program,
2925 GLint location,
2926 const GLchar *name)
2927{
2928 if (!context->getExtensions().bindUniformLocation)
2929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002930 context->handleError(InvalidOperation()
2931 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002932 return false;
2933 }
2934
2935 Program *programObject = GetValidProgram(context, program);
2936 if (!programObject)
2937 {
2938 return false;
2939 }
2940
2941 if (location < 0)
2942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002943 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002944 return false;
2945 }
2946
2947 const Caps &caps = context->getCaps();
2948 if (static_cast<size_t>(location) >=
2949 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002951 context->handleError(InvalidValue() << "Location must be less than "
2952 "(MAX_VERTEX_UNIFORM_VECTORS + "
2953 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002954 return false;
2955 }
2956
Geoff Langfc32e8b2017-05-31 14:16:59 -04002957 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2958 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04002959 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002961 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04002962 return false;
2963 }
2964
Geoff Langd8605522016-04-13 10:19:12 -04002965 if (strncmp(name, "gl_", 3) == 0)
2966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002967 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04002968 return false;
2969 }
2970
2971 return true;
2972}
2973
Jamie Madille2e406c2016-06-02 13:04:10 -04002974bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002975{
2976 if (!context->getExtensions().framebufferMixedSamples)
2977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002978 context->handleError(InvalidOperation()
2979 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002980 return false;
2981 }
2982 switch (components)
2983 {
2984 case GL_RGB:
2985 case GL_RGBA:
2986 case GL_ALPHA:
2987 case GL_NONE:
2988 break;
2989 default:
2990 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002991 InvalidEnum()
2992 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002993 return false;
2994 }
2995
2996 return true;
2997}
2998
Sami Väisänene45e53b2016-05-25 10:36:04 +03002999// CHROMIUM_path_rendering
3000
3001bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3002{
3003 if (!context->getExtensions().pathRendering)
3004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003005 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003006 return false;
3007 }
3008 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3009 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003010 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003011 return false;
3012 }
3013 if (matrix == nullptr)
3014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003015 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003016 return false;
3017 }
3018 return true;
3019}
3020
3021bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3022{
3023 if (!context->getExtensions().pathRendering)
3024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003025 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003026 return false;
3027 }
3028 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3029 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003031 return false;
3032 }
3033 return true;
3034}
3035
3036bool ValidateGenPaths(Context *context, GLsizei range)
3037{
3038 if (!context->getExtensions().pathRendering)
3039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003040 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003041 return false;
3042 }
3043
3044 // range = 0 is undefined in NV_path_rendering.
3045 // we add stricter semantic check here and require a non zero positive range.
3046 if (range <= 0)
3047 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003048 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003049 return false;
3050 }
3051
3052 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003055 return false;
3056 }
3057
3058 return true;
3059}
3060
3061bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3062{
3063 if (!context->getExtensions().pathRendering)
3064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003065 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003066 return false;
3067 }
3068
3069 // range = 0 is undefined in NV_path_rendering.
3070 // we add stricter semantic check here and require a non zero positive range.
3071 if (range <= 0)
3072 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003073 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003074 return false;
3075 }
3076
3077 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3078 checkedRange += range;
3079
3080 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003083 return false;
3084 }
3085 return true;
3086}
3087
3088bool ValidatePathCommands(Context *context,
3089 GLuint path,
3090 GLsizei numCommands,
3091 const GLubyte *commands,
3092 GLsizei numCoords,
3093 GLenum coordType,
3094 const void *coords)
3095{
3096 if (!context->getExtensions().pathRendering)
3097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003098 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003099 return false;
3100 }
3101 if (!context->hasPath(path))
3102 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003104 return false;
3105 }
3106
3107 if (numCommands < 0)
3108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003109 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003110 return false;
3111 }
3112 else if (numCommands > 0)
3113 {
3114 if (!commands)
3115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003116 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003117 return false;
3118 }
3119 }
3120
3121 if (numCoords < 0)
3122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003123 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003124 return false;
3125 }
3126 else if (numCoords > 0)
3127 {
3128 if (!coords)
3129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003130 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003131 return false;
3132 }
3133 }
3134
3135 std::uint32_t coordTypeSize = 0;
3136 switch (coordType)
3137 {
3138 case GL_BYTE:
3139 coordTypeSize = sizeof(GLbyte);
3140 break;
3141
3142 case GL_UNSIGNED_BYTE:
3143 coordTypeSize = sizeof(GLubyte);
3144 break;
3145
3146 case GL_SHORT:
3147 coordTypeSize = sizeof(GLshort);
3148 break;
3149
3150 case GL_UNSIGNED_SHORT:
3151 coordTypeSize = sizeof(GLushort);
3152 break;
3153
3154 case GL_FLOAT:
3155 coordTypeSize = sizeof(GLfloat);
3156 break;
3157
3158 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003159 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003160 return false;
3161 }
3162
3163 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3164 checkedSize += (coordTypeSize * numCoords);
3165 if (!checkedSize.IsValid())
3166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003168 return false;
3169 }
3170
3171 // early return skips command data validation when it doesn't exist.
3172 if (!commands)
3173 return true;
3174
3175 GLsizei expectedNumCoords = 0;
3176 for (GLsizei i = 0; i < numCommands; ++i)
3177 {
3178 switch (commands[i])
3179 {
3180 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3181 break;
3182 case GL_MOVE_TO_CHROMIUM:
3183 case GL_LINE_TO_CHROMIUM:
3184 expectedNumCoords += 2;
3185 break;
3186 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3187 expectedNumCoords += 4;
3188 break;
3189 case GL_CUBIC_CURVE_TO_CHROMIUM:
3190 expectedNumCoords += 6;
3191 break;
3192 case GL_CONIC_CURVE_TO_CHROMIUM:
3193 expectedNumCoords += 5;
3194 break;
3195 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003196 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003197 return false;
3198 }
3199 }
3200 if (expectedNumCoords != numCoords)
3201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003202 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003203 return false;
3204 }
3205
3206 return true;
3207}
3208
3209bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3210{
3211 if (!context->getExtensions().pathRendering)
3212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003213 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003214 return false;
3215 }
3216 if (!context->hasPath(path))
3217 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003219 return false;
3220 }
3221
3222 switch (pname)
3223 {
3224 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3225 if (value < 0.0f)
3226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003227 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003228 return false;
3229 }
3230 break;
3231 case GL_PATH_END_CAPS_CHROMIUM:
3232 switch (static_cast<GLenum>(value))
3233 {
3234 case GL_FLAT_CHROMIUM:
3235 case GL_SQUARE_CHROMIUM:
3236 case GL_ROUND_CHROMIUM:
3237 break;
3238 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003239 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003240 return false;
3241 }
3242 break;
3243 case GL_PATH_JOIN_STYLE_CHROMIUM:
3244 switch (static_cast<GLenum>(value))
3245 {
3246 case GL_MITER_REVERT_CHROMIUM:
3247 case GL_BEVEL_CHROMIUM:
3248 case GL_ROUND_CHROMIUM:
3249 break;
3250 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003251 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003252 return false;
3253 }
3254 case GL_PATH_MITER_LIMIT_CHROMIUM:
3255 if (value < 0.0f)
3256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003257 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003258 return false;
3259 }
3260 break;
3261
3262 case GL_PATH_STROKE_BOUND_CHROMIUM:
3263 // no errors, only clamping.
3264 break;
3265
3266 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003267 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003268 return false;
3269 }
3270 return true;
3271}
3272
3273bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3274{
3275 if (!context->getExtensions().pathRendering)
3276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003277 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003278 return false;
3279 }
3280
3281 if (!context->hasPath(path))
3282 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003284 return false;
3285 }
3286 if (!value)
3287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003288 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003289 return false;
3290 }
3291
3292 switch (pname)
3293 {
3294 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3295 case GL_PATH_END_CAPS_CHROMIUM:
3296 case GL_PATH_JOIN_STYLE_CHROMIUM:
3297 case GL_PATH_MITER_LIMIT_CHROMIUM:
3298 case GL_PATH_STROKE_BOUND_CHROMIUM:
3299 break;
3300
3301 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003302 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003303 return false;
3304 }
3305
3306 return true;
3307}
3308
3309bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3310{
3311 if (!context->getExtensions().pathRendering)
3312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003313 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003314 return false;
3315 }
3316
3317 switch (func)
3318 {
3319 case GL_NEVER:
3320 case GL_ALWAYS:
3321 case GL_LESS:
3322 case GL_LEQUAL:
3323 case GL_EQUAL:
3324 case GL_GEQUAL:
3325 case GL_GREATER:
3326 case GL_NOTEQUAL:
3327 break;
3328 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003329 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003330 return false;
3331 }
3332
3333 return true;
3334}
3335
3336// Note that the spec specifies that for the path drawing commands
3337// if the path object is not an existing path object the command
3338// does nothing and no error is generated.
3339// However if the path object exists but has not been specified any
3340// commands then an error is generated.
3341
3342bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3343{
3344 if (!context->getExtensions().pathRendering)
3345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003346 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003347 return false;
3348 }
3349 if (context->hasPath(path) && !context->hasPathData(path))
3350 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003351 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003352 return false;
3353 }
3354
3355 switch (fillMode)
3356 {
3357 case GL_COUNT_UP_CHROMIUM:
3358 case GL_COUNT_DOWN_CHROMIUM:
3359 break;
3360 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003361 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003362 return false;
3363 }
3364
3365 if (!isPow2(mask + 1))
3366 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003367 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003368 return false;
3369 }
3370
3371 return true;
3372}
3373
3374bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3375{
3376 if (!context->getExtensions().pathRendering)
3377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003378 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003379 return false;
3380 }
3381 if (context->hasPath(path) && !context->hasPathData(path))
3382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003383 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003384 return false;
3385 }
3386
3387 return true;
3388}
3389
3390bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3391{
3392 if (!context->getExtensions().pathRendering)
3393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003394 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003395 return false;
3396 }
3397 if (context->hasPath(path) && !context->hasPathData(path))
3398 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003399 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003400 return false;
3401 }
3402
3403 switch (coverMode)
3404 {
3405 case GL_CONVEX_HULL_CHROMIUM:
3406 case GL_BOUNDING_BOX_CHROMIUM:
3407 break;
3408 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003410 return false;
3411 }
3412 return true;
3413}
3414
3415bool ValidateStencilThenCoverFillPath(Context *context,
3416 GLuint path,
3417 GLenum fillMode,
3418 GLuint mask,
3419 GLenum coverMode)
3420{
3421 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3422 ValidateCoverPath(context, path, coverMode);
3423}
3424
3425bool ValidateStencilThenCoverStrokePath(Context *context,
3426 GLuint path,
3427 GLint reference,
3428 GLuint mask,
3429 GLenum coverMode)
3430{
3431 return ValidateStencilStrokePath(context, path, reference, mask) &&
3432 ValidateCoverPath(context, path, coverMode);
3433}
3434
3435bool ValidateIsPath(Context *context)
3436{
3437 if (!context->getExtensions().pathRendering)
3438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003439 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003440 return false;
3441 }
3442 return true;
3443}
3444
Sami Väisänend59ca052016-06-21 16:10:00 +03003445bool ValidateCoverFillPathInstanced(Context *context,
3446 GLsizei numPaths,
3447 GLenum pathNameType,
3448 const void *paths,
3449 GLuint pathBase,
3450 GLenum coverMode,
3451 GLenum transformType,
3452 const GLfloat *transformValues)
3453{
3454 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3455 transformType, transformValues))
3456 return false;
3457
3458 switch (coverMode)
3459 {
3460 case GL_CONVEX_HULL_CHROMIUM:
3461 case GL_BOUNDING_BOX_CHROMIUM:
3462 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3463 break;
3464 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003465 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003466 return false;
3467 }
3468
3469 return true;
3470}
3471
3472bool ValidateCoverStrokePathInstanced(Context *context,
3473 GLsizei numPaths,
3474 GLenum pathNameType,
3475 const void *paths,
3476 GLuint pathBase,
3477 GLenum coverMode,
3478 GLenum transformType,
3479 const GLfloat *transformValues)
3480{
3481 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3482 transformType, transformValues))
3483 return false;
3484
3485 switch (coverMode)
3486 {
3487 case GL_CONVEX_HULL_CHROMIUM:
3488 case GL_BOUNDING_BOX_CHROMIUM:
3489 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3490 break;
3491 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003493 return false;
3494 }
3495
3496 return true;
3497}
3498
3499bool ValidateStencilFillPathInstanced(Context *context,
3500 GLsizei numPaths,
3501 GLenum pathNameType,
3502 const void *paths,
3503 GLuint pathBase,
3504 GLenum fillMode,
3505 GLuint mask,
3506 GLenum transformType,
3507 const GLfloat *transformValues)
3508{
3509
3510 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3511 transformType, transformValues))
3512 return false;
3513
3514 switch (fillMode)
3515 {
3516 case GL_COUNT_UP_CHROMIUM:
3517 case GL_COUNT_DOWN_CHROMIUM:
3518 break;
3519 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003520 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003521 return false;
3522 }
3523 if (!isPow2(mask + 1))
3524 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003525 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003526 return false;
3527 }
3528 return true;
3529}
3530
3531bool ValidateStencilStrokePathInstanced(Context *context,
3532 GLsizei numPaths,
3533 GLenum pathNameType,
3534 const void *paths,
3535 GLuint pathBase,
3536 GLint reference,
3537 GLuint mask,
3538 GLenum transformType,
3539 const GLfloat *transformValues)
3540{
3541 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3542 transformType, transformValues))
3543 return false;
3544
3545 // no more validation here.
3546
3547 return true;
3548}
3549
3550bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3551 GLsizei numPaths,
3552 GLenum pathNameType,
3553 const void *paths,
3554 GLuint pathBase,
3555 GLenum fillMode,
3556 GLuint mask,
3557 GLenum coverMode,
3558 GLenum transformType,
3559 const GLfloat *transformValues)
3560{
3561 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3562 transformType, transformValues))
3563 return false;
3564
3565 switch (coverMode)
3566 {
3567 case GL_CONVEX_HULL_CHROMIUM:
3568 case GL_BOUNDING_BOX_CHROMIUM:
3569 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3570 break;
3571 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003572 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003573 return false;
3574 }
3575
3576 switch (fillMode)
3577 {
3578 case GL_COUNT_UP_CHROMIUM:
3579 case GL_COUNT_DOWN_CHROMIUM:
3580 break;
3581 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003583 return false;
3584 }
3585 if (!isPow2(mask + 1))
3586 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003587 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003588 return false;
3589 }
3590
3591 return true;
3592}
3593
3594bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3595 GLsizei numPaths,
3596 GLenum pathNameType,
3597 const void *paths,
3598 GLuint pathBase,
3599 GLint reference,
3600 GLuint mask,
3601 GLenum coverMode,
3602 GLenum transformType,
3603 const GLfloat *transformValues)
3604{
3605 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3606 transformType, transformValues))
3607 return false;
3608
3609 switch (coverMode)
3610 {
3611 case GL_CONVEX_HULL_CHROMIUM:
3612 case GL_BOUNDING_BOX_CHROMIUM:
3613 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3614 break;
3615 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003617 return false;
3618 }
3619
3620 return true;
3621}
3622
Sami Väisänen46eaa942016-06-29 10:26:37 +03003623bool ValidateBindFragmentInputLocation(Context *context,
3624 GLuint program,
3625 GLint location,
3626 const GLchar *name)
3627{
3628 if (!context->getExtensions().pathRendering)
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003631 return false;
3632 }
3633
3634 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3635 if (location >= MaxLocation)
3636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003637 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003638 return false;
3639 }
3640
3641 const auto *programObject = context->getProgram(program);
3642 if (!programObject)
3643 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003645 return false;
3646 }
3647
3648 if (!name)
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003651 return false;
3652 }
3653
3654 if (angle::BeginsWith(name, "gl_"))
3655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003657 return false;
3658 }
3659
3660 return true;
3661}
3662
3663bool ValidateProgramPathFragmentInputGen(Context *context,
3664 GLuint program,
3665 GLint location,
3666 GLenum genMode,
3667 GLint components,
3668 const GLfloat *coeffs)
3669{
3670 if (!context->getExtensions().pathRendering)
3671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003672 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003673 return false;
3674 }
3675
3676 const auto *programObject = context->getProgram(program);
3677 if (!programObject || programObject->isFlaggedForDeletion())
3678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003680 return false;
3681 }
3682
3683 if (!programObject->isLinked())
3684 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003686 return false;
3687 }
3688
3689 switch (genMode)
3690 {
3691 case GL_NONE:
3692 if (components != 0)
3693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003695 return false;
3696 }
3697 break;
3698
3699 case GL_OBJECT_LINEAR_CHROMIUM:
3700 case GL_EYE_LINEAR_CHROMIUM:
3701 case GL_CONSTANT_CHROMIUM:
3702 if (components < 1 || components > 4)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003705 return false;
3706 }
3707 if (!coeffs)
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003710 return false;
3711 }
3712 break;
3713
3714 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003715 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003716 return false;
3717 }
3718
3719 // If the location is -1 then the command is silently ignored
3720 // and no further validation is needed.
3721 if (location == -1)
3722 return true;
3723
Jamie Madillbd044ed2017-06-05 12:59:21 -04003724 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003725
3726 if (!binding.valid)
3727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003729 return false;
3730 }
3731
3732 if (binding.type != GL_NONE)
3733 {
3734 GLint expectedComponents = 0;
3735 switch (binding.type)
3736 {
3737 case GL_FLOAT:
3738 expectedComponents = 1;
3739 break;
3740 case GL_FLOAT_VEC2:
3741 expectedComponents = 2;
3742 break;
3743 case GL_FLOAT_VEC3:
3744 expectedComponents = 3;
3745 break;
3746 case GL_FLOAT_VEC4:
3747 expectedComponents = 4;
3748 break;
3749 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003750 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003751 InvalidOperation()
3752 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003753 return false;
3754 }
3755 if (expectedComponents != components && genMode != GL_NONE)
3756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003758 return false;
3759 }
3760 }
3761 return true;
3762}
3763
Geoff Lang97073d12016-04-20 10:42:34 -07003764bool ValidateCopyTextureCHROMIUM(Context *context,
3765 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003766 GLint sourceLevel,
3767 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003768 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003769 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003770 GLint internalFormat,
3771 GLenum destType,
3772 GLboolean unpackFlipY,
3773 GLboolean unpackPremultiplyAlpha,
3774 GLboolean unpackUnmultiplyAlpha)
3775{
3776 if (!context->getExtensions().copyTexture)
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidOperation()
3779 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003780 return false;
3781 }
3782
Geoff Lang4f0e0032017-05-01 16:04:35 -04003783 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003784 if (source == nullptr)
3785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003786 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003787 return false;
3788 }
3789
3790 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003792 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003793 return false;
3794 }
3795
3796 GLenum sourceTarget = source->getTarget();
3797 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003798
3799 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003801 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003802 return false;
3803 }
3804
Geoff Lang4f0e0032017-05-01 16:04:35 -04003805 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3806 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3807 if (sourceWidth == 0 || sourceHeight == 0)
3808 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003809 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003810 return false;
3811 }
3812
3813 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3814 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003816 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003817 return false;
3818 }
3819
Geoff Lang4f0e0032017-05-01 16:04:35 -04003820 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003821 if (dest == nullptr)
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidValue()
3824 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003825 return false;
3826 }
3827
Geoff Lang4f0e0032017-05-01 16:04:35 -04003828 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003831 return false;
3832 }
3833
Geoff Lang4f0e0032017-05-01 16:04:35 -04003834 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3835 sourceHeight))
3836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003837 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003838 return false;
3839 }
3840
Geoff Lang97073d12016-04-20 10:42:34 -07003841 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3842 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003843 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003844 return false;
3845 }
3846
Geoff Lang4f0e0032017-05-01 16:04:35 -04003847 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003849 context->handleError(
3850 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003851 return false;
3852 }
3853
Geoff Lang97073d12016-04-20 10:42:34 -07003854 if (dest->getImmutableFormat())
3855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003857 return false;
3858 }
3859
3860 return true;
3861}
3862
3863bool ValidateCopySubTextureCHROMIUM(Context *context,
3864 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003865 GLint sourceLevel,
3866 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003867 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003868 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003869 GLint xoffset,
3870 GLint yoffset,
3871 GLint x,
3872 GLint y,
3873 GLsizei width,
3874 GLsizei height,
3875 GLboolean unpackFlipY,
3876 GLboolean unpackPremultiplyAlpha,
3877 GLboolean unpackUnmultiplyAlpha)
3878{
3879 if (!context->getExtensions().copyTexture)
3880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003881 context->handleError(InvalidOperation()
3882 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003883 return false;
3884 }
3885
Geoff Lang4f0e0032017-05-01 16:04:35 -04003886 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003887 if (source == nullptr)
3888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003890 return false;
3891 }
3892
3893 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003896 return false;
3897 }
3898
3899 GLenum sourceTarget = source->getTarget();
3900 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003901
3902 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3903 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003904 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003905 return false;
3906 }
3907
3908 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3909 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003911 context->handleError(InvalidValue()
3912 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003913 return false;
3914 }
3915
3916 if (x < 0 || y < 0)
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003919 return false;
3920 }
3921
3922 if (width < 0 || height < 0)
3923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003924 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003925 return false;
3926 }
3927
Geoff Lang4f0e0032017-05-01 16:04:35 -04003928 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3929 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003932 return false;
3933 }
3934
Geoff Lang4f0e0032017-05-01 16:04:35 -04003935 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3936 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003937 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003938 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003939 return false;
3940 }
3941
Geoff Lang4f0e0032017-05-01 16:04:35 -04003942 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003943 if (dest == nullptr)
3944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003945 context->handleError(InvalidValue()
3946 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003947 return false;
3948 }
3949
Geoff Lang4f0e0032017-05-01 16:04:35 -04003950 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003952 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003953 return false;
3954 }
3955
Geoff Lang4f0e0032017-05-01 16:04:35 -04003956 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003959 return false;
3960 }
3961
Geoff Lang4f0e0032017-05-01 16:04:35 -04003962 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3963 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003964 context
3965 ->handleError(InvalidOperation()
3966 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003967 return false;
3968 }
3969
3970 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3971 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003973 context->handleError(InvalidOperation()
3974 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003975 return false;
3976 }
3977
3978 if (xoffset < 0 || yoffset < 0)
3979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003980 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07003981 return false;
3982 }
3983
Geoff Lang4f0e0032017-05-01 16:04:35 -04003984 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3985 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003988 return false;
3989 }
3990
3991 return true;
3992}
3993
Geoff Lang47110bf2016-04-20 11:13:22 -07003994bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3995{
3996 if (!context->getExtensions().copyCompressedTexture)
3997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003998 context->handleError(InvalidOperation()
3999 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004000 return false;
4001 }
4002
4003 const gl::Texture *source = context->getTexture(sourceId);
4004 if (source == nullptr)
4005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004006 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004007 return false;
4008 }
4009
4010 if (source->getTarget() != GL_TEXTURE_2D)
4011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004012 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004013 return false;
4014 }
4015
4016 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004018 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004019 return false;
4020 }
4021
4022 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4023 if (!sourceFormat.info->compressed)
4024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004025 context->handleError(InvalidOperation()
4026 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004027 return false;
4028 }
4029
4030 const gl::Texture *dest = context->getTexture(destId);
4031 if (dest == nullptr)
4032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004033 context->handleError(InvalidValue()
4034 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004035 return false;
4036 }
4037
4038 if (dest->getTarget() != GL_TEXTURE_2D)
4039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004040 context->handleError(InvalidValue()
4041 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004042 return false;
4043 }
4044
4045 if (dest->getImmutableFormat())
4046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004047 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004048 return false;
4049 }
4050
4051 return true;
4052}
4053
Martin Radev4c4c8e72016-08-04 12:25:34 +03004054bool ValidateCreateShader(Context *context, GLenum type)
4055{
4056 switch (type)
4057 {
4058 case GL_VERTEX_SHADER:
4059 case GL_FRAGMENT_SHADER:
4060 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004061
Martin Radev4c4c8e72016-08-04 12:25:34 +03004062 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004063 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004065 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04004066 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004067 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004068 break;
4069
Martin Radev4c4c8e72016-08-04 12:25:34 +03004070 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004071 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004072 return false;
4073 }
Jamie Madill29639852016-09-02 15:00:09 -04004074
4075 return true;
4076}
4077
4078bool ValidateBufferData(ValidationContext *context,
4079 GLenum target,
4080 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004081 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04004082 GLenum usage)
4083{
4084 if (size < 0)
4085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004086 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004087 return false;
4088 }
4089
4090 switch (usage)
4091 {
4092 case GL_STREAM_DRAW:
4093 case GL_STATIC_DRAW:
4094 case GL_DYNAMIC_DRAW:
4095 break;
4096
4097 case GL_STREAM_READ:
4098 case GL_STREAM_COPY:
4099 case GL_STATIC_READ:
4100 case GL_STATIC_COPY:
4101 case GL_DYNAMIC_READ:
4102 case GL_DYNAMIC_COPY:
4103 if (context->getClientMajorVersion() < 3)
4104 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004106 return false;
4107 }
4108 break;
4109
4110 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004112 return false;
4113 }
4114
4115 if (!ValidBufferTarget(context, target))
4116 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004118 return false;
4119 }
4120
4121 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4122
4123 if (!buffer)
4124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004126 return false;
4127 }
4128
4129 return true;
4130}
4131
4132bool ValidateBufferSubData(ValidationContext *context,
4133 GLenum target,
4134 GLintptr offset,
4135 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004136 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004137{
Brandon Jones6cad5662017-06-14 13:25:13 -07004138 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004140 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4141 return false;
4142 }
4143
4144 if (offset < 0)
4145 {
4146 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004147 return false;
4148 }
4149
4150 if (!ValidBufferTarget(context, target))
4151 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004152 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004153 return false;
4154 }
4155
4156 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4157
4158 if (!buffer)
4159 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004160 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004161 return false;
4162 }
4163
4164 if (buffer->isMapped())
4165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004166 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004167 return false;
4168 }
4169
4170 // Check for possible overflow of size + offset
4171 angle::CheckedNumeric<size_t> checkedSize(size);
4172 checkedSize += offset;
4173 if (!checkedSize.IsValid())
4174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004175 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004176 return false;
4177 }
4178
4179 if (size + offset > buffer->getSize())
4180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004181 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004182 return false;
4183 }
4184
Martin Radev4c4c8e72016-08-04 12:25:34 +03004185 return true;
4186}
4187
Geoff Langc339c4e2016-11-29 10:37:36 -05004188bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004189{
Geoff Langc339c4e2016-11-29 10:37:36 -05004190 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004192 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004193 return false;
4194 }
4195
4196 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
4197 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05004198 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04004199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004200 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004201 return false;
4202 }
4203
4204 return true;
4205}
4206
Jamie Madillef300b12016-10-07 15:12:09 -04004207bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4208{
4209 if (texture < GL_TEXTURE0 ||
4210 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004212 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004213 return false;
4214 }
4215
4216 return true;
4217}
4218
4219bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4220{
4221 Program *programObject = GetValidProgram(context, program);
4222 if (!programObject)
4223 {
4224 return false;
4225 }
4226
4227 Shader *shaderObject = GetValidShader(context, shader);
4228 if (!shaderObject)
4229 {
4230 return false;
4231 }
4232
4233 switch (shaderObject->getType())
4234 {
4235 case GL_VERTEX_SHADER:
4236 {
4237 if (programObject->getAttachedVertexShader())
4238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004240 return false;
4241 }
4242 break;
4243 }
4244 case GL_FRAGMENT_SHADER:
4245 {
4246 if (programObject->getAttachedFragmentShader())
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004249 return false;
4250 }
4251 break;
4252 }
4253 case GL_COMPUTE_SHADER:
4254 {
4255 if (programObject->getAttachedComputeShader())
4256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004258 return false;
4259 }
4260 break;
4261 }
4262 default:
4263 UNREACHABLE();
4264 break;
4265 }
4266
4267 return true;
4268}
4269
Jamie Madill01a80ee2016-11-07 12:06:18 -05004270bool ValidateBindAttribLocation(ValidationContext *context,
4271 GLuint program,
4272 GLuint index,
4273 const GLchar *name)
4274{
4275 if (index >= MAX_VERTEX_ATTRIBS)
4276 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004277 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004278 return false;
4279 }
4280
4281 if (strncmp(name, "gl_", 3) == 0)
4282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004284 return false;
4285 }
4286
Geoff Langfc32e8b2017-05-31 14:16:59 -04004287 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4288 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04004289 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004291 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004292 return false;
4293 }
4294
Jamie Madill01a80ee2016-11-07 12:06:18 -05004295 return GetValidProgram(context, program) != nullptr;
4296}
4297
4298bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4299{
4300 if (!ValidBufferTarget(context, target))
4301 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004302 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004303 return false;
4304 }
4305
4306 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4307 !context->isBufferGenerated(buffer))
4308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004310 return false;
4311 }
4312
4313 return true;
4314}
4315
4316bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4317{
4318 if (!ValidFramebufferTarget(target))
4319 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004321 return false;
4322 }
4323
4324 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4325 !context->isFramebufferGenerated(framebuffer))
4326 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004327 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004328 return false;
4329 }
4330
4331 return true;
4332}
4333
4334bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4335{
4336 if (target != GL_RENDERBUFFER)
4337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004338 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004339 return false;
4340 }
4341
4342 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4343 !context->isRenderbufferGenerated(renderbuffer))
4344 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004345 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004346 return false;
4347 }
4348
4349 return true;
4350}
4351
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004352static bool ValidBlendEquationMode(GLenum mode)
4353{
4354 switch (mode)
4355 {
4356 case GL_FUNC_ADD:
4357 case GL_FUNC_SUBTRACT:
4358 case GL_FUNC_REVERSE_SUBTRACT:
4359 case GL_MIN:
4360 case GL_MAX:
4361 return true;
4362
4363 default:
4364 return false;
4365 }
4366}
4367
Jamie Madillc1d770e2017-04-13 17:31:24 -04004368bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004369 GLfloat red,
4370 GLfloat green,
4371 GLfloat blue,
4372 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004373{
4374 return true;
4375}
4376
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004377bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4378{
4379 if (!ValidBlendEquationMode(mode))
4380 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004382 return false;
4383 }
4384
4385 return true;
4386}
4387
4388bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4389{
4390 if (!ValidBlendEquationMode(modeRGB))
4391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004393 return false;
4394 }
4395
4396 if (!ValidBlendEquationMode(modeAlpha))
4397 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004399 return false;
4400 }
4401
4402 return true;
4403}
4404
4405bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4406{
4407 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4408}
4409
4410static bool ValidSrcBlendFunc(GLenum srcBlend)
4411{
4412 switch (srcBlend)
4413 {
4414 case GL_ZERO:
4415 case GL_ONE:
4416 case GL_SRC_COLOR:
4417 case GL_ONE_MINUS_SRC_COLOR:
4418 case GL_DST_COLOR:
4419 case GL_ONE_MINUS_DST_COLOR:
4420 case GL_SRC_ALPHA:
4421 case GL_ONE_MINUS_SRC_ALPHA:
4422 case GL_DST_ALPHA:
4423 case GL_ONE_MINUS_DST_ALPHA:
4424 case GL_CONSTANT_COLOR:
4425 case GL_ONE_MINUS_CONSTANT_COLOR:
4426 case GL_CONSTANT_ALPHA:
4427 case GL_ONE_MINUS_CONSTANT_ALPHA:
4428 case GL_SRC_ALPHA_SATURATE:
4429 return true;
4430
4431 default:
4432 return false;
4433 }
4434}
4435
4436static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4437{
4438 switch (dstBlend)
4439 {
4440 case GL_ZERO:
4441 case GL_ONE:
4442 case GL_SRC_COLOR:
4443 case GL_ONE_MINUS_SRC_COLOR:
4444 case GL_DST_COLOR:
4445 case GL_ONE_MINUS_DST_COLOR:
4446 case GL_SRC_ALPHA:
4447 case GL_ONE_MINUS_SRC_ALPHA:
4448 case GL_DST_ALPHA:
4449 case GL_ONE_MINUS_DST_ALPHA:
4450 case GL_CONSTANT_COLOR:
4451 case GL_ONE_MINUS_CONSTANT_COLOR:
4452 case GL_CONSTANT_ALPHA:
4453 case GL_ONE_MINUS_CONSTANT_ALPHA:
4454 return true;
4455
4456 case GL_SRC_ALPHA_SATURATE:
4457 return (contextMajorVersion >= 3);
4458
4459 default:
4460 return false;
4461 }
4462}
4463
4464bool ValidateBlendFuncSeparate(ValidationContext *context,
4465 GLenum srcRGB,
4466 GLenum dstRGB,
4467 GLenum srcAlpha,
4468 GLenum dstAlpha)
4469{
4470 if (!ValidSrcBlendFunc(srcRGB))
4471 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004473 return false;
4474 }
4475
4476 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4477 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004479 return false;
4480 }
4481
4482 if (!ValidSrcBlendFunc(srcAlpha))
4483 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004484 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004485 return false;
4486 }
4487
4488 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4489 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004491 return false;
4492 }
4493
Frank Henigman146e8a12017-03-02 23:22:37 -05004494 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4495 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004496 {
4497 bool constantColorUsed =
4498 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4499 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4500
4501 bool constantAlphaUsed =
4502 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4503 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4504
4505 if (constantColorUsed && constantAlphaUsed)
4506 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004507 const char *msg;
4508 if (context->getExtensions().webglCompatibility)
4509 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004510 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004511 }
4512 else
4513 {
4514 msg =
4515 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4516 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4517 "implementation.";
4518 ERR() << msg;
4519 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004520 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004521 return false;
4522 }
4523 }
4524
4525 return true;
4526}
4527
Geoff Langc339c4e2016-11-29 10:37:36 -05004528bool ValidateGetString(Context *context, GLenum name)
4529{
4530 switch (name)
4531 {
4532 case GL_VENDOR:
4533 case GL_RENDERER:
4534 case GL_VERSION:
4535 case GL_SHADING_LANGUAGE_VERSION:
4536 case GL_EXTENSIONS:
4537 break;
4538
4539 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4540 if (!context->getExtensions().requestExtension)
4541 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004543 return false;
4544 }
4545 break;
4546
4547 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004549 return false;
4550 }
4551
4552 return true;
4553}
4554
Geoff Lang47c48082016-12-07 15:38:13 -05004555bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4556{
4557 if (width <= 0.0f || isNaN(width))
4558 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004559 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004560 return false;
4561 }
4562
4563 return true;
4564}
4565
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004566bool ValidateVertexAttribPointer(ValidationContext *context,
4567 GLuint index,
4568 GLint size,
4569 GLenum type,
4570 GLboolean normalized,
4571 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004572 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004573{
Shao80957d92017-02-20 21:25:59 +08004574 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004575 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004576 return false;
4577 }
4578
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004579 if (stride < 0)
4580 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004581 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004582 return false;
4583 }
4584
Shao80957d92017-02-20 21:25:59 +08004585 const Caps &caps = context->getCaps();
4586 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004587 {
Shao80957d92017-02-20 21:25:59 +08004588 if (stride > caps.maxVertexAttribStride)
4589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004590 context->handleError(InvalidValue()
4591 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004592 return false;
4593 }
4594
4595 if (index >= caps.maxVertexAttribBindings)
4596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004597 context->handleError(InvalidValue()
4598 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004599 return false;
4600 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004601 }
4602
4603 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4604 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4605 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4606 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004607 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4608 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004609 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004611 context
4612 ->handleError(InvalidOperation()
4613 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004614 return false;
4615 }
4616
4617 if (context->getExtensions().webglCompatibility)
4618 {
4619 // WebGL 1.0 [Section 6.14] Fixed point support
4620 // The WebGL API does not support the GL_FIXED data type.
4621 if (type == GL_FIXED)
4622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004623 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004624 return false;
4625 }
4626
Geoff Lang2d62ab72017-03-23 16:54:40 -04004627 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004628 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004629 return false;
4630 }
4631 }
4632
4633 return true;
4634}
4635
Jamie Madill876429b2017-04-20 15:46:24 -04004636bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004637{
4638 if (context->getExtensions().webglCompatibility && zNear > zFar)
4639 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004640 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004641 return false;
4642 }
4643
4644 return true;
4645}
4646
Jamie Madille8fb6402017-02-14 17:56:40 -05004647bool ValidateRenderbufferStorage(ValidationContext *context,
4648 GLenum target,
4649 GLenum internalformat,
4650 GLsizei width,
4651 GLsizei height)
4652{
4653 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4654 height);
4655}
4656
4657bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4658 GLenum target,
4659 GLsizei samples,
4660 GLenum internalformat,
4661 GLsizei width,
4662 GLsizei height)
4663{
4664 if (!context->getExtensions().framebufferMultisample)
4665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004666 context->handleError(InvalidOperation()
4667 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004668 return false;
4669 }
4670
4671 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4672 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4673 // generated.
4674 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004676 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004677 return false;
4678 }
4679
4680 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4681 // the specified storage. This is different than ES 3.0 in which a sample number higher
4682 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4683 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4684 if (context->getClientMajorVersion() >= 3)
4685 {
4686 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4687 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004689 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004690 return false;
4691 }
4692 }
4693
4694 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4695 width, height);
4696}
4697
Jamie Madillc1d770e2017-04-13 17:31:24 -04004698bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4699{
4700 if (!ValidFramebufferTarget(target))
4701 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004702 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004703 return false;
4704 }
4705
4706 return true;
4707}
4708
4709bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004710 GLfloat red,
4711 GLfloat green,
4712 GLfloat blue,
4713 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004714{
4715 return true;
4716}
4717
Jamie Madill876429b2017-04-20 15:46:24 -04004718bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004719{
4720 return true;
4721}
4722
4723bool ValidateClearStencil(ValidationContext *context, GLint s)
4724{
4725 return true;
4726}
4727
4728bool ValidateColorMask(ValidationContext *context,
4729 GLboolean red,
4730 GLboolean green,
4731 GLboolean blue,
4732 GLboolean alpha)
4733{
4734 return true;
4735}
4736
4737bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4738{
4739 return true;
4740}
4741
4742bool ValidateCreateProgram(ValidationContext *context)
4743{
4744 return true;
4745}
4746
4747bool ValidateCullFace(ValidationContext *context, GLenum mode)
4748{
4749 switch (mode)
4750 {
4751 case GL_FRONT:
4752 case GL_BACK:
4753 case GL_FRONT_AND_BACK:
4754 break;
4755
4756 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004758 return false;
4759 }
4760
4761 return true;
4762}
4763
4764bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4765{
4766 if (program == 0)
4767 {
4768 return false;
4769 }
4770
4771 if (!context->getProgram(program))
4772 {
4773 if (context->getShader(program))
4774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004775 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004776 return false;
4777 }
4778 else
4779 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004780 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004781 return false;
4782 }
4783 }
4784
4785 return true;
4786}
4787
4788bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4789{
4790 if (shader == 0)
4791 {
4792 return false;
4793 }
4794
4795 if (!context->getShader(shader))
4796 {
4797 if (context->getProgram(shader))
4798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004799 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004800 return false;
4801 }
4802 else
4803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004804 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004805 return false;
4806 }
4807 }
4808
4809 return true;
4810}
4811
4812bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4813{
4814 switch (func)
4815 {
4816 case GL_NEVER:
4817 case GL_ALWAYS:
4818 case GL_LESS:
4819 case GL_LEQUAL:
4820 case GL_EQUAL:
4821 case GL_GREATER:
4822 case GL_GEQUAL:
4823 case GL_NOTEQUAL:
4824 break;
4825
4826 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004828 return false;
4829 }
4830
4831 return true;
4832}
4833
4834bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4835{
4836 return true;
4837}
4838
4839bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4840{
4841 Program *programObject = GetValidProgram(context, program);
4842 if (!programObject)
4843 {
4844 return false;
4845 }
4846
4847 Shader *shaderObject = GetValidShader(context, shader);
4848 if (!shaderObject)
4849 {
4850 return false;
4851 }
4852
4853 const Shader *attachedShader = nullptr;
4854
4855 switch (shaderObject->getType())
4856 {
4857 case GL_VERTEX_SHADER:
4858 {
4859 attachedShader = programObject->getAttachedVertexShader();
4860 break;
4861 }
4862 case GL_FRAGMENT_SHADER:
4863 {
4864 attachedShader = programObject->getAttachedFragmentShader();
4865 break;
4866 }
4867 case GL_COMPUTE_SHADER:
4868 {
4869 attachedShader = programObject->getAttachedComputeShader();
4870 break;
4871 }
4872 default:
4873 UNREACHABLE();
4874 return false;
4875 }
4876
4877 if (attachedShader != shaderObject)
4878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004880 return false;
4881 }
4882
4883 return true;
4884}
4885
4886bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4887{
4888 if (index >= MAX_VERTEX_ATTRIBS)
4889 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004890 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004891 return false;
4892 }
4893
4894 return true;
4895}
4896
4897bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4898{
4899 if (index >= MAX_VERTEX_ATTRIBS)
4900 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004901 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004902 return false;
4903 }
4904
4905 return true;
4906}
4907
4908bool ValidateFinish(ValidationContext *context)
4909{
4910 return true;
4911}
4912
4913bool ValidateFlush(ValidationContext *context)
4914{
4915 return true;
4916}
4917
4918bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4919{
4920 switch (mode)
4921 {
4922 case GL_CW:
4923 case GL_CCW:
4924 break;
4925 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004926 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004927 return false;
4928 }
4929
4930 return true;
4931}
4932
4933bool ValidateGetActiveAttrib(ValidationContext *context,
4934 GLuint program,
4935 GLuint index,
4936 GLsizei bufsize,
4937 GLsizei *length,
4938 GLint *size,
4939 GLenum *type,
4940 GLchar *name)
4941{
4942 if (bufsize < 0)
4943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004944 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004945 return false;
4946 }
4947
4948 Program *programObject = GetValidProgram(context, program);
4949
4950 if (!programObject)
4951 {
4952 return false;
4953 }
4954
4955 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4956 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004957 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004958 return false;
4959 }
4960
4961 return true;
4962}
4963
4964bool ValidateGetActiveUniform(ValidationContext *context,
4965 GLuint program,
4966 GLuint index,
4967 GLsizei bufsize,
4968 GLsizei *length,
4969 GLint *size,
4970 GLenum *type,
4971 GLchar *name)
4972{
4973 if (bufsize < 0)
4974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004975 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004976 return false;
4977 }
4978
4979 Program *programObject = GetValidProgram(context, program);
4980
4981 if (!programObject)
4982 {
4983 return false;
4984 }
4985
4986 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4987 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004988 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004989 return false;
4990 }
4991
4992 return true;
4993}
4994
4995bool ValidateGetAttachedShaders(ValidationContext *context,
4996 GLuint program,
4997 GLsizei maxcount,
4998 GLsizei *count,
4999 GLuint *shaders)
5000{
5001 if (maxcount < 0)
5002 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005003 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005004 return false;
5005 }
5006
5007 Program *programObject = GetValidProgram(context, program);
5008
5009 if (!programObject)
5010 {
5011 return false;
5012 }
5013
5014 return true;
5015}
5016
5017bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5018{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005019 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5020 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005021 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005023 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005024 return false;
5025 }
5026
Jamie Madillc1d770e2017-04-13 17:31:24 -04005027 Program *programObject = GetValidProgram(context, program);
5028
5029 if (!programObject)
5030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005032 return false;
5033 }
5034
5035 if (!programObject->isLinked())
5036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005037 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005038 return false;
5039 }
5040
5041 return true;
5042}
5043
5044bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5045{
5046 GLenum nativeType;
5047 unsigned int numParams = 0;
5048 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5049}
5050
5051bool ValidateGetError(ValidationContext *context)
5052{
5053 return true;
5054}
5055
5056bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5057{
5058 GLenum nativeType;
5059 unsigned int numParams = 0;
5060 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5061}
5062
5063bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5064{
5065 GLenum nativeType;
5066 unsigned int numParams = 0;
5067 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5068}
5069
5070bool ValidateGetProgramInfoLog(ValidationContext *context,
5071 GLuint program,
5072 GLsizei bufsize,
5073 GLsizei *length,
5074 GLchar *infolog)
5075{
5076 if (bufsize < 0)
5077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005078 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005079 return false;
5080 }
5081
5082 Program *programObject = GetValidProgram(context, program);
5083 if (!programObject)
5084 {
5085 return false;
5086 }
5087
5088 return true;
5089}
5090
5091bool ValidateGetShaderInfoLog(ValidationContext *context,
5092 GLuint shader,
5093 GLsizei bufsize,
5094 GLsizei *length,
5095 GLchar *infolog)
5096{
5097 if (bufsize < 0)
5098 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005099 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005100 return false;
5101 }
5102
5103 Shader *shaderObject = GetValidShader(context, shader);
5104 if (!shaderObject)
5105 {
5106 return false;
5107 }
5108
5109 return true;
5110}
5111
5112bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5113 GLenum shadertype,
5114 GLenum precisiontype,
5115 GLint *range,
5116 GLint *precision)
5117{
5118 switch (shadertype)
5119 {
5120 case GL_VERTEX_SHADER:
5121 case GL_FRAGMENT_SHADER:
5122 break;
5123 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005124 context->handleError(InvalidOperation()
5125 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005126 return false;
5127 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005129 return false;
5130 }
5131
5132 switch (precisiontype)
5133 {
5134 case GL_LOW_FLOAT:
5135 case GL_MEDIUM_FLOAT:
5136 case GL_HIGH_FLOAT:
5137 case GL_LOW_INT:
5138 case GL_MEDIUM_INT:
5139 case GL_HIGH_INT:
5140 break;
5141
5142 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005144 return false;
5145 }
5146
5147 return true;
5148}
5149
5150bool ValidateGetShaderSource(ValidationContext *context,
5151 GLuint shader,
5152 GLsizei bufsize,
5153 GLsizei *length,
5154 GLchar *source)
5155{
5156 if (bufsize < 0)
5157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005158 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005159 return false;
5160 }
5161
5162 Shader *shaderObject = GetValidShader(context, shader);
5163 if (!shaderObject)
5164 {
5165 return false;
5166 }
5167
5168 return true;
5169}
5170
5171bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5172{
5173 if (strstr(name, "gl_") == name)
5174 {
5175 return false;
5176 }
5177
Geoff Langfc32e8b2017-05-31 14:16:59 -04005178 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5179 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005180 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005182 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005183 return false;
5184 }
5185
Jamie Madillc1d770e2017-04-13 17:31:24 -04005186 Program *programObject = GetValidProgram(context, program);
5187
5188 if (!programObject)
5189 {
5190 return false;
5191 }
5192
5193 if (!programObject->isLinked())
5194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005196 return false;
5197 }
5198
5199 return true;
5200}
5201
5202bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5203{
5204 switch (mode)
5205 {
5206 case GL_FASTEST:
5207 case GL_NICEST:
5208 case GL_DONT_CARE:
5209 break;
5210
5211 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005212 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005213 return false;
5214 }
5215
5216 switch (target)
5217 {
5218 case GL_GENERATE_MIPMAP_HINT:
5219 break;
5220
Geoff Lange7bd2182017-06-16 16:13:13 -04005221 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5222 if (context->getClientVersion() < ES_3_0 &&
5223 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005225 context->handleError(InvalidOperation()
5226 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005227 return false;
5228 }
5229 break;
5230
5231 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005233 return false;
5234 }
5235
5236 return true;
5237}
5238
5239bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5240{
5241 return true;
5242}
5243
5244bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5245{
5246 return true;
5247}
5248
5249bool ValidateIsProgram(ValidationContext *context, GLuint program)
5250{
5251 return true;
5252}
5253
5254bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5255{
5256 return true;
5257}
5258
5259bool ValidateIsShader(ValidationContext *context, GLuint shader)
5260{
5261 return true;
5262}
5263
5264bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5265{
5266 return true;
5267}
5268
5269bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5270{
5271 if (context->getClientMajorVersion() < 3)
5272 {
5273 switch (pname)
5274 {
5275 case GL_UNPACK_IMAGE_HEIGHT:
5276 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005277 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005278 return false;
5279
5280 case GL_UNPACK_ROW_LENGTH:
5281 case GL_UNPACK_SKIP_ROWS:
5282 case GL_UNPACK_SKIP_PIXELS:
5283 if (!context->getExtensions().unpackSubimage)
5284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005285 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005286 return false;
5287 }
5288 break;
5289
5290 case GL_PACK_ROW_LENGTH:
5291 case GL_PACK_SKIP_ROWS:
5292 case GL_PACK_SKIP_PIXELS:
5293 if (!context->getExtensions().packSubimage)
5294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005295 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005296 return false;
5297 }
5298 break;
5299 }
5300 }
5301
5302 if (param < 0)
5303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005304 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005305 return false;
5306 }
5307
5308 switch (pname)
5309 {
5310 case GL_UNPACK_ALIGNMENT:
5311 if (param != 1 && param != 2 && param != 4 && param != 8)
5312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005313 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005314 return false;
5315 }
5316 break;
5317
5318 case GL_PACK_ALIGNMENT:
5319 if (param != 1 && param != 2 && param != 4 && param != 8)
5320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005321 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005322 return false;
5323 }
5324 break;
5325
5326 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5327 case GL_UNPACK_ROW_LENGTH:
5328 case GL_UNPACK_IMAGE_HEIGHT:
5329 case GL_UNPACK_SKIP_IMAGES:
5330 case GL_UNPACK_SKIP_ROWS:
5331 case GL_UNPACK_SKIP_PIXELS:
5332 case GL_PACK_ROW_LENGTH:
5333 case GL_PACK_SKIP_ROWS:
5334 case GL_PACK_SKIP_PIXELS:
5335 break;
5336
5337 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005338 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005339 return false;
5340 }
5341
5342 return true;
5343}
5344
5345bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5346{
5347 return true;
5348}
5349
5350bool ValidateReleaseShaderCompiler(ValidationContext *context)
5351{
5352 return true;
5353}
5354
Jamie Madill876429b2017-04-20 15:46:24 -04005355bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005356{
5357 return true;
5358}
5359
5360bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5361{
5362 if (width < 0 || height < 0)
5363 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005364 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005365 return false;
5366 }
5367
5368 return true;
5369}
5370
5371bool ValidateShaderBinary(ValidationContext *context,
5372 GLsizei n,
5373 const GLuint *shaders,
5374 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005375 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005376 GLsizei length)
5377{
5378 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5379 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5380 shaderBinaryFormats.end())
5381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005382 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005383 return false;
5384 }
5385
5386 return true;
5387}
5388
5389bool ValidateShaderSource(ValidationContext *context,
5390 GLuint shader,
5391 GLsizei count,
5392 const GLchar *const *string,
5393 const GLint *length)
5394{
5395 if (count < 0)
5396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005397 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005398 return false;
5399 }
5400
Geoff Langfc32e8b2017-05-31 14:16:59 -04005401 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5402 // shader-related entry points
5403 if (context->getExtensions().webglCompatibility)
5404 {
5405 for (GLsizei i = 0; i < count; i++)
5406 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005407 size_t len =
5408 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005409
5410 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005411 if (!IsValidESSLShaderSourceString(string[i], len,
5412 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005414 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005415 return false;
5416 }
5417 }
5418 }
5419
Jamie Madillc1d770e2017-04-13 17:31:24 -04005420 Shader *shaderObject = GetValidShader(context, shader);
5421 if (!shaderObject)
5422 {
5423 return false;
5424 }
5425
5426 return true;
5427}
5428
5429bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5430{
5431 if (!IsValidStencilFunc(func))
5432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005434 return false;
5435 }
5436
5437 return true;
5438}
5439
5440bool ValidateStencilFuncSeparate(ValidationContext *context,
5441 GLenum face,
5442 GLenum func,
5443 GLint ref,
5444 GLuint mask)
5445{
5446 if (!IsValidStencilFace(face))
5447 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005448 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005449 return false;
5450 }
5451
5452 if (!IsValidStencilFunc(func))
5453 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005455 return false;
5456 }
5457
5458 return true;
5459}
5460
5461bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5462{
5463 return true;
5464}
5465
5466bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5467{
5468 if (!IsValidStencilFace(face))
5469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005471 return false;
5472 }
5473
5474 return true;
5475}
5476
5477bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5478{
5479 if (!IsValidStencilOp(fail))
5480 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005482 return false;
5483 }
5484
5485 if (!IsValidStencilOp(zfail))
5486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005488 return false;
5489 }
5490
5491 if (!IsValidStencilOp(zpass))
5492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005494 return false;
5495 }
5496
5497 return true;
5498}
5499
5500bool ValidateStencilOpSeparate(ValidationContext *context,
5501 GLenum face,
5502 GLenum fail,
5503 GLenum zfail,
5504 GLenum zpass)
5505{
5506 if (!IsValidStencilFace(face))
5507 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005508 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005509 return false;
5510 }
5511
5512 return ValidateStencilOp(context, fail, zfail, zpass);
5513}
5514
5515bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5516{
5517 return ValidateUniform(context, GL_FLOAT, location, 1);
5518}
5519
5520bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5521{
5522 return ValidateUniform(context, GL_FLOAT, location, count);
5523}
5524
Jamie Madillbe849e42017-05-02 15:49:00 -04005525bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5526{
5527 return ValidateUniform1iv(context, location, 1, &x);
5528}
5529
Jamie Madillc1d770e2017-04-13 17:31:24 -04005530bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5531{
5532 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5533}
5534
5535bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5536{
5537 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5538}
5539
5540bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5541{
5542 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5543}
5544
5545bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5546{
5547 return ValidateUniform(context, GL_INT_VEC2, location, count);
5548}
5549
5550bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5551{
5552 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5553}
5554
5555bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5556{
5557 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5558}
5559
5560bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5561{
5562 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5563}
5564
5565bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5566{
5567 return ValidateUniform(context, GL_INT_VEC3, location, count);
5568}
5569
5570bool ValidateUniform4f(ValidationContext *context,
5571 GLint location,
5572 GLfloat x,
5573 GLfloat y,
5574 GLfloat z,
5575 GLfloat w)
5576{
5577 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5578}
5579
5580bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5581{
5582 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5583}
5584
5585bool ValidateUniform4i(ValidationContext *context,
5586 GLint location,
5587 GLint x,
5588 GLint y,
5589 GLint z,
5590 GLint w)
5591{
5592 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5593}
5594
5595bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5596{
5597 return ValidateUniform(context, GL_INT_VEC4, location, count);
5598}
5599
5600bool ValidateUniformMatrix2fv(ValidationContext *context,
5601 GLint location,
5602 GLsizei count,
5603 GLboolean transpose,
5604 const GLfloat *value)
5605{
5606 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5607}
5608
5609bool ValidateUniformMatrix3fv(ValidationContext *context,
5610 GLint location,
5611 GLsizei count,
5612 GLboolean transpose,
5613 const GLfloat *value)
5614{
5615 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5616}
5617
5618bool ValidateUniformMatrix4fv(ValidationContext *context,
5619 GLint location,
5620 GLsizei count,
5621 GLboolean transpose,
5622 const GLfloat *value)
5623{
5624 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5625}
5626
5627bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5628{
5629 Program *programObject = GetValidProgram(context, program);
5630
5631 if (!programObject)
5632 {
5633 return false;
5634 }
5635
5636 return true;
5637}
5638
Jamie Madillc1d770e2017-04-13 17:31:24 -04005639bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5640{
5641 return ValidateVertexAttribIndex(context, index);
5642}
5643
5644bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5645{
5646 return ValidateVertexAttribIndex(context, index);
5647}
5648
5649bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5650{
5651 return ValidateVertexAttribIndex(context, index);
5652}
5653
5654bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5655{
5656 return ValidateVertexAttribIndex(context, index);
5657}
5658
5659bool ValidateVertexAttrib3f(ValidationContext *context,
5660 GLuint index,
5661 GLfloat x,
5662 GLfloat y,
5663 GLfloat z)
5664{
5665 return ValidateVertexAttribIndex(context, index);
5666}
5667
5668bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5669{
5670 return ValidateVertexAttribIndex(context, index);
5671}
5672
5673bool ValidateVertexAttrib4f(ValidationContext *context,
5674 GLuint index,
5675 GLfloat x,
5676 GLfloat y,
5677 GLfloat z,
5678 GLfloat w)
5679{
5680 return ValidateVertexAttribIndex(context, index);
5681}
5682
5683bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5684{
5685 return ValidateVertexAttribIndex(context, index);
5686}
5687
5688bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5689{
5690 if (width < 0 || height < 0)
5691 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005692 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005693 return false;
5694 }
5695
5696 return true;
5697}
5698
5699bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5700{
5701 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5702}
5703
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005704bool ValidateDrawElements(ValidationContext *context,
5705 GLenum mode,
5706 GLsizei count,
5707 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005708 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005709{
5710 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5711}
5712
Jamie Madillbe849e42017-05-02 15:49:00 -04005713bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5714 GLenum target,
5715 GLenum attachment,
5716 GLenum pname,
5717 GLint *params)
5718{
5719 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5720 nullptr);
5721}
5722
5723bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5724{
5725 return ValidateGetProgramivBase(context, program, pname, nullptr);
5726}
5727
5728bool ValidateCopyTexImage2D(ValidationContext *context,
5729 GLenum target,
5730 GLint level,
5731 GLenum internalformat,
5732 GLint x,
5733 GLint y,
5734 GLsizei width,
5735 GLsizei height,
5736 GLint border)
5737{
5738 if (context->getClientMajorVersion() < 3)
5739 {
5740 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5741 0, x, y, width, height, border);
5742 }
5743
5744 ASSERT(context->getClientMajorVersion() == 3);
5745 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5746 0, x, y, width, height, border);
5747}
5748
5749bool ValidateCopyTexSubImage2D(Context *context,
5750 GLenum target,
5751 GLint level,
5752 GLint xoffset,
5753 GLint yoffset,
5754 GLint x,
5755 GLint y,
5756 GLsizei width,
5757 GLsizei height)
5758{
5759 if (context->getClientMajorVersion() < 3)
5760 {
5761 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5762 yoffset, x, y, width, height, 0);
5763 }
5764
5765 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5766 yoffset, 0, x, y, width, height, 0);
5767}
5768
5769bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5770{
5771 return ValidateGenOrDelete(context, n);
5772}
5773
5774bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5775{
5776 return ValidateGenOrDelete(context, n);
5777}
5778
5779bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5780{
5781 return ValidateGenOrDelete(context, n);
5782}
5783
5784bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5785{
5786 return ValidateGenOrDelete(context, n);
5787}
5788
5789bool ValidateDisable(Context *context, GLenum cap)
5790{
5791 if (!ValidCap(context, cap, false))
5792 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 return false;
5795 }
5796
5797 return true;
5798}
5799
5800bool ValidateEnable(Context *context, GLenum cap)
5801{
5802 if (!ValidCap(context, cap, false))
5803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807
5808 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5809 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5810 {
5811 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005812 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005813
5814 // We also output an error message to the debugger window if tracing is active, so that
5815 // developers can see the error message.
5816 ERR() << errorMessage;
5817 return false;
5818 }
5819
5820 return true;
5821}
5822
5823bool ValidateFramebufferRenderbuffer(Context *context,
5824 GLenum target,
5825 GLenum attachment,
5826 GLenum renderbuffertarget,
5827 GLuint renderbuffer)
5828{
Brandon Jones6cad5662017-06-14 13:25:13 -07005829 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5832 return false;
5833 }
5834
5835 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5836 {
5837 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 return false;
5839 }
5840
5841 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5842 renderbuffertarget, renderbuffer);
5843}
5844
5845bool ValidateFramebufferTexture2D(Context *context,
5846 GLenum target,
5847 GLenum attachment,
5848 GLenum textarget,
5849 GLuint texture,
5850 GLint level)
5851{
5852 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5853 // extension
5854 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5855 level != 0)
5856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005857 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 return false;
5859 }
5860
5861 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5862 {
5863 return false;
5864 }
5865
5866 if (texture != 0)
5867 {
5868 gl::Texture *tex = context->getTexture(texture);
5869 ASSERT(tex);
5870
5871 const gl::Caps &caps = context->getCaps();
5872
5873 switch (textarget)
5874 {
5875 case GL_TEXTURE_2D:
5876 {
5877 if (level > gl::log2(caps.max2DTextureSize))
5878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005879 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005880 return false;
5881 }
5882 if (tex->getTarget() != GL_TEXTURE_2D)
5883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005885 return false;
5886 }
5887 }
5888 break;
5889
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005890 case GL_TEXTURE_RECTANGLE_ANGLE:
5891 {
5892 if (level != 0)
5893 {
5894 context->handleError(InvalidValue());
5895 return false;
5896 }
5897 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5898 {
5899 context->handleError(InvalidOperation()
5900 << "Textarget must match the texture target type.");
5901 return false;
5902 }
5903 }
5904 break;
5905
Jamie Madillbe849e42017-05-02 15:49:00 -04005906 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5907 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5908 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5909 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5910 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5911 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5912 {
5913 if (level > gl::log2(caps.maxCubeMapTextureSize))
5914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005915 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 return false;
5917 }
5918 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005920 context->handleError(InvalidOperation()
5921 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005922 return false;
5923 }
5924 }
5925 break;
5926
5927 case GL_TEXTURE_2D_MULTISAMPLE:
5928 {
5929 if (context->getClientVersion() < ES_3_1)
5930 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 return false;
5933 }
5934
5935 if (level != 0)
5936 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005937 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04005938 return false;
5939 }
5940 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005942 context->handleError(InvalidOperation()
5943 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005944 return false;
5945 }
5946 }
5947 break;
5948
5949 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005951 return false;
5952 }
5953
5954 const Format &format = tex->getFormat(textarget, level);
5955 if (format.info->compressed)
5956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005957 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005958 return false;
5959 }
5960 }
5961
5962 return true;
5963}
5964
5965bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5966{
5967 return ValidateGenOrDelete(context, n);
5968}
5969
5970bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5971{
5972 return ValidateGenOrDelete(context, n);
5973}
5974
5975bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5976{
5977 return ValidateGenOrDelete(context, n);
5978}
5979
5980bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5981{
5982 return ValidateGenOrDelete(context, n);
5983}
5984
5985bool ValidateGenerateMipmap(Context *context, GLenum target)
5986{
5987 if (!ValidTextureTarget(context, target))
5988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005989 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 return false;
5991 }
5992
5993 Texture *texture = context->getTargetTexture(target);
5994
5995 if (texture == nullptr)
5996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005998 return false;
5999 }
6000
6001 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6002
6003 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6004 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6005 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006007 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006008 return false;
6009 }
6010
6011 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
6012 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
6013 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
6014
Brandon Jones6cad5662017-06-14 13:25:13 -07006015 if (format.info->compressed)
6016 {
6017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6018 return false;
6019 }
6020
Jamie Madillbe849e42017-05-02 15:49:00 -04006021 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
Brandon Jones6cad5662017-06-14 13:25:13 -07006022 // unsized formats or that are color renderable and filterable. Since we do not track if
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 // the texture was created with sized or unsized format (only sized formats are stored),
6024 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
6025 // be able to) because they aren't color renderable. Simply do a special case for LUMA
6026 // textures since they're the only texture format that can be created with unsized formats
6027 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
6028 // was the last version to use add them.
6029 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
Brandon Jones6cad5662017-06-14 13:25:13 -07006030 (!formatCaps.renderable && !format.info->isLUMA()))
Jamie Madillbe849e42017-05-02 15:49:00 -04006031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006032 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006033 return false;
6034 }
6035
Geoff Lang65ac5b92017-05-01 13:16:30 -04006036 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
6037 bool supportsSRGBMipmapGeneration =
6038 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
6039 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006041 context->handleError(InvalidOperation()
6042 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006043 return false;
6044 }
6045
6046 // Non-power of 2 ES2 check
6047 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6048 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6049 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6050 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006051 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6052 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006054 return false;
6055 }
6056
6057 // Cube completeness check
6058 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006060 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 return false;
6062 }
6063
6064 return true;
6065}
6066
6067bool ValidateGetBufferParameteriv(ValidationContext *context,
6068 GLenum target,
6069 GLenum pname,
6070 GLint *params)
6071{
6072 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6073}
6074
6075bool ValidateGetRenderbufferParameteriv(Context *context,
6076 GLenum target,
6077 GLenum pname,
6078 GLint *params)
6079{
6080 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6081}
6082
6083bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6084{
6085 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6086}
6087
6088bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6089{
6090 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6091}
6092
6093bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6094{
6095 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6096}
6097
6098bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6099{
6100 return ValidateGetUniformBase(context, program, location);
6101}
6102
6103bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6104{
6105 return ValidateGetUniformBase(context, program, location);
6106}
6107
6108bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6109{
6110 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6111}
6112
6113bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6114{
6115 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6116}
6117
6118bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6119{
6120 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6121}
6122
6123bool ValidateIsEnabled(Context *context, GLenum cap)
6124{
6125 if (!ValidCap(context, cap, true))
6126 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006127 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006128 return false;
6129 }
6130
6131 return true;
6132}
6133
6134bool ValidateLinkProgram(Context *context, GLuint program)
6135{
6136 if (context->hasActiveTransformFeedback(program))
6137 {
6138 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006139 context->handleError(InvalidOperation() << "Cannot link program while program is "
6140 "associated with an active transform "
6141 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006142 return false;
6143 }
6144
6145 Program *programObject = GetValidProgram(context, program);
6146 if (!programObject)
6147 {
6148 return false;
6149 }
6150
6151 return true;
6152}
6153
Jamie Madill4928b7c2017-06-20 12:57:39 -04006154bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006155 GLint x,
6156 GLint y,
6157 GLsizei width,
6158 GLsizei height,
6159 GLenum format,
6160 GLenum type,
6161 void *pixels)
6162{
6163 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6164 nullptr, pixels);
6165}
6166
6167bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6168{
6169 return ValidateTexParameterBase(context, target, pname, -1, &param);
6170}
6171
6172bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6173{
6174 return ValidateTexParameterBase(context, target, pname, -1, params);
6175}
6176
6177bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6178{
6179 return ValidateTexParameterBase(context, target, pname, -1, &param);
6180}
6181
6182bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6183{
6184 return ValidateTexParameterBase(context, target, pname, -1, params);
6185}
6186
6187bool ValidateUseProgram(Context *context, GLuint program)
6188{
6189 if (program != 0)
6190 {
6191 Program *programObject = context->getProgram(program);
6192 if (!programObject)
6193 {
6194 // ES 3.1.0 section 7.3 page 72
6195 if (context->getShader(program))
6196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006198 return false;
6199 }
6200 else
6201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006202 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006203 return false;
6204 }
6205 }
6206 if (!programObject->isLinked())
6207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006209 return false;
6210 }
6211 }
6212 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6213 {
6214 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006215 context
6216 ->handleError(InvalidOperation()
6217 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006218 return false;
6219 }
6220
6221 return true;
6222}
6223
Jamie Madillc29968b2016-01-20 11:17:23 -05006224} // namespace gl