blob: 84cbc2a2c9fc16506baf9e24db5d7ec6b554ef25 [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
Geoff Langb433e872017-10-05 14:01:47 -0400791 case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
Jamie Madillbe849e42017-05-02 15:49:00 -0400792 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
Brandon Jonesed5b46f2017-07-21 08:39:17 -0700952bool ValidateWebGLNamePrefix(ValidationContext *context, const GLchar *name)
953{
954 ASSERT(context->isWebGL());
955
956 // WebGL 1.0 [Section 6.16] GLSL Constructs
957 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
958 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
959 {
960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), WebglBindAttribLocationReservedPrefix);
961 return false;
962 }
963
964 return true;
965}
966
967bool ValidateWebGLNameLength(ValidationContext *context, size_t length)
968{
969 ASSERT(context->isWebGL());
970
971 if (context->isWebGL1() && length > 256)
972 {
973 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
974 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
975 // locations.
976 ANGLE_VALIDATION_ERR(context, InvalidValue(), WebglNameLengthLimitExceeded);
977
978 return false;
979 }
980 else if (length > 1024)
981 {
982 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
983 // uniform and attribute locations.
984 ANGLE_VALIDATION_ERR(context, InvalidValue(), Webgl2NameLengthLimitExceeded);
985 return false;
986 }
987
988 return true;
989}
990
Jamie Madillc29968b2016-01-20 11:17:23 -0500991} // anonymous namespace
992
Geoff Langff5b2d52016-09-07 11:32:23 -0400993bool ValidateES2TexImageParameters(Context *context,
994 GLenum target,
995 GLint level,
996 GLenum internalformat,
997 bool isCompressed,
998 bool isSubImage,
999 GLint xoffset,
1000 GLint yoffset,
1001 GLsizei width,
1002 GLsizei height,
1003 GLint border,
1004 GLenum format,
1005 GLenum type,
1006 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001007 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008{
Jamie Madill6f38f822014-06-06 17:12:20 -04001009 if (!ValidTexture2DDestinationTarget(context, target))
1010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001011 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001013 }
1014
Austin Kinross08528e12015-10-07 16:24:40 -07001015 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
Brandon Jones6cad5662017-06-14 13:25:13 -07001021 if (!ValidMipLevel(context, target, level))
1022 {
1023 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
1024 return false;
1025 }
1026
1027 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 std::numeric_limits<GLsizei>::max() - yoffset < height)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04001031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 }
1033
Geoff Lang6e898aa2017-06-02 11:17:26 -04001034 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1035 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1036 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1037 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1038 // case.
1039 bool nonEqualFormatsAllowed =
1040 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
1041 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
1042
1043 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001045 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001046 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 }
1048
Geoff Langaae65a42014-05-26 12:43:44 -04001049 const gl::Caps &caps = context->getCaps();
1050
Geoff Langa9be0dc2014-12-17 12:34:40 -05001051 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001053 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
1054 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001056 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001059 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001060 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
1061 {
1062 ASSERT(level == 0);
1063 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1064 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
1065 {
1066 context->handleError(InvalidValue());
1067 return false;
1068 }
1069 if (isCompressed)
1070 {
1071 context->handleError(InvalidEnum()
1072 << "Rectangle texture cannot have a compressed format.");
1073 return false;
1074 }
1075 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001076 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001077 {
1078 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001080 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001081 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083
Geoff Langa9be0dc2014-12-17 12:34:40 -05001084 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1085 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001087 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001088 return false;
1089 }
1090 }
1091 else
1092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001093 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001094 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001095 }
1096
He Yunchaoced53ae2016-11-29 15:00:51 +08001097 gl::Texture *texture =
1098 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 if (!texture)
1100 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001101 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 }
1104
Geoff Langa9be0dc2014-12-17 12:34:40 -05001105 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 {
Geoff Langca271392017-04-05 12:30:00 -04001107 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1108 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001110 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001111 return false;
1112 }
1113
Geoff Langa9be0dc2014-12-17 12:34:40 -05001114 if (format != GL_NONE)
1115 {
Geoff Langca271392017-04-05 12:30:00 -04001116 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1117 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001118 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001120 return false;
1121 }
1122 }
1123
1124 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1125 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001127 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001128 return false;
1129 }
1130 }
1131 else
1132 {
Geoff Lang69cce582015-09-17 13:20:36 -04001133 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001135 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001136 return false;
1137 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 }
1139
1140 // Verify zero border
1141 if (border != 0)
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 }
1146
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 if (isCompressed)
1148 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001149 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001150 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1151 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001152 switch (actualInternalFormat)
1153 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001154 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1155 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1156 if (!context->getExtensions().textureCompressionDXT1)
1157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001159 return false;
1160 }
1161 break;
1162 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1163 if (!context->getExtensions().textureCompressionDXT1)
1164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001166 return false;
1167 }
1168 break;
1169 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1170 if (!context->getExtensions().textureCompressionDXT5)
1171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001173 return false;
1174 }
1175 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001176 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1177 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1178 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1179 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1180 if (!context->getExtensions().textureCompressionS3TCsRGB)
1181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001183 return false;
1184 }
1185 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001186 case GL_ETC1_RGB8_OES:
1187 if (!context->getExtensions().compressedETC1RGB8Texture)
1188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 return false;
1191 }
1192 break;
1193 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001194 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1195 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1196 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1197 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001198 if (!context->getExtensions().lossyETCDecode)
1199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001200 context->handleError(InvalidEnum()
1201 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 return false;
1203 }
1204 break;
1205 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001207 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001208 }
Geoff Lang966c9402017-04-18 12:38:27 -04001209
1210 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001211 {
Geoff Lang966c9402017-04-18 12:38:27 -04001212 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1213 height, texture->getWidth(target, level),
1214 texture->getHeight(target, level)))
1215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001216 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001217 return false;
1218 }
1219
1220 if (format != actualInternalFormat)
1221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001223 return false;
1224 }
1225 }
1226 else
1227 {
1228 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001231 return false;
1232 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001233 }
1234 }
1235 else
1236 {
1237 // validate <type> by itself (used as secondary key below)
1238 switch (type)
1239 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001240 case GL_UNSIGNED_BYTE:
1241 case GL_UNSIGNED_SHORT_5_6_5:
1242 case GL_UNSIGNED_SHORT_4_4_4_4:
1243 case GL_UNSIGNED_SHORT_5_5_5_1:
1244 case GL_UNSIGNED_SHORT:
1245 case GL_UNSIGNED_INT:
1246 case GL_UNSIGNED_INT_24_8_OES:
1247 case GL_HALF_FLOAT_OES:
1248 case GL_FLOAT:
1249 break;
1250 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001251 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001252 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 }
1254
1255 // validate <format> + <type> combinations
1256 // - invalid <format> -> sets INVALID_ENUM
1257 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1258 switch (format)
1259 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001260 case GL_ALPHA:
1261 case GL_LUMINANCE:
1262 case GL_LUMINANCE_ALPHA:
1263 switch (type)
1264 {
1265 case GL_UNSIGNED_BYTE:
1266 case GL_FLOAT:
1267 case GL_HALF_FLOAT_OES:
1268 break;
1269 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001271 return false;
1272 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001274 case GL_RED:
1275 case GL_RG:
1276 if (!context->getExtensions().textureRG)
1277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001278 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001279 return false;
1280 }
1281 switch (type)
1282 {
1283 case GL_UNSIGNED_BYTE:
1284 case GL_FLOAT:
1285 case GL_HALF_FLOAT_OES:
1286 break;
1287 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001289 return false;
1290 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001292 case GL_RGB:
1293 switch (type)
1294 {
1295 case GL_UNSIGNED_BYTE:
1296 case GL_UNSIGNED_SHORT_5_6_5:
1297 case GL_FLOAT:
1298 case GL_HALF_FLOAT_OES:
1299 break;
1300 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001302 return false;
1303 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001305 case GL_RGBA:
1306 switch (type)
1307 {
1308 case GL_UNSIGNED_BYTE:
1309 case GL_UNSIGNED_SHORT_4_4_4_4:
1310 case GL_UNSIGNED_SHORT_5_5_5_1:
1311 case GL_FLOAT:
1312 case GL_HALF_FLOAT_OES:
1313 break;
1314 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001315 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001316 return false;
1317 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001319 case GL_BGRA_EXT:
1320 switch (type)
1321 {
1322 case GL_UNSIGNED_BYTE:
1323 break;
1324 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001325 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 return false;
1327 }
1328 break;
1329 case GL_SRGB_EXT:
1330 case GL_SRGB_ALPHA_EXT:
1331 if (!context->getExtensions().sRGB)
1332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001333 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001334 return false;
1335 }
1336 switch (type)
1337 {
1338 case GL_UNSIGNED_BYTE:
1339 break;
1340 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001341 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 return false;
1343 }
1344 break;
1345 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1346 // handled below
1347 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1348 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1349 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1350 break;
1351 case GL_DEPTH_COMPONENT:
1352 switch (type)
1353 {
1354 case GL_UNSIGNED_SHORT:
1355 case GL_UNSIGNED_INT:
1356 break;
1357 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001358 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001359 return false;
1360 }
1361 break;
1362 case GL_DEPTH_STENCIL_OES:
1363 switch (type)
1364 {
1365 case GL_UNSIGNED_INT_24_8_OES:
1366 break;
1367 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001369 return false;
1370 }
1371 break;
1372 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 }
1376
1377 switch (format)
1378 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1380 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1381 if (context->getExtensions().textureCompressionDXT1)
1382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001384 return false;
1385 }
1386 else
1387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001388 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001389 return false;
1390 }
1391 break;
1392 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1393 if (context->getExtensions().textureCompressionDXT3)
1394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001396 return false;
1397 }
1398 else
1399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001400 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001401 return false;
1402 }
1403 break;
1404 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1405 if (context->getExtensions().textureCompressionDXT5)
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 return false;
1409 }
1410 else
1411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 return false;
1414 }
1415 break;
1416 case GL_ETC1_RGB8_OES:
1417 if (context->getExtensions().compressedETC1RGB8Texture)
1418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001420 return false;
1421 }
1422 else
1423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001424 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001425 return false;
1426 }
1427 break;
1428 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001429 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1430 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1431 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1432 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001433 if (context->getExtensions().lossyETCDecode)
1434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001435 context->handleError(InvalidOperation()
1436 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001437 return false;
1438 }
1439 else
1440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001441 context->handleError(InvalidEnum()
1442 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001443 return false;
1444 }
1445 break;
1446 case GL_DEPTH_COMPONENT:
1447 case GL_DEPTH_STENCIL_OES:
1448 if (!context->getExtensions().depthTextures)
1449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001450 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001451 return false;
1452 }
1453 if (target != GL_TEXTURE_2D)
1454 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001456 return false;
1457 }
1458 // OES_depth_texture supports loading depth data and multiple levels,
1459 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001460 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1463 return false;
1464 }
1465 if (level != 0)
1466 {
1467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001468 return false;
1469 }
1470 break;
1471 default:
1472 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 }
1474
Geoff Lang6e898aa2017-06-02 11:17:26 -04001475 if (!isSubImage)
1476 {
1477 switch (internalformat)
1478 {
1479 case GL_RGBA32F:
1480 if (!context->getExtensions().colorBufferFloatRGBA)
1481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001482 context->handleError(InvalidValue()
1483 << "Sized GL_RGBA32F internal format requires "
1484 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001485 return false;
1486 }
1487 if (type != GL_FLOAT)
1488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001489 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001490 return false;
1491 }
1492 if (format != GL_RGBA)
1493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001495 return false;
1496 }
1497 break;
1498
1499 case GL_RGB32F:
1500 if (!context->getExtensions().colorBufferFloatRGB)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidValue()
1503 << "Sized GL_RGB32F internal format requires "
1504 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001505 return false;
1506 }
1507 if (type != GL_FLOAT)
1508 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001509 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001510 return false;
1511 }
1512 if (format != GL_RGB)
1513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001515 return false;
1516 }
1517 break;
1518
1519 default:
1520 break;
1521 }
1522 }
1523
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524 if (type == GL_FLOAT)
1525 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001526 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001528 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001529 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001530 }
1531 }
1532 else if (type == GL_HALF_FLOAT_OES)
1533 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001534 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001536 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539 }
1540 }
1541
Geoff Langdbcced82017-06-06 15:55:54 -04001542 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1543 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001544 imageSize))
1545 {
1546 return false;
1547 }
1548
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001549 return true;
1550}
1551
He Yunchaoced53ae2016-11-29 15:00:51 +08001552bool ValidateES2TexStorageParameters(Context *context,
1553 GLenum target,
1554 GLsizei levels,
1555 GLenum internalformat,
1556 GLsizei width,
1557 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001558{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001559 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1560 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001562 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001563 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001564 }
1565
1566 if (width < 1 || height < 1 || levels < 1)
1567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001568 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001569 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001570 }
1571
1572 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001574 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001575 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001576 }
1577
1578 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001580 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001581 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001582 }
1583
Geoff Langca271392017-04-05 12:30:00 -04001584 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001585 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586 {
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 Langaae65a42014-05-26 12:43:44 -04001591 const gl::Caps &caps = context->getCaps();
1592
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001593 switch (target)
1594 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001595 case GL_TEXTURE_2D:
1596 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1597 static_cast<GLuint>(height) > caps.max2DTextureSize)
1598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001599 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001600 return false;
1601 }
1602 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001603 case GL_TEXTURE_RECTANGLE_ANGLE:
1604 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1605 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1606 {
1607 context->handleError(InvalidValue());
1608 return false;
1609 }
1610 if (formatInfo.compressed)
1611 {
1612 context->handleError(InvalidEnum()
1613 << "Rectangle texture cannot have a compressed format.");
1614 return false;
1615 }
1616 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001617 case GL_TEXTURE_CUBE_MAP:
1618 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1619 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001621 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001622 return false;
1623 }
1624 break;
1625 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001626 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001627 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001628 }
1629
Geoff Langc0b9ef42014-07-02 10:02:37 -04001630 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001631 {
1632 if (!gl::isPow2(width) || !gl::isPow2(height))
1633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001634 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001635 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001636 }
1637 }
1638
1639 switch (internalformat)
1640 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001641 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1642 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1643 if (!context->getExtensions().textureCompressionDXT1)
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001646 return false;
1647 }
1648 break;
1649 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1650 if (!context->getExtensions().textureCompressionDXT3)
1651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001652 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001653 return false;
1654 }
1655 break;
1656 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1657 if (!context->getExtensions().textureCompressionDXT5)
1658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001660 return false;
1661 }
1662 break;
1663 case GL_ETC1_RGB8_OES:
1664 if (!context->getExtensions().compressedETC1RGB8Texture)
1665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001666 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001667 return false;
1668 }
1669 break;
1670 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001671 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1672 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1673 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1674 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001675 if (!context->getExtensions().lossyETCDecode)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidEnum()
1678 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001679 return false;
1680 }
1681 break;
1682 case GL_RGBA32F_EXT:
1683 case GL_RGB32F_EXT:
1684 case GL_ALPHA32F_EXT:
1685 case GL_LUMINANCE32F_EXT:
1686 case GL_LUMINANCE_ALPHA32F_EXT:
1687 if (!context->getExtensions().textureFloat)
1688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001690 return false;
1691 }
1692 break;
1693 case GL_RGBA16F_EXT:
1694 case GL_RGB16F_EXT:
1695 case GL_ALPHA16F_EXT:
1696 case GL_LUMINANCE16F_EXT:
1697 case GL_LUMINANCE_ALPHA16F_EXT:
1698 if (!context->getExtensions().textureHalfFloat)
1699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001700 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001701 return false;
1702 }
1703 break;
1704 case GL_R8_EXT:
1705 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001706 if (!context->getExtensions().textureRG)
1707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001708 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001709 return false;
1710 }
1711 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001712 case GL_R16F_EXT:
1713 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001714 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001717 return false;
1718 }
1719 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001720 case GL_R32F_EXT:
1721 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001722 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001725 return false;
1726 }
1727 break;
1728 case GL_DEPTH_COMPONENT16:
1729 case GL_DEPTH_COMPONENT32_OES:
1730 case GL_DEPTH24_STENCIL8_OES:
1731 if (!context->getExtensions().depthTextures)
1732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001733 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001734 return false;
1735 }
1736 if (target != GL_TEXTURE_2D)
1737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001738 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001739 return false;
1740 }
1741 // ANGLE_depth_texture only supports 1-level textures
1742 if (levels != 1)
1743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001745 return false;
1746 }
1747 break;
1748 default:
1749 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 }
1751
Geoff Lang691e58c2014-12-19 17:03:25 -05001752 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 if (!texture || texture->id() == 0)
1754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001756 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 }
1758
Geoff Lang69cce582015-09-17 13:20:36 -04001759 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001762 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001763 }
1764
1765 return true;
1766}
1767
He Yunchaoced53ae2016-11-29 15:00:51 +08001768bool ValidateDiscardFramebufferEXT(Context *context,
1769 GLenum target,
1770 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001771 const GLenum *attachments)
1772{
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 if (!context->getExtensions().discardFramebuffer)
1774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001775 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001776 return false;
1777 }
1778
Austin Kinross08332632015-05-05 13:35:47 -07001779 bool defaultFramebuffer = false;
1780
1781 switch (target)
1782 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001783 case GL_FRAMEBUFFER:
1784 defaultFramebuffer =
1785 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1786 break;
1787 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001789 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001790 }
1791
He Yunchaoced53ae2016-11-29 15:00:51 +08001792 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1793 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001794}
1795
Austin Kinrossbc781f32015-10-26 09:27:38 -07001796bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1797{
1798 if (!context->getExtensions().vertexArrayObject)
1799 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001801 return false;
1802 }
1803
1804 return ValidateBindVertexArrayBase(context, array);
1805}
1806
Jamie Madilld7576732017-08-26 18:49:50 -04001807bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001808{
1809 if (!context->getExtensions().vertexArrayObject)
1810 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001811 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001812 return false;
1813 }
1814
Olli Etuaho41997e72016-03-10 13:38:39 +02001815 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001816}
1817
Jamie Madilld7576732017-08-26 18:49:50 -04001818bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001819{
1820 if (!context->getExtensions().vertexArrayObject)
1821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001823 return false;
1824 }
1825
Olli Etuaho41997e72016-03-10 13:38:39 +02001826 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001827}
1828
Jamie Madilld7576732017-08-26 18:49:50 -04001829bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001830{
1831 if (!context->getExtensions().vertexArrayObject)
1832 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001834 return false;
1835 }
1836
1837 return true;
1838}
Geoff Langc5629752015-12-07 16:29:04 -05001839
1840bool ValidateProgramBinaryOES(Context *context,
1841 GLuint program,
1842 GLenum binaryFormat,
1843 const void *binary,
1844 GLint length)
1845{
1846 if (!context->getExtensions().getProgramBinary)
1847 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001849 return false;
1850 }
1851
1852 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1853}
1854
1855bool ValidateGetProgramBinaryOES(Context *context,
1856 GLuint program,
1857 GLsizei bufSize,
1858 GLsizei *length,
1859 GLenum *binaryFormat,
1860 void *binary)
1861{
1862 if (!context->getExtensions().getProgramBinary)
1863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001865 return false;
1866 }
1867
1868 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1869}
Geoff Lange102fee2015-12-10 11:23:30 -05001870
Geoff Lang70d0f492015-12-10 17:45:46 -05001871static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1872{
1873 switch (source)
1874 {
1875 case GL_DEBUG_SOURCE_API:
1876 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1877 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1878 case GL_DEBUG_SOURCE_OTHER:
1879 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1880 return !mustBeThirdPartyOrApplication;
1881
1882 case GL_DEBUG_SOURCE_THIRD_PARTY:
1883 case GL_DEBUG_SOURCE_APPLICATION:
1884 return true;
1885
1886 default:
1887 return false;
1888 }
1889}
1890
1891static bool ValidDebugType(GLenum type)
1892{
1893 switch (type)
1894 {
1895 case GL_DEBUG_TYPE_ERROR:
1896 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1897 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1898 case GL_DEBUG_TYPE_PERFORMANCE:
1899 case GL_DEBUG_TYPE_PORTABILITY:
1900 case GL_DEBUG_TYPE_OTHER:
1901 case GL_DEBUG_TYPE_MARKER:
1902 case GL_DEBUG_TYPE_PUSH_GROUP:
1903 case GL_DEBUG_TYPE_POP_GROUP:
1904 return true;
1905
1906 default:
1907 return false;
1908 }
1909}
1910
1911static bool ValidDebugSeverity(GLenum severity)
1912{
1913 switch (severity)
1914 {
1915 case GL_DEBUG_SEVERITY_HIGH:
1916 case GL_DEBUG_SEVERITY_MEDIUM:
1917 case GL_DEBUG_SEVERITY_LOW:
1918 case GL_DEBUG_SEVERITY_NOTIFICATION:
1919 return true;
1920
1921 default:
1922 return false;
1923 }
1924}
1925
Geoff Lange102fee2015-12-10 11:23:30 -05001926bool ValidateDebugMessageControlKHR(Context *context,
1927 GLenum source,
1928 GLenum type,
1929 GLenum severity,
1930 GLsizei count,
1931 const GLuint *ids,
1932 GLboolean enabled)
1933{
1934 if (!context->getExtensions().debug)
1935 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001937 return false;
1938 }
1939
Geoff Lang70d0f492015-12-10 17:45:46 -05001940 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1941 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001943 return false;
1944 }
1945
1946 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1947 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001949 return false;
1950 }
1951
1952 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1953 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001954 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001955 return false;
1956 }
1957
1958 if (count > 0)
1959 {
1960 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001962 context->handleError(
1963 InvalidOperation()
1964 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001965 return false;
1966 }
1967
1968 if (severity != GL_DONT_CARE)
1969 {
Jamie Madill437fa652016-05-03 15:13:24 -04001970 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001971 InvalidOperation()
1972 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001973 return false;
1974 }
1975 }
1976
Geoff Lange102fee2015-12-10 11:23:30 -05001977 return true;
1978}
1979
1980bool ValidateDebugMessageInsertKHR(Context *context,
1981 GLenum source,
1982 GLenum type,
1983 GLuint id,
1984 GLenum severity,
1985 GLsizei length,
1986 const GLchar *buf)
1987{
1988 if (!context->getExtensions().debug)
1989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001991 return false;
1992 }
1993
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001994 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001995 {
1996 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1997 // not generate an error.
1998 return false;
1999 }
2000
2001 if (!ValidDebugSeverity(severity))
2002 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002003 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002004 return false;
2005 }
2006
2007 if (!ValidDebugType(type))
2008 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002009 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05002010 return false;
2011 }
2012
2013 if (!ValidDebugSource(source, true))
2014 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002016 return false;
2017 }
2018
2019 size_t messageLength = (length < 0) ? strlen(buf) : length;
2020 if (messageLength > context->getExtensions().maxDebugMessageLength)
2021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002022 context->handleError(InvalidValue()
2023 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002024 return false;
2025 }
2026
Geoff Lange102fee2015-12-10 11:23:30 -05002027 return true;
2028}
2029
2030bool ValidateDebugMessageCallbackKHR(Context *context,
2031 GLDEBUGPROCKHR callback,
2032 const void *userParam)
2033{
2034 if (!context->getExtensions().debug)
2035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002037 return false;
2038 }
2039
Geoff Lange102fee2015-12-10 11:23:30 -05002040 return true;
2041}
2042
2043bool ValidateGetDebugMessageLogKHR(Context *context,
2044 GLuint count,
2045 GLsizei bufSize,
2046 GLenum *sources,
2047 GLenum *types,
2048 GLuint *ids,
2049 GLenum *severities,
2050 GLsizei *lengths,
2051 GLchar *messageLog)
2052{
2053 if (!context->getExtensions().debug)
2054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002056 return false;
2057 }
2058
Geoff Lang70d0f492015-12-10 17:45:46 -05002059 if (bufSize < 0 && messageLog != nullptr)
2060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002061 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002062 return false;
2063 }
2064
Geoff Lange102fee2015-12-10 11:23:30 -05002065 return true;
2066}
2067
2068bool ValidatePushDebugGroupKHR(Context *context,
2069 GLenum source,
2070 GLuint id,
2071 GLsizei length,
2072 const GLchar *message)
2073{
2074 if (!context->getExtensions().debug)
2075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002077 return false;
2078 }
2079
Geoff Lang70d0f492015-12-10 17:45:46 -05002080 if (!ValidDebugSource(source, true))
2081 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002082 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002083 return false;
2084 }
2085
2086 size_t messageLength = (length < 0) ? strlen(message) : length;
2087 if (messageLength > context->getExtensions().maxDebugMessageLength)
2088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002089 context->handleError(InvalidValue()
2090 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002091 return false;
2092 }
2093
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002094 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002095 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002097 context
2098 ->handleError(StackOverflow()
2099 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002100 return false;
2101 }
2102
Geoff Lange102fee2015-12-10 11:23:30 -05002103 return true;
2104}
2105
2106bool ValidatePopDebugGroupKHR(Context *context)
2107{
2108 if (!context->getExtensions().debug)
2109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002111 return false;
2112 }
2113
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002114 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002115 if (currentStackSize <= 1)
2116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002117 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002118 return false;
2119 }
2120
2121 return true;
2122}
2123
2124static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2125{
2126 switch (identifier)
2127 {
2128 case GL_BUFFER:
2129 if (context->getBuffer(name) == nullptr)
2130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002131 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002132 return false;
2133 }
2134 return true;
2135
2136 case GL_SHADER:
2137 if (context->getShader(name) == nullptr)
2138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002139 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002140 return false;
2141 }
2142 return true;
2143
2144 case GL_PROGRAM:
2145 if (context->getProgram(name) == nullptr)
2146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002147 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002148 return false;
2149 }
2150 return true;
2151
2152 case GL_VERTEX_ARRAY:
2153 if (context->getVertexArray(name) == nullptr)
2154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002156 return false;
2157 }
2158 return true;
2159
2160 case GL_QUERY:
2161 if (context->getQuery(name) == nullptr)
2162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002163 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002164 return false;
2165 }
2166 return true;
2167
2168 case GL_TRANSFORM_FEEDBACK:
2169 if (context->getTransformFeedback(name) == nullptr)
2170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002171 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002172 return false;
2173 }
2174 return true;
2175
2176 case GL_SAMPLER:
2177 if (context->getSampler(name) == nullptr)
2178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002180 return false;
2181 }
2182 return true;
2183
2184 case GL_TEXTURE:
2185 if (context->getTexture(name) == nullptr)
2186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002187 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002188 return false;
2189 }
2190 return true;
2191
2192 case GL_RENDERBUFFER:
2193 if (context->getRenderbuffer(name) == nullptr)
2194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002196 return false;
2197 }
2198 return true;
2199
2200 case GL_FRAMEBUFFER:
2201 if (context->getFramebuffer(name) == nullptr)
2202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002203 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002204 return false;
2205 }
2206 return true;
2207
2208 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002210 return false;
2211 }
Geoff Lange102fee2015-12-10 11:23:30 -05002212}
2213
Martin Radev9d901792016-07-15 15:58:58 +03002214static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2215{
2216 size_t labelLength = 0;
2217
2218 if (length < 0)
2219 {
2220 if (label != nullptr)
2221 {
2222 labelLength = strlen(label);
2223 }
2224 }
2225 else
2226 {
2227 labelLength = static_cast<size_t>(length);
2228 }
2229
2230 if (labelLength > context->getExtensions().maxLabelLength)
2231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002232 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002233 return false;
2234 }
2235
2236 return true;
2237}
2238
Geoff Lange102fee2015-12-10 11:23:30 -05002239bool ValidateObjectLabelKHR(Context *context,
2240 GLenum identifier,
2241 GLuint name,
2242 GLsizei length,
2243 const GLchar *label)
2244{
2245 if (!context->getExtensions().debug)
2246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002248 return false;
2249 }
2250
Geoff Lang70d0f492015-12-10 17:45:46 -05002251 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2252 {
2253 return false;
2254 }
2255
Martin Radev9d901792016-07-15 15:58:58 +03002256 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002257 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002258 return false;
2259 }
2260
Geoff Lange102fee2015-12-10 11:23:30 -05002261 return true;
2262}
2263
2264bool ValidateGetObjectLabelKHR(Context *context,
2265 GLenum identifier,
2266 GLuint name,
2267 GLsizei bufSize,
2268 GLsizei *length,
2269 GLchar *label)
2270{
2271 if (!context->getExtensions().debug)
2272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002274 return false;
2275 }
2276
Geoff Lang70d0f492015-12-10 17:45:46 -05002277 if (bufSize < 0)
2278 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002279 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002280 return false;
2281 }
2282
2283 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2284 {
2285 return false;
2286 }
2287
Martin Radev9d901792016-07-15 15:58:58 +03002288 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002289}
2290
2291static bool ValidateObjectPtrName(Context *context, const void *ptr)
2292{
Jamie Madill70b5bb02017-08-28 13:32:37 -04002293 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
Geoff Lang70d0f492015-12-10 17:45:46 -05002294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002295 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002296 return false;
2297 }
2298
Geoff Lange102fee2015-12-10 11:23:30 -05002299 return true;
2300}
2301
2302bool ValidateObjectPtrLabelKHR(Context *context,
2303 const void *ptr,
2304 GLsizei length,
2305 const GLchar *label)
2306{
2307 if (!context->getExtensions().debug)
2308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002310 return false;
2311 }
2312
Geoff Lang70d0f492015-12-10 17:45:46 -05002313 if (!ValidateObjectPtrName(context, ptr))
2314 {
2315 return false;
2316 }
2317
Martin Radev9d901792016-07-15 15:58:58 +03002318 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002319 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002320 return false;
2321 }
2322
Geoff Lange102fee2015-12-10 11:23:30 -05002323 return true;
2324}
2325
2326bool ValidateGetObjectPtrLabelKHR(Context *context,
2327 const void *ptr,
2328 GLsizei bufSize,
2329 GLsizei *length,
2330 GLchar *label)
2331{
2332 if (!context->getExtensions().debug)
2333 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002335 return false;
2336 }
2337
Geoff Lang70d0f492015-12-10 17:45:46 -05002338 if (bufSize < 0)
2339 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002340 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002341 return false;
2342 }
2343
2344 if (!ValidateObjectPtrName(context, ptr))
2345 {
2346 return false;
2347 }
2348
Martin Radev9d901792016-07-15 15:58:58 +03002349 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002350}
2351
2352bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2353{
2354 if (!context->getExtensions().debug)
2355 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002357 return false;
2358 }
2359
Geoff Lang70d0f492015-12-10 17:45:46 -05002360 // TODO: represent this in Context::getQueryParameterInfo.
2361 switch (pname)
2362 {
2363 case GL_DEBUG_CALLBACK_FUNCTION:
2364 case GL_DEBUG_CALLBACK_USER_PARAM:
2365 break;
2366
2367 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002368 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002369 return false;
2370 }
2371
Geoff Lange102fee2015-12-10 11:23:30 -05002372 return true;
2373}
Jamie Madillc29968b2016-01-20 11:17:23 -05002374
2375bool ValidateBlitFramebufferANGLE(Context *context,
2376 GLint srcX0,
2377 GLint srcY0,
2378 GLint srcX1,
2379 GLint srcY1,
2380 GLint dstX0,
2381 GLint dstY0,
2382 GLint dstX1,
2383 GLint dstY1,
2384 GLbitfield mask,
2385 GLenum filter)
2386{
2387 if (!context->getExtensions().framebufferBlit)
2388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002389 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002390 return false;
2391 }
2392
2393 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2394 {
2395 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidOperation() << "Scaling and flipping in "
2397 "BlitFramebufferANGLE not supported by this "
2398 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002399 return false;
2400 }
2401
2402 if (filter == GL_LINEAR)
2403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002404 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002405 return false;
2406 }
2407
Jamie Madill51f40ec2016-06-15 14:06:00 -04002408 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2409 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002410
2411 if (mask & GL_COLOR_BUFFER_BIT)
2412 {
2413 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2414 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2415
2416 if (readColorAttachment && drawColorAttachment)
2417 {
2418 if (!(readColorAttachment->type() == GL_TEXTURE &&
2419 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2420 readColorAttachment->type() != GL_RENDERBUFFER &&
2421 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002423 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002424 return false;
2425 }
2426
Geoff Langa15472a2015-08-11 11:48:03 -04002427 for (size_t drawbufferIdx = 0;
2428 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002429 {
Geoff Langa15472a2015-08-11 11:48:03 -04002430 const FramebufferAttachment *attachment =
2431 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2432 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002433 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002434 if (!(attachment->type() == GL_TEXTURE &&
2435 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2436 attachment->type() != GL_RENDERBUFFER &&
2437 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002439 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002440 return false;
2441 }
2442
2443 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002444 if (!Format::EquivalentForBlit(attachment->getFormat(),
2445 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002447 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002448 return false;
2449 }
2450 }
2451 }
2452
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002453 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002454 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2455 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002457 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002458 return false;
2459 }
2460 }
2461 }
2462
2463 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2464 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2465 for (size_t i = 0; i < 2; i++)
2466 {
2467 if (mask & masks[i])
2468 {
2469 const FramebufferAttachment *readBuffer =
2470 readFramebuffer->getAttachment(attachments[i]);
2471 const FramebufferAttachment *drawBuffer =
2472 drawFramebuffer->getAttachment(attachments[i]);
2473
2474 if (readBuffer && drawBuffer)
2475 {
2476 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2477 dstX0, dstY0, dstX1, dstY1))
2478 {
2479 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002480 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2481 "stencil blits are supported by "
2482 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002483 return false;
2484 }
2485
2486 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002489 return false;
2490 }
2491 }
2492 }
2493 }
2494
2495 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2496 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002497}
Jamie Madillc29968b2016-01-20 11:17:23 -05002498
2499bool ValidateClear(ValidationContext *context, GLbitfield mask)
2500{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002501 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002502 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002505 return false;
2506 }
2507
2508 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2509 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002510 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002511 return false;
2512 }
2513
Geoff Lang76e65652017-03-27 14:58:02 -04002514 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2515 {
2516 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2517 GL_SIGNED_NORMALIZED};
2518
Corentin Wallez59c41592017-07-11 13:19:54 -04002519 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002520 drawBufferIdx++)
2521 {
2522 if (!ValidateWebGLFramebufferAttachmentClearType(
2523 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2524 {
2525 return false;
2526 }
2527 }
2528 }
2529
Jamie Madillc29968b2016-01-20 11:17:23 -05002530 return true;
2531}
2532
2533bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2534{
2535 if (!context->getExtensions().drawBuffers)
2536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002537 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002538 return false;
2539 }
2540
2541 return ValidateDrawBuffersBase(context, n, bufs);
2542}
2543
Jamie Madill73a84962016-02-12 09:27:23 -05002544bool ValidateTexImage2D(Context *context,
2545 GLenum target,
2546 GLint level,
2547 GLint internalformat,
2548 GLsizei width,
2549 GLsizei height,
2550 GLint border,
2551 GLenum format,
2552 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002553 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002554{
Martin Radev1be913c2016-07-11 17:59:16 +03002555 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002556 {
2557 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002558 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002559 }
2560
Martin Radev1be913c2016-07-11 17:59:16 +03002561 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002562 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002563 0, 0, width, height, 1, border, format, type, -1,
2564 pixels);
2565}
2566
2567bool ValidateTexImage2DRobust(Context *context,
2568 GLenum target,
2569 GLint level,
2570 GLint internalformat,
2571 GLsizei width,
2572 GLsizei height,
2573 GLint border,
2574 GLenum format,
2575 GLenum type,
2576 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002577 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002578{
2579 if (!ValidateRobustEntryPoint(context, bufSize))
2580 {
2581 return false;
2582 }
2583
2584 if (context->getClientMajorVersion() < 3)
2585 {
2586 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2587 0, 0, width, height, border, format, type, bufSize,
2588 pixels);
2589 }
2590
2591 ASSERT(context->getClientMajorVersion() >= 3);
2592 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2593 0, 0, width, height, 1, border, format, type, bufSize,
2594 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002595}
2596
2597bool ValidateTexSubImage2D(Context *context,
2598 GLenum target,
2599 GLint level,
2600 GLint xoffset,
2601 GLint yoffset,
2602 GLsizei width,
2603 GLsizei height,
2604 GLenum format,
2605 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002606 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002607{
2608
Martin Radev1be913c2016-07-11 17:59:16 +03002609 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002610 {
2611 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002612 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002613 }
2614
Martin Radev1be913c2016-07-11 17:59:16 +03002615 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002616 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002617 yoffset, 0, width, height, 1, 0, format, type, -1,
2618 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002619}
2620
Geoff Langc52f6f12016-10-14 10:18:00 -04002621bool ValidateTexSubImage2DRobustANGLE(Context *context,
2622 GLenum target,
2623 GLint level,
2624 GLint xoffset,
2625 GLint yoffset,
2626 GLsizei width,
2627 GLsizei height,
2628 GLenum format,
2629 GLenum type,
2630 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002631 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002632{
2633 if (!ValidateRobustEntryPoint(context, bufSize))
2634 {
2635 return false;
2636 }
2637
2638 if (context->getClientMajorVersion() < 3)
2639 {
2640 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2641 yoffset, width, height, 0, format, type, bufSize,
2642 pixels);
2643 }
2644
2645 ASSERT(context->getClientMajorVersion() >= 3);
2646 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2647 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2648 pixels);
2649}
2650
Jamie Madill73a84962016-02-12 09:27:23 -05002651bool ValidateCompressedTexImage2D(Context *context,
2652 GLenum target,
2653 GLint level,
2654 GLenum internalformat,
2655 GLsizei width,
2656 GLsizei height,
2657 GLint border,
2658 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002659 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002660{
Martin Radev1be913c2016-07-11 17:59:16 +03002661 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002662 {
2663 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002664 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002665 {
2666 return false;
2667 }
2668 }
2669 else
2670 {
Martin Radev1be913c2016-07-11 17:59:16 +03002671 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002672 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002673 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002674 data))
2675 {
2676 return false;
2677 }
2678 }
2679
Geoff Langca271392017-04-05 12:30:00 -04002680 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002681 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002682 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002683 if (blockSizeOrErr.isError())
2684 {
2685 context->handleError(blockSizeOrErr.getError());
2686 return false;
2687 }
2688
2689 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002691 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002692 return false;
2693 }
2694
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002695 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2696 {
2697 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2698 return false;
2699 }
2700
Jamie Madill73a84962016-02-12 09:27:23 -05002701 return true;
2702}
2703
Corentin Wallezb2931602017-04-11 15:58:57 -04002704bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2705 GLenum target,
2706 GLint level,
2707 GLenum internalformat,
2708 GLsizei width,
2709 GLsizei height,
2710 GLint border,
2711 GLsizei imageSize,
2712 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002713 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002714{
2715 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2716 {
2717 return false;
2718 }
2719
2720 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2721 border, imageSize, data);
2722}
2723bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2724 GLenum target,
2725 GLint level,
2726 GLint xoffset,
2727 GLint yoffset,
2728 GLsizei width,
2729 GLsizei height,
2730 GLenum format,
2731 GLsizei imageSize,
2732 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002733 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002734{
2735 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2736 {
2737 return false;
2738 }
2739
2740 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2741 format, imageSize, data);
2742}
2743
Jamie Madill73a84962016-02-12 09:27:23 -05002744bool ValidateCompressedTexSubImage2D(Context *context,
2745 GLenum target,
2746 GLint level,
2747 GLint xoffset,
2748 GLint yoffset,
2749 GLsizei width,
2750 GLsizei height,
2751 GLenum format,
2752 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002753 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002754{
Martin Radev1be913c2016-07-11 17:59:16 +03002755 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002756 {
2757 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002758 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002759 {
2760 return false;
2761 }
2762 }
2763 else
2764 {
Martin Radev1be913c2016-07-11 17:59:16 +03002765 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002766 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002767 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002768 data))
2769 {
2770 return false;
2771 }
2772 }
2773
Geoff Langca271392017-04-05 12:30:00 -04002774 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002775 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002776 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002777 if (blockSizeOrErr.isError())
2778 {
2779 context->handleError(blockSizeOrErr.getError());
2780 return false;
2781 }
2782
2783 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002785 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002786 return false;
2787 }
2788
2789 return true;
2790}
2791
Olli Etuaho4f667482016-03-30 15:56:35 +03002792bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2793{
Geoff Lang496c02d2016-10-20 11:38:11 -07002794 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002795}
2796
2797bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2798{
2799 if (!context->getExtensions().mapBuffer)
2800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002801 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002802 return false;
2803 }
2804
2805 if (!ValidBufferTarget(context, target))
2806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002807 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002808 return false;
2809 }
2810
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002811 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002812
2813 if (buffer == nullptr)
2814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002815 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002816 return false;
2817 }
2818
2819 if (access != GL_WRITE_ONLY_OES)
2820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002821 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002822 return false;
2823 }
2824
2825 if (buffer->isMapped())
2826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002827 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002828 return false;
2829 }
2830
Geoff Lang79f71042017-08-14 16:43:43 -04002831 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002832}
2833
2834bool ValidateUnmapBufferOES(Context *context, GLenum target)
2835{
2836 if (!context->getExtensions().mapBuffer)
2837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002838 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002839 return false;
2840 }
2841
2842 return ValidateUnmapBufferBase(context, target);
2843}
2844
2845bool ValidateMapBufferRangeEXT(Context *context,
2846 GLenum target,
2847 GLintptr offset,
2848 GLsizeiptr length,
2849 GLbitfield access)
2850{
2851 if (!context->getExtensions().mapBufferRange)
2852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002853 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002854 return false;
2855 }
2856
2857 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2858}
2859
Geoff Lang79f71042017-08-14 16:43:43 -04002860bool ValidateMapBufferBase(Context *context, GLenum target)
2861{
2862 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2863 ASSERT(buffer != nullptr);
2864
2865 // Check if this buffer is currently being used as a transform feedback output buffer
2866 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2867 if (transformFeedback != nullptr && transformFeedback->isActive())
2868 {
2869 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2870 {
2871 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2872 if (transformFeedbackBuffer.get() == buffer)
2873 {
2874 context->handleError(InvalidOperation()
2875 << "Buffer is currently bound for transform feedback.");
2876 return false;
2877 }
2878 }
2879 }
2880
2881 return true;
2882}
2883
Olli Etuaho4f667482016-03-30 15:56:35 +03002884bool ValidateFlushMappedBufferRangeEXT(Context *context,
2885 GLenum target,
2886 GLintptr offset,
2887 GLsizeiptr length)
2888{
2889 if (!context->getExtensions().mapBufferRange)
2890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002891 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002892 return false;
2893 }
2894
2895 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2896}
2897
Ian Ewell54f87462016-03-10 13:47:21 -05002898bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2899{
2900 Texture *textureObject = context->getTexture(texture);
2901 if (textureObject && textureObject->getTarget() != target && texture != 0)
2902 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002904 return false;
2905 }
2906
Geoff Langf41a7152016-09-19 15:11:17 -04002907 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2908 !context->isTextureGenerated(texture))
2909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002910 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002911 return false;
2912 }
2913
Ian Ewell54f87462016-03-10 13:47:21 -05002914 switch (target)
2915 {
2916 case GL_TEXTURE_2D:
2917 case GL_TEXTURE_CUBE_MAP:
2918 break;
2919
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002920 case GL_TEXTURE_RECTANGLE_ANGLE:
2921 if (!context->getExtensions().textureRectangle)
2922 {
2923 context->handleError(InvalidEnum()
2924 << "Context does not support GL_ANGLE_texture_rectangle");
2925 return false;
2926 }
2927 break;
2928
Ian Ewell54f87462016-03-10 13:47:21 -05002929 case GL_TEXTURE_3D:
2930 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002931 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002932 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002933 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002934 return false;
2935 }
2936 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002937
2938 case GL_TEXTURE_2D_MULTISAMPLE:
2939 if (context->getClientVersion() < Version(3, 1))
2940 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002942 return false;
2943 }
Geoff Lang3b573612016-10-31 14:08:10 -04002944 break;
2945
Ian Ewell54f87462016-03-10 13:47:21 -05002946 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002947 if (!context->getExtensions().eglImageExternal &&
2948 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002950 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002951 return false;
2952 }
2953 break;
2954 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002956 return false;
2957 }
2958
2959 return true;
2960}
2961
Geoff Langd8605522016-04-13 10:19:12 -04002962bool ValidateBindUniformLocationCHROMIUM(Context *context,
2963 GLuint program,
2964 GLint location,
2965 const GLchar *name)
2966{
2967 if (!context->getExtensions().bindUniformLocation)
2968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002969 context->handleError(InvalidOperation()
2970 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002971 return false;
2972 }
2973
2974 Program *programObject = GetValidProgram(context, program);
2975 if (!programObject)
2976 {
2977 return false;
2978 }
2979
2980 if (location < 0)
2981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002982 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002983 return false;
2984 }
2985
2986 const Caps &caps = context->getCaps();
2987 if (static_cast<size_t>(location) >=
2988 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002990 context->handleError(InvalidValue() << "Location must be less than "
2991 "(MAX_VERTEX_UNIFORM_VECTORS + "
2992 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002993 return false;
2994 }
2995
Geoff Langfc32e8b2017-05-31 14:16:59 -04002996 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2997 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04002998 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003000 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04003001 return false;
3002 }
3003
Geoff Langd8605522016-04-13 10:19:12 -04003004 if (strncmp(name, "gl_", 3) == 0)
3005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003006 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04003007 return false;
3008 }
3009
3010 return true;
3011}
3012
Jamie Madille2e406c2016-06-02 13:04:10 -04003013bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03003014{
3015 if (!context->getExtensions().framebufferMixedSamples)
3016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003017 context->handleError(InvalidOperation()
3018 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03003019 return false;
3020 }
3021 switch (components)
3022 {
3023 case GL_RGB:
3024 case GL_RGBA:
3025 case GL_ALPHA:
3026 case GL_NONE:
3027 break;
3028 default:
3029 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003030 InvalidEnum()
3031 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03003032 return false;
3033 }
3034
3035 return true;
3036}
3037
Sami Väisänene45e53b2016-05-25 10:36:04 +03003038// CHROMIUM_path_rendering
3039
3040bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3041{
3042 if (!context->getExtensions().pathRendering)
3043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003044 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003045 return false;
3046 }
3047 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3048 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003049 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003050 return false;
3051 }
3052 if (matrix == nullptr)
3053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003054 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003055 return false;
3056 }
3057 return true;
3058}
3059
3060bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3061{
3062 if (!context->getExtensions().pathRendering)
3063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003064 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003065 return false;
3066 }
3067 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3068 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003069 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003070 return false;
3071 }
3072 return true;
3073}
3074
3075bool ValidateGenPaths(Context *context, GLsizei range)
3076{
3077 if (!context->getExtensions().pathRendering)
3078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003079 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003080 return false;
3081 }
3082
3083 // range = 0 is undefined in NV_path_rendering.
3084 // we add stricter semantic check here and require a non zero positive range.
3085 if (range <= 0)
3086 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003087 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003088 return false;
3089 }
3090
3091 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003094 return false;
3095 }
3096
3097 return true;
3098}
3099
3100bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3101{
3102 if (!context->getExtensions().pathRendering)
3103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003104 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003105 return false;
3106 }
3107
3108 // range = 0 is undefined in NV_path_rendering.
3109 // we add stricter semantic check here and require a non zero positive range.
3110 if (range <= 0)
3111 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003112 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003113 return false;
3114 }
3115
3116 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3117 checkedRange += range;
3118
3119 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003122 return false;
3123 }
3124 return true;
3125}
3126
3127bool ValidatePathCommands(Context *context,
3128 GLuint path,
3129 GLsizei numCommands,
3130 const GLubyte *commands,
3131 GLsizei numCoords,
3132 GLenum coordType,
3133 const void *coords)
3134{
3135 if (!context->getExtensions().pathRendering)
3136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003137 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003138 return false;
3139 }
3140 if (!context->hasPath(path))
3141 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003143 return false;
3144 }
3145
3146 if (numCommands < 0)
3147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003148 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003149 return false;
3150 }
3151 else if (numCommands > 0)
3152 {
3153 if (!commands)
3154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003155 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003156 return false;
3157 }
3158 }
3159
3160 if (numCoords < 0)
3161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003162 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003163 return false;
3164 }
3165 else if (numCoords > 0)
3166 {
3167 if (!coords)
3168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003169 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003170 return false;
3171 }
3172 }
3173
3174 std::uint32_t coordTypeSize = 0;
3175 switch (coordType)
3176 {
3177 case GL_BYTE:
3178 coordTypeSize = sizeof(GLbyte);
3179 break;
3180
3181 case GL_UNSIGNED_BYTE:
3182 coordTypeSize = sizeof(GLubyte);
3183 break;
3184
3185 case GL_SHORT:
3186 coordTypeSize = sizeof(GLshort);
3187 break;
3188
3189 case GL_UNSIGNED_SHORT:
3190 coordTypeSize = sizeof(GLushort);
3191 break;
3192
3193 case GL_FLOAT:
3194 coordTypeSize = sizeof(GLfloat);
3195 break;
3196
3197 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003198 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003199 return false;
3200 }
3201
3202 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3203 checkedSize += (coordTypeSize * numCoords);
3204 if (!checkedSize.IsValid())
3205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003207 return false;
3208 }
3209
3210 // early return skips command data validation when it doesn't exist.
3211 if (!commands)
3212 return true;
3213
3214 GLsizei expectedNumCoords = 0;
3215 for (GLsizei i = 0; i < numCommands; ++i)
3216 {
3217 switch (commands[i])
3218 {
3219 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3220 break;
3221 case GL_MOVE_TO_CHROMIUM:
3222 case GL_LINE_TO_CHROMIUM:
3223 expectedNumCoords += 2;
3224 break;
3225 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3226 expectedNumCoords += 4;
3227 break;
3228 case GL_CUBIC_CURVE_TO_CHROMIUM:
3229 expectedNumCoords += 6;
3230 break;
3231 case GL_CONIC_CURVE_TO_CHROMIUM:
3232 expectedNumCoords += 5;
3233 break;
3234 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003235 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003236 return false;
3237 }
3238 }
3239 if (expectedNumCoords != numCoords)
3240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003241 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003242 return false;
3243 }
3244
3245 return true;
3246}
3247
3248bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3249{
3250 if (!context->getExtensions().pathRendering)
3251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003253 return false;
3254 }
3255 if (!context->hasPath(path))
3256 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003258 return false;
3259 }
3260
3261 switch (pname)
3262 {
3263 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3264 if (value < 0.0f)
3265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003266 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003267 return false;
3268 }
3269 break;
3270 case GL_PATH_END_CAPS_CHROMIUM:
3271 switch (static_cast<GLenum>(value))
3272 {
3273 case GL_FLAT_CHROMIUM:
3274 case GL_SQUARE_CHROMIUM:
3275 case GL_ROUND_CHROMIUM:
3276 break;
3277 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003278 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003279 return false;
3280 }
3281 break;
3282 case GL_PATH_JOIN_STYLE_CHROMIUM:
3283 switch (static_cast<GLenum>(value))
3284 {
3285 case GL_MITER_REVERT_CHROMIUM:
3286 case GL_BEVEL_CHROMIUM:
3287 case GL_ROUND_CHROMIUM:
3288 break;
3289 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003291 return false;
3292 }
3293 case GL_PATH_MITER_LIMIT_CHROMIUM:
3294 if (value < 0.0f)
3295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003296 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003297 return false;
3298 }
3299 break;
3300
3301 case GL_PATH_STROKE_BOUND_CHROMIUM:
3302 // no errors, only clamping.
3303 break;
3304
3305 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003306 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003307 return false;
3308 }
3309 return true;
3310}
3311
3312bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3313{
3314 if (!context->getExtensions().pathRendering)
3315 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003316 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003317 return false;
3318 }
3319
3320 if (!context->hasPath(path))
3321 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003323 return false;
3324 }
3325 if (!value)
3326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003327 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003328 return false;
3329 }
3330
3331 switch (pname)
3332 {
3333 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3334 case GL_PATH_END_CAPS_CHROMIUM:
3335 case GL_PATH_JOIN_STYLE_CHROMIUM:
3336 case GL_PATH_MITER_LIMIT_CHROMIUM:
3337 case GL_PATH_STROKE_BOUND_CHROMIUM:
3338 break;
3339
3340 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003341 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003342 return false;
3343 }
3344
3345 return true;
3346}
3347
3348bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3349{
3350 if (!context->getExtensions().pathRendering)
3351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003352 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003353 return false;
3354 }
3355
3356 switch (func)
3357 {
3358 case GL_NEVER:
3359 case GL_ALWAYS:
3360 case GL_LESS:
3361 case GL_LEQUAL:
3362 case GL_EQUAL:
3363 case GL_GEQUAL:
3364 case GL_GREATER:
3365 case GL_NOTEQUAL:
3366 break;
3367 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003368 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003369 return false;
3370 }
3371
3372 return true;
3373}
3374
3375// Note that the spec specifies that for the path drawing commands
3376// if the path object is not an existing path object the command
3377// does nothing and no error is generated.
3378// However if the path object exists but has not been specified any
3379// commands then an error is generated.
3380
3381bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3382{
3383 if (!context->getExtensions().pathRendering)
3384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003385 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003386 return false;
3387 }
3388 if (context->hasPath(path) && !context->hasPathData(path))
3389 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003390 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003391 return false;
3392 }
3393
3394 switch (fillMode)
3395 {
3396 case GL_COUNT_UP_CHROMIUM:
3397 case GL_COUNT_DOWN_CHROMIUM:
3398 break;
3399 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003400 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003401 return false;
3402 }
3403
3404 if (!isPow2(mask + 1))
3405 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003406 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003407 return false;
3408 }
3409
3410 return true;
3411}
3412
3413bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3414{
3415 if (!context->getExtensions().pathRendering)
3416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003417 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003418 return false;
3419 }
3420 if (context->hasPath(path) && !context->hasPathData(path))
3421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003422 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003423 return false;
3424 }
3425
3426 return true;
3427}
3428
3429bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3430{
3431 if (!context->getExtensions().pathRendering)
3432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003433 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003434 return false;
3435 }
3436 if (context->hasPath(path) && !context->hasPathData(path))
3437 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003439 return false;
3440 }
3441
3442 switch (coverMode)
3443 {
3444 case GL_CONVEX_HULL_CHROMIUM:
3445 case GL_BOUNDING_BOX_CHROMIUM:
3446 break;
3447 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003448 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003449 return false;
3450 }
3451 return true;
3452}
3453
3454bool ValidateStencilThenCoverFillPath(Context *context,
3455 GLuint path,
3456 GLenum fillMode,
3457 GLuint mask,
3458 GLenum coverMode)
3459{
3460 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3461 ValidateCoverPath(context, path, coverMode);
3462}
3463
3464bool ValidateStencilThenCoverStrokePath(Context *context,
3465 GLuint path,
3466 GLint reference,
3467 GLuint mask,
3468 GLenum coverMode)
3469{
3470 return ValidateStencilStrokePath(context, path, reference, mask) &&
3471 ValidateCoverPath(context, path, coverMode);
3472}
3473
3474bool ValidateIsPath(Context *context)
3475{
3476 if (!context->getExtensions().pathRendering)
3477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003478 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003479 return false;
3480 }
3481 return true;
3482}
3483
Sami Väisänend59ca052016-06-21 16:10:00 +03003484bool ValidateCoverFillPathInstanced(Context *context,
3485 GLsizei numPaths,
3486 GLenum pathNameType,
3487 const void *paths,
3488 GLuint pathBase,
3489 GLenum coverMode,
3490 GLenum transformType,
3491 const GLfloat *transformValues)
3492{
3493 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3494 transformType, transformValues))
3495 return false;
3496
3497 switch (coverMode)
3498 {
3499 case GL_CONVEX_HULL_CHROMIUM:
3500 case GL_BOUNDING_BOX_CHROMIUM:
3501 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3502 break;
3503 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003504 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003505 return false;
3506 }
3507
3508 return true;
3509}
3510
3511bool ValidateCoverStrokePathInstanced(Context *context,
3512 GLsizei numPaths,
3513 GLenum pathNameType,
3514 const void *paths,
3515 GLuint pathBase,
3516 GLenum coverMode,
3517 GLenum transformType,
3518 const GLfloat *transformValues)
3519{
3520 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3521 transformType, transformValues))
3522 return false;
3523
3524 switch (coverMode)
3525 {
3526 case GL_CONVEX_HULL_CHROMIUM:
3527 case GL_BOUNDING_BOX_CHROMIUM:
3528 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3529 break;
3530 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003532 return false;
3533 }
3534
3535 return true;
3536}
3537
3538bool ValidateStencilFillPathInstanced(Context *context,
3539 GLsizei numPaths,
3540 GLenum pathNameType,
3541 const void *paths,
3542 GLuint pathBase,
3543 GLenum fillMode,
3544 GLuint mask,
3545 GLenum transformType,
3546 const GLfloat *transformValues)
3547{
3548
3549 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3550 transformType, transformValues))
3551 return false;
3552
3553 switch (fillMode)
3554 {
3555 case GL_COUNT_UP_CHROMIUM:
3556 case GL_COUNT_DOWN_CHROMIUM:
3557 break;
3558 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003560 return false;
3561 }
3562 if (!isPow2(mask + 1))
3563 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003564 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003565 return false;
3566 }
3567 return true;
3568}
3569
3570bool ValidateStencilStrokePathInstanced(Context *context,
3571 GLsizei numPaths,
3572 GLenum pathNameType,
3573 const void *paths,
3574 GLuint pathBase,
3575 GLint reference,
3576 GLuint mask,
3577 GLenum transformType,
3578 const GLfloat *transformValues)
3579{
3580 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3581 transformType, transformValues))
3582 return false;
3583
3584 // no more validation here.
3585
3586 return true;
3587}
3588
3589bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3590 GLsizei numPaths,
3591 GLenum pathNameType,
3592 const void *paths,
3593 GLuint pathBase,
3594 GLenum fillMode,
3595 GLuint mask,
3596 GLenum coverMode,
3597 GLenum transformType,
3598 const GLfloat *transformValues)
3599{
3600 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3601 transformType, transformValues))
3602 return false;
3603
3604 switch (coverMode)
3605 {
3606 case GL_CONVEX_HULL_CHROMIUM:
3607 case GL_BOUNDING_BOX_CHROMIUM:
3608 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3609 break;
3610 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003612 return false;
3613 }
3614
3615 switch (fillMode)
3616 {
3617 case GL_COUNT_UP_CHROMIUM:
3618 case GL_COUNT_DOWN_CHROMIUM:
3619 break;
3620 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003621 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003622 return false;
3623 }
3624 if (!isPow2(mask + 1))
3625 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003626 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003627 return false;
3628 }
3629
3630 return true;
3631}
3632
3633bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3634 GLsizei numPaths,
3635 GLenum pathNameType,
3636 const void *paths,
3637 GLuint pathBase,
3638 GLint reference,
3639 GLuint mask,
3640 GLenum coverMode,
3641 GLenum transformType,
3642 const GLfloat *transformValues)
3643{
3644 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3645 transformType, transformValues))
3646 return false;
3647
3648 switch (coverMode)
3649 {
3650 case GL_CONVEX_HULL_CHROMIUM:
3651 case GL_BOUNDING_BOX_CHROMIUM:
3652 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3653 break;
3654 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003655 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003656 return false;
3657 }
3658
3659 return true;
3660}
3661
Sami Väisänen46eaa942016-06-29 10:26:37 +03003662bool ValidateBindFragmentInputLocation(Context *context,
3663 GLuint program,
3664 GLint location,
3665 const GLchar *name)
3666{
3667 if (!context->getExtensions().pathRendering)
3668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003670 return false;
3671 }
3672
3673 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3674 if (location >= MaxLocation)
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003677 return false;
3678 }
3679
3680 const auto *programObject = context->getProgram(program);
3681 if (!programObject)
3682 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003684 return false;
3685 }
3686
3687 if (!name)
3688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003690 return false;
3691 }
3692
3693 if (angle::BeginsWith(name, "gl_"))
3694 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003695 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003696 return false;
3697 }
3698
3699 return true;
3700}
3701
3702bool ValidateProgramPathFragmentInputGen(Context *context,
3703 GLuint program,
3704 GLint location,
3705 GLenum genMode,
3706 GLint components,
3707 const GLfloat *coeffs)
3708{
3709 if (!context->getExtensions().pathRendering)
3710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003712 return false;
3713 }
3714
3715 const auto *programObject = context->getProgram(program);
3716 if (!programObject || programObject->isFlaggedForDeletion())
3717 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003719 return false;
3720 }
3721
3722 if (!programObject->isLinked())
3723 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003725 return false;
3726 }
3727
3728 switch (genMode)
3729 {
3730 case GL_NONE:
3731 if (components != 0)
3732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003734 return false;
3735 }
3736 break;
3737
3738 case GL_OBJECT_LINEAR_CHROMIUM:
3739 case GL_EYE_LINEAR_CHROMIUM:
3740 case GL_CONSTANT_CHROMIUM:
3741 if (components < 1 || components > 4)
3742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003744 return false;
3745 }
3746 if (!coeffs)
3747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003749 return false;
3750 }
3751 break;
3752
3753 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003755 return false;
3756 }
3757
3758 // If the location is -1 then the command is silently ignored
3759 // and no further validation is needed.
3760 if (location == -1)
3761 return true;
3762
Jamie Madillbd044ed2017-06-05 12:59:21 -04003763 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003764
3765 if (!binding.valid)
3766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003768 return false;
3769 }
3770
3771 if (binding.type != GL_NONE)
3772 {
3773 GLint expectedComponents = 0;
3774 switch (binding.type)
3775 {
3776 case GL_FLOAT:
3777 expectedComponents = 1;
3778 break;
3779 case GL_FLOAT_VEC2:
3780 expectedComponents = 2;
3781 break;
3782 case GL_FLOAT_VEC3:
3783 expectedComponents = 3;
3784 break;
3785 case GL_FLOAT_VEC4:
3786 expectedComponents = 4;
3787 break;
3788 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003789 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 InvalidOperation()
3791 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003792 return false;
3793 }
3794 if (expectedComponents != components && genMode != GL_NONE)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003797 return false;
3798 }
3799 }
3800 return true;
3801}
3802
Geoff Lang97073d12016-04-20 10:42:34 -07003803bool ValidateCopyTextureCHROMIUM(Context *context,
3804 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003805 GLint sourceLevel,
3806 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003807 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003808 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003809 GLint internalFormat,
3810 GLenum destType,
3811 GLboolean unpackFlipY,
3812 GLboolean unpackPremultiplyAlpha,
3813 GLboolean unpackUnmultiplyAlpha)
3814{
3815 if (!context->getExtensions().copyTexture)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidOperation()
3818 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003819 return false;
3820 }
3821
Geoff Lang4f0e0032017-05-01 16:04:35 -04003822 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003823 if (source == nullptr)
3824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003825 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003826 return false;
3827 }
3828
3829 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003831 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003832 return false;
3833 }
3834
3835 GLenum sourceTarget = source->getTarget();
3836 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003837
3838 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003841 return false;
3842 }
3843
Geoff Lang4f0e0032017-05-01 16:04:35 -04003844 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3845 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3846 if (sourceWidth == 0 || sourceHeight == 0)
3847 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003849 return false;
3850 }
3851
3852 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3853 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003856 return false;
3857 }
3858
Geoff Lang4f0e0032017-05-01 16:04:35 -04003859 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003860 if (dest == nullptr)
3861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003862 context->handleError(InvalidValue()
3863 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003864 return false;
3865 }
3866
Geoff Lang4f0e0032017-05-01 16:04:35 -04003867 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003870 return false;
3871 }
3872
Geoff Lang4f0e0032017-05-01 16:04:35 -04003873 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3874 sourceHeight))
3875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003876 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003877 return false;
3878 }
3879
Geoff Lang97073d12016-04-20 10:42:34 -07003880 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3881 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003883 return false;
3884 }
3885
Geoff Lang4f0e0032017-05-01 16:04:35 -04003886 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003888 context->handleError(
3889 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003890 return false;
3891 }
3892
Geoff Lang97073d12016-04-20 10:42:34 -07003893 if (dest->getImmutableFormat())
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003896 return false;
3897 }
3898
3899 return true;
3900}
3901
3902bool ValidateCopySubTextureCHROMIUM(Context *context,
3903 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003904 GLint sourceLevel,
3905 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003906 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003907 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003908 GLint xoffset,
3909 GLint yoffset,
3910 GLint x,
3911 GLint y,
3912 GLsizei width,
3913 GLsizei height,
3914 GLboolean unpackFlipY,
3915 GLboolean unpackPremultiplyAlpha,
3916 GLboolean unpackUnmultiplyAlpha)
3917{
3918 if (!context->getExtensions().copyTexture)
3919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003920 context->handleError(InvalidOperation()
3921 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003922 return false;
3923 }
3924
Geoff Lang4f0e0032017-05-01 16:04:35 -04003925 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003926 if (source == nullptr)
3927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003928 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003929 return false;
3930 }
3931
3932 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003935 return false;
3936 }
3937
3938 GLenum sourceTarget = source->getTarget();
3939 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003940
3941 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003943 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003944 return false;
3945 }
3946
3947 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3948 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003950 context->handleError(InvalidValue()
3951 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003952 return false;
3953 }
3954
3955 if (x < 0 || y < 0)
3956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003957 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003958 return false;
3959 }
3960
3961 if (width < 0 || height < 0)
3962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003964 return false;
3965 }
3966
Geoff Lang4f0e0032017-05-01 16:04:35 -04003967 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3968 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003971 return false;
3972 }
3973
Geoff Lang4f0e0032017-05-01 16:04:35 -04003974 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3975 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003978 return false;
3979 }
3980
Geoff Lang4f0e0032017-05-01 16:04:35 -04003981 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003982 if (dest == nullptr)
3983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003984 context->handleError(InvalidValue()
3985 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003986 return false;
3987 }
3988
Geoff Lang4f0e0032017-05-01 16:04:35 -04003989 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003991 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003992 return false;
3993 }
3994
Geoff Lang4f0e0032017-05-01 16:04:35 -04003995 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003997 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003998 return false;
3999 }
4000
Geoff Lang4f0e0032017-05-01 16:04:35 -04004001 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
4002 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04004003 context
4004 ->handleError(InvalidOperation()
4005 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04004006 return false;
4007 }
4008
4009 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
4010 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004012 context->handleError(InvalidOperation()
4013 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004014 return false;
4015 }
4016
4017 if (xoffset < 0 || yoffset < 0)
4018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004019 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07004020 return false;
4021 }
4022
Geoff Lang4f0e0032017-05-01 16:04:35 -04004023 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
4024 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004026 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07004027 return false;
4028 }
4029
4030 return true;
4031}
4032
Geoff Lang47110bf2016-04-20 11:13:22 -07004033bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
4034{
4035 if (!context->getExtensions().copyCompressedTexture)
4036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004037 context->handleError(InvalidOperation()
4038 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004039 return false;
4040 }
4041
4042 const gl::Texture *source = context->getTexture(sourceId);
4043 if (source == nullptr)
4044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004045 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004046 return false;
4047 }
4048
4049 if (source->getTarget() != GL_TEXTURE_2D)
4050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004051 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004052 return false;
4053 }
4054
4055 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004057 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004058 return false;
4059 }
4060
4061 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4062 if (!sourceFormat.info->compressed)
4063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004064 context->handleError(InvalidOperation()
4065 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004066 return false;
4067 }
4068
4069 const gl::Texture *dest = context->getTexture(destId);
4070 if (dest == nullptr)
4071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004072 context->handleError(InvalidValue()
4073 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004074 return false;
4075 }
4076
4077 if (dest->getTarget() != GL_TEXTURE_2D)
4078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004079 context->handleError(InvalidValue()
4080 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004081 return false;
4082 }
4083
4084 if (dest->getImmutableFormat())
4085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004086 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004087 return false;
4088 }
4089
4090 return true;
4091}
4092
Martin Radev4c4c8e72016-08-04 12:25:34 +03004093bool ValidateCreateShader(Context *context, GLenum type)
4094{
4095 switch (type)
4096 {
4097 case GL_VERTEX_SHADER:
4098 case GL_FRAGMENT_SHADER:
4099 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004100
Martin Radev4c4c8e72016-08-04 12:25:34 +03004101 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004102 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004103 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Langeb66a6e2016-10-31 13:06:12 -04004105 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004106 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004107 break;
4108
Martin Radev4c4c8e72016-08-04 12:25:34 +03004109 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004111 return false;
4112 }
Jamie Madill29639852016-09-02 15:00:09 -04004113
4114 return true;
4115}
4116
4117bool ValidateBufferData(ValidationContext *context,
4118 GLenum target,
4119 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004120 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04004121 GLenum usage)
4122{
4123 if (size < 0)
4124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004125 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004126 return false;
4127 }
4128
4129 switch (usage)
4130 {
4131 case GL_STREAM_DRAW:
4132 case GL_STATIC_DRAW:
4133 case GL_DYNAMIC_DRAW:
4134 break;
4135
4136 case GL_STREAM_READ:
4137 case GL_STREAM_COPY:
4138 case GL_STATIC_READ:
4139 case GL_STATIC_COPY:
4140 case GL_DYNAMIC_READ:
4141 case GL_DYNAMIC_COPY:
4142 if (context->getClientMajorVersion() < 3)
4143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004145 return false;
4146 }
4147 break;
4148
4149 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004151 return false;
4152 }
4153
4154 if (!ValidBufferTarget(context, target))
4155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004156 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004157 return false;
4158 }
4159
4160 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4161
4162 if (!buffer)
4163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004165 return false;
4166 }
4167
4168 return true;
4169}
4170
4171bool ValidateBufferSubData(ValidationContext *context,
4172 GLenum target,
4173 GLintptr offset,
4174 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004175 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004176{
Brandon Jones6cad5662017-06-14 13:25:13 -07004177 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004179 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4180 return false;
4181 }
4182
4183 if (offset < 0)
4184 {
4185 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004186 return false;
4187 }
4188
4189 if (!ValidBufferTarget(context, target))
4190 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004191 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004192 return false;
4193 }
4194
4195 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4196
4197 if (!buffer)
4198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004200 return false;
4201 }
4202
4203 if (buffer->isMapped())
4204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004205 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004206 return false;
4207 }
4208
4209 // Check for possible overflow of size + offset
4210 angle::CheckedNumeric<size_t> checkedSize(size);
4211 checkedSize += offset;
4212 if (!checkedSize.IsValid())
4213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004214 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004215 return false;
4216 }
4217
4218 if (size + offset > buffer->getSize())
4219 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004220 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004221 return false;
4222 }
4223
Martin Radev4c4c8e72016-08-04 12:25:34 +03004224 return true;
4225}
4226
Geoff Langc339c4e2016-11-29 10:37:36 -05004227bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004228{
Geoff Langc339c4e2016-11-29 10:37:36 -05004229 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004231 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004232 return false;
4233 }
4234
4235 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
4236 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05004237 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04004238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004239 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004240 return false;
4241 }
4242
4243 return true;
4244}
4245
Jamie Madillef300b12016-10-07 15:12:09 -04004246bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4247{
4248 if (texture < GL_TEXTURE0 ||
4249 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004251 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004252 return false;
4253 }
4254
4255 return true;
4256}
4257
4258bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4259{
4260 Program *programObject = GetValidProgram(context, program);
4261 if (!programObject)
4262 {
4263 return false;
4264 }
4265
4266 Shader *shaderObject = GetValidShader(context, shader);
4267 if (!shaderObject)
4268 {
4269 return false;
4270 }
4271
4272 switch (shaderObject->getType())
4273 {
4274 case GL_VERTEX_SHADER:
4275 {
4276 if (programObject->getAttachedVertexShader())
4277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004279 return false;
4280 }
4281 break;
4282 }
4283 case GL_FRAGMENT_SHADER:
4284 {
4285 if (programObject->getAttachedFragmentShader())
4286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004288 return false;
4289 }
4290 break;
4291 }
4292 case GL_COMPUTE_SHADER:
4293 {
4294 if (programObject->getAttachedComputeShader())
4295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004297 return false;
4298 }
4299 break;
4300 }
4301 default:
4302 UNREACHABLE();
4303 break;
4304 }
4305
4306 return true;
4307}
4308
Jamie Madill01a80ee2016-11-07 12:06:18 -05004309bool ValidateBindAttribLocation(ValidationContext *context,
4310 GLuint program,
4311 GLuint index,
4312 const GLchar *name)
4313{
4314 if (index >= MAX_VERTEX_ATTRIBS)
4315 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004316 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004317 return false;
4318 }
4319
4320 if (strncmp(name, "gl_", 3) == 0)
4321 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004323 return false;
4324 }
4325
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004326 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004327 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004328 const size_t length = strlen(name);
4329
4330 if (!IsValidESSLString(name, length))
4331 {
4332 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4333 // for shader-related entry points
4334 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4335 return false;
4336 }
4337
4338 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4339 {
4340 return false;
4341 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004342 }
4343
Jamie Madill01a80ee2016-11-07 12:06:18 -05004344 return GetValidProgram(context, program) != nullptr;
4345}
4346
4347bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4348{
4349 if (!ValidBufferTarget(context, target))
4350 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004351 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004352 return false;
4353 }
4354
4355 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4356 !context->isBufferGenerated(buffer))
4357 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004358 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004359 return false;
4360 }
4361
4362 return true;
4363}
4364
4365bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4366{
4367 if (!ValidFramebufferTarget(target))
4368 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004369 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004370 return false;
4371 }
4372
4373 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4374 !context->isFramebufferGenerated(framebuffer))
4375 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004376 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004377 return false;
4378 }
4379
4380 return true;
4381}
4382
4383bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4384{
4385 if (target != GL_RENDERBUFFER)
4386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004388 return false;
4389 }
4390
4391 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4392 !context->isRenderbufferGenerated(renderbuffer))
4393 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004395 return false;
4396 }
4397
4398 return true;
4399}
4400
Geoff Lang50cac572017-09-26 17:37:43 -04004401static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004402{
4403 switch (mode)
4404 {
4405 case GL_FUNC_ADD:
4406 case GL_FUNC_SUBTRACT:
4407 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004408 return true;
4409
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004410 case GL_MIN:
4411 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004412 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004413
4414 default:
4415 return false;
4416 }
4417}
4418
Jamie Madillc1d770e2017-04-13 17:31:24 -04004419bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004420 GLfloat red,
4421 GLfloat green,
4422 GLfloat blue,
4423 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004424{
4425 return true;
4426}
4427
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004428bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4429{
Geoff Lang50cac572017-09-26 17:37:43 -04004430 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004431 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004433 return false;
4434 }
4435
4436 return true;
4437}
4438
4439bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4440{
Geoff Lang50cac572017-09-26 17:37:43 -04004441 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004442 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004444 return false;
4445 }
4446
Geoff Lang50cac572017-09-26 17:37:43 -04004447 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004448 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004450 return false;
4451 }
4452
4453 return true;
4454}
4455
4456bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4457{
4458 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4459}
4460
4461static bool ValidSrcBlendFunc(GLenum srcBlend)
4462{
4463 switch (srcBlend)
4464 {
4465 case GL_ZERO:
4466 case GL_ONE:
4467 case GL_SRC_COLOR:
4468 case GL_ONE_MINUS_SRC_COLOR:
4469 case GL_DST_COLOR:
4470 case GL_ONE_MINUS_DST_COLOR:
4471 case GL_SRC_ALPHA:
4472 case GL_ONE_MINUS_SRC_ALPHA:
4473 case GL_DST_ALPHA:
4474 case GL_ONE_MINUS_DST_ALPHA:
4475 case GL_CONSTANT_COLOR:
4476 case GL_ONE_MINUS_CONSTANT_COLOR:
4477 case GL_CONSTANT_ALPHA:
4478 case GL_ONE_MINUS_CONSTANT_ALPHA:
4479 case GL_SRC_ALPHA_SATURATE:
4480 return true;
4481
4482 default:
4483 return false;
4484 }
4485}
4486
4487static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4488{
4489 switch (dstBlend)
4490 {
4491 case GL_ZERO:
4492 case GL_ONE:
4493 case GL_SRC_COLOR:
4494 case GL_ONE_MINUS_SRC_COLOR:
4495 case GL_DST_COLOR:
4496 case GL_ONE_MINUS_DST_COLOR:
4497 case GL_SRC_ALPHA:
4498 case GL_ONE_MINUS_SRC_ALPHA:
4499 case GL_DST_ALPHA:
4500 case GL_ONE_MINUS_DST_ALPHA:
4501 case GL_CONSTANT_COLOR:
4502 case GL_ONE_MINUS_CONSTANT_COLOR:
4503 case GL_CONSTANT_ALPHA:
4504 case GL_ONE_MINUS_CONSTANT_ALPHA:
4505 return true;
4506
4507 case GL_SRC_ALPHA_SATURATE:
4508 return (contextMajorVersion >= 3);
4509
4510 default:
4511 return false;
4512 }
4513}
4514
4515bool ValidateBlendFuncSeparate(ValidationContext *context,
4516 GLenum srcRGB,
4517 GLenum dstRGB,
4518 GLenum srcAlpha,
4519 GLenum dstAlpha)
4520{
4521 if (!ValidSrcBlendFunc(srcRGB))
4522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004524 return false;
4525 }
4526
4527 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004529 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004530 return false;
4531 }
4532
4533 if (!ValidSrcBlendFunc(srcAlpha))
4534 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004536 return false;
4537 }
4538
4539 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4540 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004542 return false;
4543 }
4544
Frank Henigman146e8a12017-03-02 23:22:37 -05004545 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4546 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004547 {
4548 bool constantColorUsed =
4549 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4550 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4551
4552 bool constantAlphaUsed =
4553 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4554 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4555
4556 if (constantColorUsed && constantAlphaUsed)
4557 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004558 const char *msg;
4559 if (context->getExtensions().webglCompatibility)
4560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004561 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004562 }
4563 else
4564 {
4565 msg =
4566 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4567 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4568 "implementation.";
4569 ERR() << msg;
4570 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004571 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004572 return false;
4573 }
4574 }
4575
4576 return true;
4577}
4578
Geoff Langc339c4e2016-11-29 10:37:36 -05004579bool ValidateGetString(Context *context, GLenum name)
4580{
4581 switch (name)
4582 {
4583 case GL_VENDOR:
4584 case GL_RENDERER:
4585 case GL_VERSION:
4586 case GL_SHADING_LANGUAGE_VERSION:
4587 case GL_EXTENSIONS:
4588 break;
4589
4590 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4591 if (!context->getExtensions().requestExtension)
4592 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004593 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004594 return false;
4595 }
4596 break;
4597
4598 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004599 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004600 return false;
4601 }
4602
4603 return true;
4604}
4605
Geoff Lang47c48082016-12-07 15:38:13 -05004606bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4607{
4608 if (width <= 0.0f || isNaN(width))
4609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004610 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004611 return false;
4612 }
4613
4614 return true;
4615}
4616
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004617bool ValidateVertexAttribPointer(ValidationContext *context,
4618 GLuint index,
4619 GLint size,
4620 GLenum type,
4621 GLboolean normalized,
4622 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004623 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004624{
Shao80957d92017-02-20 21:25:59 +08004625 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004626 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004627 return false;
4628 }
4629
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004630 if (stride < 0)
4631 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004632 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004633 return false;
4634 }
4635
Shao80957d92017-02-20 21:25:59 +08004636 const Caps &caps = context->getCaps();
4637 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004638 {
Shao80957d92017-02-20 21:25:59 +08004639 if (stride > caps.maxVertexAttribStride)
4640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004641 context->handleError(InvalidValue()
4642 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004643 return false;
4644 }
4645
4646 if (index >= caps.maxVertexAttribBindings)
4647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004648 context->handleError(InvalidValue()
4649 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004650 return false;
4651 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004652 }
4653
4654 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4655 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4656 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4657 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004658 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4659 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004660 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004662 context
4663 ->handleError(InvalidOperation()
4664 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004665 return false;
4666 }
4667
4668 if (context->getExtensions().webglCompatibility)
4669 {
4670 // WebGL 1.0 [Section 6.14] Fixed point support
4671 // The WebGL API does not support the GL_FIXED data type.
4672 if (type == GL_FIXED)
4673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004674 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004675 return false;
4676 }
4677
Geoff Lang2d62ab72017-03-23 16:54:40 -04004678 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004679 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004680 return false;
4681 }
4682 }
4683
4684 return true;
4685}
4686
Jamie Madill876429b2017-04-20 15:46:24 -04004687bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004688{
4689 if (context->getExtensions().webglCompatibility && zNear > zFar)
4690 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004692 return false;
4693 }
4694
4695 return true;
4696}
4697
Jamie Madille8fb6402017-02-14 17:56:40 -05004698bool ValidateRenderbufferStorage(ValidationContext *context,
4699 GLenum target,
4700 GLenum internalformat,
4701 GLsizei width,
4702 GLsizei height)
4703{
4704 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4705 height);
4706}
4707
4708bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4709 GLenum target,
4710 GLsizei samples,
4711 GLenum internalformat,
4712 GLsizei width,
4713 GLsizei height)
4714{
4715 if (!context->getExtensions().framebufferMultisample)
4716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004717 context->handleError(InvalidOperation()
4718 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004719 return false;
4720 }
4721
4722 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4723 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4724 // generated.
4725 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004727 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004728 return false;
4729 }
4730
4731 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4732 // the specified storage. This is different than ES 3.0 in which a sample number higher
4733 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4734 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4735 if (context->getClientMajorVersion() >= 3)
4736 {
4737 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4738 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004740 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004741 return false;
4742 }
4743 }
4744
4745 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4746 width, height);
4747}
4748
Jamie Madillc1d770e2017-04-13 17:31:24 -04004749bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4750{
4751 if (!ValidFramebufferTarget(target))
4752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004753 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004754 return false;
4755 }
4756
4757 return true;
4758}
4759
4760bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004761 GLfloat red,
4762 GLfloat green,
4763 GLfloat blue,
4764 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004765{
4766 return true;
4767}
4768
Jamie Madill876429b2017-04-20 15:46:24 -04004769bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004770{
4771 return true;
4772}
4773
4774bool ValidateClearStencil(ValidationContext *context, GLint s)
4775{
4776 return true;
4777}
4778
4779bool ValidateColorMask(ValidationContext *context,
4780 GLboolean red,
4781 GLboolean green,
4782 GLboolean blue,
4783 GLboolean alpha)
4784{
4785 return true;
4786}
4787
4788bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4789{
4790 return true;
4791}
4792
4793bool ValidateCreateProgram(ValidationContext *context)
4794{
4795 return true;
4796}
4797
4798bool ValidateCullFace(ValidationContext *context, GLenum mode)
4799{
4800 switch (mode)
4801 {
4802 case GL_FRONT:
4803 case GL_BACK:
4804 case GL_FRONT_AND_BACK:
4805 break;
4806
4807 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004808 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004809 return false;
4810 }
4811
4812 return true;
4813}
4814
4815bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4816{
4817 if (program == 0)
4818 {
4819 return false;
4820 }
4821
4822 if (!context->getProgram(program))
4823 {
4824 if (context->getShader(program))
4825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004827 return false;
4828 }
4829 else
4830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004831 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004832 return false;
4833 }
4834 }
4835
4836 return true;
4837}
4838
4839bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4840{
4841 if (shader == 0)
4842 {
4843 return false;
4844 }
4845
4846 if (!context->getShader(shader))
4847 {
4848 if (context->getProgram(shader))
4849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004851 return false;
4852 }
4853 else
4854 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004855 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004856 return false;
4857 }
4858 }
4859
4860 return true;
4861}
4862
4863bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4864{
4865 switch (func)
4866 {
4867 case GL_NEVER:
4868 case GL_ALWAYS:
4869 case GL_LESS:
4870 case GL_LEQUAL:
4871 case GL_EQUAL:
4872 case GL_GREATER:
4873 case GL_GEQUAL:
4874 case GL_NOTEQUAL:
4875 break;
4876
4877 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004878 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004879 return false;
4880 }
4881
4882 return true;
4883}
4884
4885bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4886{
4887 return true;
4888}
4889
4890bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4891{
4892 Program *programObject = GetValidProgram(context, program);
4893 if (!programObject)
4894 {
4895 return false;
4896 }
4897
4898 Shader *shaderObject = GetValidShader(context, shader);
4899 if (!shaderObject)
4900 {
4901 return false;
4902 }
4903
4904 const Shader *attachedShader = nullptr;
4905
4906 switch (shaderObject->getType())
4907 {
4908 case GL_VERTEX_SHADER:
4909 {
4910 attachedShader = programObject->getAttachedVertexShader();
4911 break;
4912 }
4913 case GL_FRAGMENT_SHADER:
4914 {
4915 attachedShader = programObject->getAttachedFragmentShader();
4916 break;
4917 }
4918 case GL_COMPUTE_SHADER:
4919 {
4920 attachedShader = programObject->getAttachedComputeShader();
4921 break;
4922 }
4923 default:
4924 UNREACHABLE();
4925 return false;
4926 }
4927
4928 if (attachedShader != shaderObject)
4929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004931 return false;
4932 }
4933
4934 return true;
4935}
4936
4937bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4938{
4939 if (index >= MAX_VERTEX_ATTRIBS)
4940 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004941 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004942 return false;
4943 }
4944
4945 return true;
4946}
4947
4948bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4949{
4950 if (index >= MAX_VERTEX_ATTRIBS)
4951 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004952 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004953 return false;
4954 }
4955
4956 return true;
4957}
4958
4959bool ValidateFinish(ValidationContext *context)
4960{
4961 return true;
4962}
4963
4964bool ValidateFlush(ValidationContext *context)
4965{
4966 return true;
4967}
4968
4969bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4970{
4971 switch (mode)
4972 {
4973 case GL_CW:
4974 case GL_CCW:
4975 break;
4976 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004977 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004978 return false;
4979 }
4980
4981 return true;
4982}
4983
4984bool ValidateGetActiveAttrib(ValidationContext *context,
4985 GLuint program,
4986 GLuint index,
4987 GLsizei bufsize,
4988 GLsizei *length,
4989 GLint *size,
4990 GLenum *type,
4991 GLchar *name)
4992{
4993 if (bufsize < 0)
4994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004995 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004996 return false;
4997 }
4998
4999 Program *programObject = GetValidProgram(context, program);
5000
5001 if (!programObject)
5002 {
5003 return false;
5004 }
5005
5006 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5007 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005008 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005009 return false;
5010 }
5011
5012 return true;
5013}
5014
5015bool ValidateGetActiveUniform(ValidationContext *context,
5016 GLuint program,
5017 GLuint index,
5018 GLsizei bufsize,
5019 GLsizei *length,
5020 GLint *size,
5021 GLenum *type,
5022 GLchar *name)
5023{
5024 if (bufsize < 0)
5025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005026 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005027 return false;
5028 }
5029
5030 Program *programObject = GetValidProgram(context, program);
5031
5032 if (!programObject)
5033 {
5034 return false;
5035 }
5036
5037 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5038 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005039 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005040 return false;
5041 }
5042
5043 return true;
5044}
5045
5046bool ValidateGetAttachedShaders(ValidationContext *context,
5047 GLuint program,
5048 GLsizei maxcount,
5049 GLsizei *count,
5050 GLuint *shaders)
5051{
5052 if (maxcount < 0)
5053 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005054 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005055 return false;
5056 }
5057
5058 Program *programObject = GetValidProgram(context, program);
5059
5060 if (!programObject)
5061 {
5062 return false;
5063 }
5064
5065 return true;
5066}
5067
5068bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5069{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005070 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5071 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005072 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005074 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005075 return false;
5076 }
5077
Jamie Madillc1d770e2017-04-13 17:31:24 -04005078 Program *programObject = GetValidProgram(context, program);
5079
5080 if (!programObject)
5081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005083 return false;
5084 }
5085
5086 if (!programObject->isLinked())
5087 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005088 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005089 return false;
5090 }
5091
5092 return true;
5093}
5094
5095bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5096{
5097 GLenum nativeType;
5098 unsigned int numParams = 0;
5099 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5100}
5101
5102bool ValidateGetError(ValidationContext *context)
5103{
5104 return true;
5105}
5106
5107bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5108{
5109 GLenum nativeType;
5110 unsigned int numParams = 0;
5111 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5112}
5113
5114bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5115{
5116 GLenum nativeType;
5117 unsigned int numParams = 0;
5118 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5119}
5120
5121bool ValidateGetProgramInfoLog(ValidationContext *context,
5122 GLuint program,
5123 GLsizei bufsize,
5124 GLsizei *length,
5125 GLchar *infolog)
5126{
5127 if (bufsize < 0)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005130 return false;
5131 }
5132
5133 Program *programObject = GetValidProgram(context, program);
5134 if (!programObject)
5135 {
5136 return false;
5137 }
5138
5139 return true;
5140}
5141
5142bool ValidateGetShaderInfoLog(ValidationContext *context,
5143 GLuint shader,
5144 GLsizei bufsize,
5145 GLsizei *length,
5146 GLchar *infolog)
5147{
5148 if (bufsize < 0)
5149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005150 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005151 return false;
5152 }
5153
5154 Shader *shaderObject = GetValidShader(context, shader);
5155 if (!shaderObject)
5156 {
5157 return false;
5158 }
5159
5160 return true;
5161}
5162
5163bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5164 GLenum shadertype,
5165 GLenum precisiontype,
5166 GLint *range,
5167 GLint *precision)
5168{
5169 switch (shadertype)
5170 {
5171 case GL_VERTEX_SHADER:
5172 case GL_FRAGMENT_SHADER:
5173 break;
5174 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005175 context->handleError(InvalidOperation()
5176 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005177 return false;
5178 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005180 return false;
5181 }
5182
5183 switch (precisiontype)
5184 {
5185 case GL_LOW_FLOAT:
5186 case GL_MEDIUM_FLOAT:
5187 case GL_HIGH_FLOAT:
5188 case GL_LOW_INT:
5189 case GL_MEDIUM_INT:
5190 case GL_HIGH_INT:
5191 break;
5192
5193 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005195 return false;
5196 }
5197
5198 return true;
5199}
5200
5201bool ValidateGetShaderSource(ValidationContext *context,
5202 GLuint shader,
5203 GLsizei bufsize,
5204 GLsizei *length,
5205 GLchar *source)
5206{
5207 if (bufsize < 0)
5208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005209 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005210 return false;
5211 }
5212
5213 Shader *shaderObject = GetValidShader(context, shader);
5214 if (!shaderObject)
5215 {
5216 return false;
5217 }
5218
5219 return true;
5220}
5221
5222bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5223{
5224 if (strstr(name, "gl_") == name)
5225 {
5226 return false;
5227 }
5228
Geoff Langfc32e8b2017-05-31 14:16:59 -04005229 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5230 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005231 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005233 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005234 return false;
5235 }
5236
Jamie Madillc1d770e2017-04-13 17:31:24 -04005237 Program *programObject = GetValidProgram(context, program);
5238
5239 if (!programObject)
5240 {
5241 return false;
5242 }
5243
5244 if (!programObject->isLinked())
5245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005246 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005247 return false;
5248 }
5249
5250 return true;
5251}
5252
5253bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5254{
5255 switch (mode)
5256 {
5257 case GL_FASTEST:
5258 case GL_NICEST:
5259 case GL_DONT_CARE:
5260 break;
5261
5262 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005263 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005264 return false;
5265 }
5266
5267 switch (target)
5268 {
5269 case GL_GENERATE_MIPMAP_HINT:
5270 break;
5271
Geoff Lange7bd2182017-06-16 16:13:13 -04005272 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5273 if (context->getClientVersion() < ES_3_0 &&
5274 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005275 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005276 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005277 return false;
5278 }
5279 break;
5280
5281 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005282 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005283 return false;
5284 }
5285
5286 return true;
5287}
5288
5289bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5290{
5291 return true;
5292}
5293
5294bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5295{
5296 return true;
5297}
5298
5299bool ValidateIsProgram(ValidationContext *context, GLuint program)
5300{
5301 return true;
5302}
5303
5304bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5305{
5306 return true;
5307}
5308
5309bool ValidateIsShader(ValidationContext *context, GLuint shader)
5310{
5311 return true;
5312}
5313
5314bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5315{
5316 return true;
5317}
5318
5319bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5320{
5321 if (context->getClientMajorVersion() < 3)
5322 {
5323 switch (pname)
5324 {
5325 case GL_UNPACK_IMAGE_HEIGHT:
5326 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005327 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005328 return false;
5329
5330 case GL_UNPACK_ROW_LENGTH:
5331 case GL_UNPACK_SKIP_ROWS:
5332 case GL_UNPACK_SKIP_PIXELS:
5333 if (!context->getExtensions().unpackSubimage)
5334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005335 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005336 return false;
5337 }
5338 break;
5339
5340 case GL_PACK_ROW_LENGTH:
5341 case GL_PACK_SKIP_ROWS:
5342 case GL_PACK_SKIP_PIXELS:
5343 if (!context->getExtensions().packSubimage)
5344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005345 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005346 return false;
5347 }
5348 break;
5349 }
5350 }
5351
5352 if (param < 0)
5353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005354 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005355 return false;
5356 }
5357
5358 switch (pname)
5359 {
5360 case GL_UNPACK_ALIGNMENT:
5361 if (param != 1 && param != 2 && param != 4 && param != 8)
5362 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005363 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005364 return false;
5365 }
5366 break;
5367
5368 case GL_PACK_ALIGNMENT:
5369 if (param != 1 && param != 2 && param != 4 && param != 8)
5370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005371 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005372 return false;
5373 }
5374 break;
5375
5376 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005377 if (!context->getExtensions().packReverseRowOrder)
5378 {
5379 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5380 }
5381 break;
5382
Jamie Madillc1d770e2017-04-13 17:31:24 -04005383 case GL_UNPACK_ROW_LENGTH:
5384 case GL_UNPACK_IMAGE_HEIGHT:
5385 case GL_UNPACK_SKIP_IMAGES:
5386 case GL_UNPACK_SKIP_ROWS:
5387 case GL_UNPACK_SKIP_PIXELS:
5388 case GL_PACK_ROW_LENGTH:
5389 case GL_PACK_SKIP_ROWS:
5390 case GL_PACK_SKIP_PIXELS:
5391 break;
5392
5393 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005394 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005395 return false;
5396 }
5397
5398 return true;
5399}
5400
5401bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5402{
5403 return true;
5404}
5405
5406bool ValidateReleaseShaderCompiler(ValidationContext *context)
5407{
5408 return true;
5409}
5410
Jamie Madill876429b2017-04-20 15:46:24 -04005411bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005412{
5413 return true;
5414}
5415
5416bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5417{
5418 if (width < 0 || height < 0)
5419 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005420 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005421 return false;
5422 }
5423
5424 return true;
5425}
5426
5427bool ValidateShaderBinary(ValidationContext *context,
5428 GLsizei n,
5429 const GLuint *shaders,
5430 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005431 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005432 GLsizei length)
5433{
5434 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5435 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5436 shaderBinaryFormats.end())
5437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005438 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005439 return false;
5440 }
5441
5442 return true;
5443}
5444
5445bool ValidateShaderSource(ValidationContext *context,
5446 GLuint shader,
5447 GLsizei count,
5448 const GLchar *const *string,
5449 const GLint *length)
5450{
5451 if (count < 0)
5452 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005453 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005454 return false;
5455 }
5456
Geoff Langfc32e8b2017-05-31 14:16:59 -04005457 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5458 // shader-related entry points
5459 if (context->getExtensions().webglCompatibility)
5460 {
5461 for (GLsizei i = 0; i < count; i++)
5462 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005463 size_t len =
5464 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005465
5466 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005467 if (!IsValidESSLShaderSourceString(string[i], len,
5468 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005470 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005471 return false;
5472 }
5473 }
5474 }
5475
Jamie Madillc1d770e2017-04-13 17:31:24 -04005476 Shader *shaderObject = GetValidShader(context, shader);
5477 if (!shaderObject)
5478 {
5479 return false;
5480 }
5481
5482 return true;
5483}
5484
5485bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5486{
5487 if (!IsValidStencilFunc(func))
5488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005490 return false;
5491 }
5492
5493 return true;
5494}
5495
5496bool ValidateStencilFuncSeparate(ValidationContext *context,
5497 GLenum face,
5498 GLenum func,
5499 GLint ref,
5500 GLuint mask)
5501{
5502 if (!IsValidStencilFace(face))
5503 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005504 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005505 return false;
5506 }
5507
5508 if (!IsValidStencilFunc(func))
5509 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005510 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005511 return false;
5512 }
5513
5514 return true;
5515}
5516
5517bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5518{
5519 return true;
5520}
5521
5522bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5523{
5524 if (!IsValidStencilFace(face))
5525 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005527 return false;
5528 }
5529
5530 return true;
5531}
5532
5533bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5534{
5535 if (!IsValidStencilOp(fail))
5536 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005538 return false;
5539 }
5540
5541 if (!IsValidStencilOp(zfail))
5542 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005543 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005544 return false;
5545 }
5546
5547 if (!IsValidStencilOp(zpass))
5548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005549 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005550 return false;
5551 }
5552
5553 return true;
5554}
5555
5556bool ValidateStencilOpSeparate(ValidationContext *context,
5557 GLenum face,
5558 GLenum fail,
5559 GLenum zfail,
5560 GLenum zpass)
5561{
5562 if (!IsValidStencilFace(face))
5563 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005564 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005565 return false;
5566 }
5567
5568 return ValidateStencilOp(context, fail, zfail, zpass);
5569}
5570
5571bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5572{
5573 return ValidateUniform(context, GL_FLOAT, location, 1);
5574}
5575
5576bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5577{
5578 return ValidateUniform(context, GL_FLOAT, location, count);
5579}
5580
Jamie Madillbe849e42017-05-02 15:49:00 -04005581bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5582{
5583 return ValidateUniform1iv(context, location, 1, &x);
5584}
5585
Jamie Madillc1d770e2017-04-13 17:31:24 -04005586bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5587{
5588 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5589}
5590
5591bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5592{
5593 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5594}
5595
5596bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5597{
5598 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5599}
5600
5601bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5602{
5603 return ValidateUniform(context, GL_INT_VEC2, location, count);
5604}
5605
5606bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5607{
5608 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5609}
5610
5611bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5612{
5613 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5614}
5615
5616bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5617{
5618 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5619}
5620
5621bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5622{
5623 return ValidateUniform(context, GL_INT_VEC3, location, count);
5624}
5625
5626bool ValidateUniform4f(ValidationContext *context,
5627 GLint location,
5628 GLfloat x,
5629 GLfloat y,
5630 GLfloat z,
5631 GLfloat w)
5632{
5633 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5634}
5635
5636bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5637{
5638 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5639}
5640
5641bool ValidateUniform4i(ValidationContext *context,
5642 GLint location,
5643 GLint x,
5644 GLint y,
5645 GLint z,
5646 GLint w)
5647{
5648 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5649}
5650
5651bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5652{
5653 return ValidateUniform(context, GL_INT_VEC4, location, count);
5654}
5655
5656bool ValidateUniformMatrix2fv(ValidationContext *context,
5657 GLint location,
5658 GLsizei count,
5659 GLboolean transpose,
5660 const GLfloat *value)
5661{
5662 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5663}
5664
5665bool ValidateUniformMatrix3fv(ValidationContext *context,
5666 GLint location,
5667 GLsizei count,
5668 GLboolean transpose,
5669 const GLfloat *value)
5670{
5671 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5672}
5673
5674bool ValidateUniformMatrix4fv(ValidationContext *context,
5675 GLint location,
5676 GLsizei count,
5677 GLboolean transpose,
5678 const GLfloat *value)
5679{
5680 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5681}
5682
5683bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5684{
5685 Program *programObject = GetValidProgram(context, program);
5686
5687 if (!programObject)
5688 {
5689 return false;
5690 }
5691
5692 return true;
5693}
5694
Jamie Madillc1d770e2017-04-13 17:31:24 -04005695bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5696{
5697 return ValidateVertexAttribIndex(context, index);
5698}
5699
5700bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5701{
5702 return ValidateVertexAttribIndex(context, index);
5703}
5704
5705bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5706{
5707 return ValidateVertexAttribIndex(context, index);
5708}
5709
5710bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5711{
5712 return ValidateVertexAttribIndex(context, index);
5713}
5714
5715bool ValidateVertexAttrib3f(ValidationContext *context,
5716 GLuint index,
5717 GLfloat x,
5718 GLfloat y,
5719 GLfloat z)
5720{
5721 return ValidateVertexAttribIndex(context, index);
5722}
5723
5724bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5725{
5726 return ValidateVertexAttribIndex(context, index);
5727}
5728
5729bool ValidateVertexAttrib4f(ValidationContext *context,
5730 GLuint index,
5731 GLfloat x,
5732 GLfloat y,
5733 GLfloat z,
5734 GLfloat w)
5735{
5736 return ValidateVertexAttribIndex(context, index);
5737}
5738
5739bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5740{
5741 return ValidateVertexAttribIndex(context, index);
5742}
5743
5744bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5745{
5746 if (width < 0 || height < 0)
5747 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005748 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005749 return false;
5750 }
5751
5752 return true;
5753}
5754
5755bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5756{
5757 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5758}
5759
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005760bool ValidateDrawElements(ValidationContext *context,
5761 GLenum mode,
5762 GLsizei count,
5763 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005764 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005765{
5766 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5767}
5768
Jamie Madillbe849e42017-05-02 15:49:00 -04005769bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5770 GLenum target,
5771 GLenum attachment,
5772 GLenum pname,
5773 GLint *params)
5774{
5775 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5776 nullptr);
5777}
5778
5779bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5780{
5781 return ValidateGetProgramivBase(context, program, pname, nullptr);
5782}
5783
5784bool ValidateCopyTexImage2D(ValidationContext *context,
5785 GLenum target,
5786 GLint level,
5787 GLenum internalformat,
5788 GLint x,
5789 GLint y,
5790 GLsizei width,
5791 GLsizei height,
5792 GLint border)
5793{
5794 if (context->getClientMajorVersion() < 3)
5795 {
5796 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5797 0, x, y, width, height, border);
5798 }
5799
5800 ASSERT(context->getClientMajorVersion() == 3);
5801 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5802 0, x, y, width, height, border);
5803}
5804
5805bool ValidateCopyTexSubImage2D(Context *context,
5806 GLenum target,
5807 GLint level,
5808 GLint xoffset,
5809 GLint yoffset,
5810 GLint x,
5811 GLint y,
5812 GLsizei width,
5813 GLsizei height)
5814{
5815 if (context->getClientMajorVersion() < 3)
5816 {
5817 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5818 yoffset, x, y, width, height, 0);
5819 }
5820
5821 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5822 yoffset, 0, x, y, width, height, 0);
5823}
5824
5825bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5826{
5827 return ValidateGenOrDelete(context, n);
5828}
5829
5830bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5831{
5832 return ValidateGenOrDelete(context, n);
5833}
5834
5835bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5836{
5837 return ValidateGenOrDelete(context, n);
5838}
5839
5840bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5841{
5842 return ValidateGenOrDelete(context, n);
5843}
5844
5845bool ValidateDisable(Context *context, GLenum cap)
5846{
5847 if (!ValidCap(context, cap, false))
5848 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005849 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 return false;
5851 }
5852
5853 return true;
5854}
5855
5856bool ValidateEnable(Context *context, GLenum cap)
5857{
5858 if (!ValidCap(context, cap, false))
5859 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005860 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005861 return false;
5862 }
5863
5864 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5865 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5866 {
5867 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005868 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005869
5870 // We also output an error message to the debugger window if tracing is active, so that
5871 // developers can see the error message.
5872 ERR() << errorMessage;
5873 return false;
5874 }
5875
5876 return true;
5877}
5878
5879bool ValidateFramebufferRenderbuffer(Context *context,
5880 GLenum target,
5881 GLenum attachment,
5882 GLenum renderbuffertarget,
5883 GLuint renderbuffer)
5884{
Brandon Jones6cad5662017-06-14 13:25:13 -07005885 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5888 return false;
5889 }
5890
5891 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5892 {
5893 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 return false;
5895 }
5896
5897 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5898 renderbuffertarget, renderbuffer);
5899}
5900
5901bool ValidateFramebufferTexture2D(Context *context,
5902 GLenum target,
5903 GLenum attachment,
5904 GLenum textarget,
5905 GLuint texture,
5906 GLint level)
5907{
5908 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5909 // extension
5910 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5911 level != 0)
5912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005913 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005914 return false;
5915 }
5916
5917 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5918 {
5919 return false;
5920 }
5921
5922 if (texture != 0)
5923 {
5924 gl::Texture *tex = context->getTexture(texture);
5925 ASSERT(tex);
5926
5927 const gl::Caps &caps = context->getCaps();
5928
5929 switch (textarget)
5930 {
5931 case GL_TEXTURE_2D:
5932 {
5933 if (level > gl::log2(caps.max2DTextureSize))
5934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005935 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 return false;
5937 }
5938 if (tex->getTarget() != GL_TEXTURE_2D)
5939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005941 return false;
5942 }
5943 }
5944 break;
5945
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005946 case GL_TEXTURE_RECTANGLE_ANGLE:
5947 {
5948 if (level != 0)
5949 {
5950 context->handleError(InvalidValue());
5951 return false;
5952 }
5953 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5954 {
5955 context->handleError(InvalidOperation()
5956 << "Textarget must match the texture target type.");
5957 return false;
5958 }
5959 }
5960 break;
5961
Jamie Madillbe849e42017-05-02 15:49:00 -04005962 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5963 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5964 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5968 {
5969 if (level > gl::log2(caps.maxCubeMapTextureSize))
5970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005971 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005972 return false;
5973 }
5974 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005976 context->handleError(InvalidOperation()
5977 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005978 return false;
5979 }
5980 }
5981 break;
5982
5983 case GL_TEXTURE_2D_MULTISAMPLE:
5984 {
5985 if (context->getClientVersion() < ES_3_1)
5986 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005988 return false;
5989 }
5990
5991 if (level != 0)
5992 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005993 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04005994 return false;
5995 }
5996 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005998 context->handleError(InvalidOperation()
5999 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 return false;
6001 }
6002 }
6003 break;
6004
6005 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006006 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006007 return false;
6008 }
6009
6010 const Format &format = tex->getFormat(textarget, level);
6011 if (format.info->compressed)
6012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006013 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006014 return false;
6015 }
6016 }
6017
6018 return true;
6019}
6020
6021bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6022{
6023 return ValidateGenOrDelete(context, n);
6024}
6025
6026bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6027{
6028 return ValidateGenOrDelete(context, n);
6029}
6030
6031bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6032{
6033 return ValidateGenOrDelete(context, n);
6034}
6035
6036bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6037{
6038 return ValidateGenOrDelete(context, n);
6039}
6040
6041bool ValidateGenerateMipmap(Context *context, GLenum target)
6042{
6043 if (!ValidTextureTarget(context, target))
6044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006045 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006046 return false;
6047 }
6048
6049 Texture *texture = context->getTargetTexture(target);
6050
6051 if (texture == nullptr)
6052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006054 return false;
6055 }
6056
6057 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6058
6059 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6060 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6061 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006063 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006064 return false;
6065 }
6066
6067 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006068 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6069 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6070 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006071 {
6072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6073 return false;
6074 }
6075
Geoff Lang536eca12017-09-13 11:23:35 -04006076 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6077 bool formatUnsized = !format.sized;
6078 bool formatColorRenderableAndFilterable =
6079 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6080 format.renderSupport(context->getClientVersion(), context->getExtensions());
6081 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006082 {
Geoff Lang536eca12017-09-13 11:23:35 -04006083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006084 return false;
6085 }
6086
Geoff Lang536eca12017-09-13 11:23:35 -04006087 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6088 // generation
6089 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6090 {
6091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6092 return false;
6093 }
6094
6095 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6096 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006097 bool supportsSRGBMipmapGeneration =
6098 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006099 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006100 {
Geoff Lang536eca12017-09-13 11:23:35 -04006101 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006102 return false;
6103 }
6104
6105 // Non-power of 2 ES2 check
6106 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6107 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6108 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6109 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006110 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6111 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006113 return false;
6114 }
6115
6116 // Cube completeness check
6117 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006120 return false;
6121 }
6122
6123 return true;
6124}
6125
6126bool ValidateGetBufferParameteriv(ValidationContext *context,
6127 GLenum target,
6128 GLenum pname,
6129 GLint *params)
6130{
6131 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6132}
6133
6134bool ValidateGetRenderbufferParameteriv(Context *context,
6135 GLenum target,
6136 GLenum pname,
6137 GLint *params)
6138{
6139 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6140}
6141
6142bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6143{
6144 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6145}
6146
6147bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6148{
6149 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6150}
6151
6152bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6153{
6154 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6155}
6156
6157bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6158{
6159 return ValidateGetUniformBase(context, program, location);
6160}
6161
6162bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6163{
6164 return ValidateGetUniformBase(context, program, location);
6165}
6166
6167bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6168{
6169 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6170}
6171
6172bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6173{
6174 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6175}
6176
6177bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6178{
6179 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6180}
6181
6182bool ValidateIsEnabled(Context *context, GLenum cap)
6183{
6184 if (!ValidCap(context, cap, true))
6185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006187 return false;
6188 }
6189
6190 return true;
6191}
6192
6193bool ValidateLinkProgram(Context *context, GLuint program)
6194{
6195 if (context->hasActiveTransformFeedback(program))
6196 {
6197 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006198 context->handleError(InvalidOperation() << "Cannot link program while program is "
6199 "associated with an active transform "
6200 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006201 return false;
6202 }
6203
6204 Program *programObject = GetValidProgram(context, program);
6205 if (!programObject)
6206 {
6207 return false;
6208 }
6209
6210 return true;
6211}
6212
Jamie Madill4928b7c2017-06-20 12:57:39 -04006213bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006214 GLint x,
6215 GLint y,
6216 GLsizei width,
6217 GLsizei height,
6218 GLenum format,
6219 GLenum type,
6220 void *pixels)
6221{
6222 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6223 nullptr, pixels);
6224}
6225
6226bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6227{
6228 return ValidateTexParameterBase(context, target, pname, -1, &param);
6229}
6230
6231bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6232{
6233 return ValidateTexParameterBase(context, target, pname, -1, params);
6234}
6235
6236bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6237{
6238 return ValidateTexParameterBase(context, target, pname, -1, &param);
6239}
6240
6241bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6242{
6243 return ValidateTexParameterBase(context, target, pname, -1, params);
6244}
6245
6246bool ValidateUseProgram(Context *context, GLuint program)
6247{
6248 if (program != 0)
6249 {
6250 Program *programObject = context->getProgram(program);
6251 if (!programObject)
6252 {
6253 // ES 3.1.0 section 7.3 page 72
6254 if (context->getShader(program))
6255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006257 return false;
6258 }
6259 else
6260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006261 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006262 return false;
6263 }
6264 }
6265 if (!programObject->isLinked())
6266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006268 return false;
6269 }
6270 }
6271 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6272 {
6273 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006274 context
6275 ->handleError(InvalidOperation()
6276 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006277 return false;
6278 }
6279
6280 return true;
6281}
6282
Jamie Madillc29968b2016-01-20 11:17:23 -05006283} // namespace gl