blob: baec2cc3b49f6600d0e3e6243c1cd19a043f80e6 [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,
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004121 BufferUsage usage)
Jamie Madill29639852016-09-02 15:00:09 -04004122{
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 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004131 case BufferUsage::StreamDraw:
4132 case BufferUsage::StaticDraw:
4133 case BufferUsage::DynamicDraw:
Jamie Madill29639852016-09-02 15:00:09 -04004134 break;
4135
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004136 case BufferUsage::StreamRead:
4137 case BufferUsage::StaticRead:
4138 case BufferUsage::DynamicRead:
4139 case BufferUsage::StreamCopy:
4140 case BufferUsage::StaticCopy:
4141 case BufferUsage::DynamicCopy:
Jamie Madill29639852016-09-02 15:00:09 -04004142 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 Lang111a99e2017-10-17 10:58:41 -04004227bool ValidateRequestExtensionANGLE(Context *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
Geoff Lang111a99e2017-10-17 10:58:41 -04004235 if (!context->isExtensionRequestable(name))
Geoff Langc287ea62016-09-16 14:46:51 -04004236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004237 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004238 return false;
4239 }
4240
4241 return true;
4242}
4243
Jamie Madillef300b12016-10-07 15:12:09 -04004244bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4245{
4246 if (texture < GL_TEXTURE0 ||
4247 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004249 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004250 return false;
4251 }
4252
4253 return true;
4254}
4255
4256bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4257{
4258 Program *programObject = GetValidProgram(context, program);
4259 if (!programObject)
4260 {
4261 return false;
4262 }
4263
4264 Shader *shaderObject = GetValidShader(context, shader);
4265 if (!shaderObject)
4266 {
4267 return false;
4268 }
4269
4270 switch (shaderObject->getType())
4271 {
4272 case GL_VERTEX_SHADER:
4273 {
4274 if (programObject->getAttachedVertexShader())
4275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004277 return false;
4278 }
4279 break;
4280 }
4281 case GL_FRAGMENT_SHADER:
4282 {
4283 if (programObject->getAttachedFragmentShader())
4284 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004285 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004286 return false;
4287 }
4288 break;
4289 }
4290 case GL_COMPUTE_SHADER:
4291 {
4292 if (programObject->getAttachedComputeShader())
4293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004295 return false;
4296 }
4297 break;
4298 }
4299 default:
4300 UNREACHABLE();
4301 break;
4302 }
4303
4304 return true;
4305}
4306
Jamie Madill01a80ee2016-11-07 12:06:18 -05004307bool ValidateBindAttribLocation(ValidationContext *context,
4308 GLuint program,
4309 GLuint index,
4310 const GLchar *name)
4311{
4312 if (index >= MAX_VERTEX_ATTRIBS)
4313 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004314 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004315 return false;
4316 }
4317
4318 if (strncmp(name, "gl_", 3) == 0)
4319 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004320 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004321 return false;
4322 }
4323
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004324 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004325 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004326 const size_t length = strlen(name);
4327
4328 if (!IsValidESSLString(name, length))
4329 {
4330 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4331 // for shader-related entry points
4332 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4333 return false;
4334 }
4335
4336 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4337 {
4338 return false;
4339 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004340 }
4341
Jamie Madill01a80ee2016-11-07 12:06:18 -05004342 return GetValidProgram(context, program) != nullptr;
4343}
4344
4345bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4346{
4347 if (!ValidBufferTarget(context, target))
4348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004349 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004350 return false;
4351 }
4352
4353 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4354 !context->isBufferGenerated(buffer))
4355 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004357 return false;
4358 }
4359
4360 return true;
4361}
4362
4363bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4364{
4365 if (!ValidFramebufferTarget(target))
4366 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004367 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004368 return false;
4369 }
4370
4371 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4372 !context->isFramebufferGenerated(framebuffer))
4373 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004374 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004375 return false;
4376 }
4377
4378 return true;
4379}
4380
4381bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4382{
4383 if (target != GL_RENDERBUFFER)
4384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004386 return false;
4387 }
4388
4389 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4390 !context->isRenderbufferGenerated(renderbuffer))
4391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004393 return false;
4394 }
4395
4396 return true;
4397}
4398
Geoff Lang50cac572017-09-26 17:37:43 -04004399static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004400{
4401 switch (mode)
4402 {
4403 case GL_FUNC_ADD:
4404 case GL_FUNC_SUBTRACT:
4405 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004406 return true;
4407
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004408 case GL_MIN:
4409 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004410 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004411
4412 default:
4413 return false;
4414 }
4415}
4416
Jamie Madillc1d770e2017-04-13 17:31:24 -04004417bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004418 GLfloat red,
4419 GLfloat green,
4420 GLfloat blue,
4421 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004422{
4423 return true;
4424}
4425
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004426bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4427{
Geoff Lang50cac572017-09-26 17:37:43 -04004428 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004431 return false;
4432 }
4433
4434 return true;
4435}
4436
4437bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4438{
Geoff Lang50cac572017-09-26 17:37:43 -04004439 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004440 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004441 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004442 return false;
4443 }
4444
Geoff Lang50cac572017-09-26 17:37:43 -04004445 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004446 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004448 return false;
4449 }
4450
4451 return true;
4452}
4453
4454bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4455{
4456 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4457}
4458
4459static bool ValidSrcBlendFunc(GLenum srcBlend)
4460{
4461 switch (srcBlend)
4462 {
4463 case GL_ZERO:
4464 case GL_ONE:
4465 case GL_SRC_COLOR:
4466 case GL_ONE_MINUS_SRC_COLOR:
4467 case GL_DST_COLOR:
4468 case GL_ONE_MINUS_DST_COLOR:
4469 case GL_SRC_ALPHA:
4470 case GL_ONE_MINUS_SRC_ALPHA:
4471 case GL_DST_ALPHA:
4472 case GL_ONE_MINUS_DST_ALPHA:
4473 case GL_CONSTANT_COLOR:
4474 case GL_ONE_MINUS_CONSTANT_COLOR:
4475 case GL_CONSTANT_ALPHA:
4476 case GL_ONE_MINUS_CONSTANT_ALPHA:
4477 case GL_SRC_ALPHA_SATURATE:
4478 return true;
4479
4480 default:
4481 return false;
4482 }
4483}
4484
4485static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4486{
4487 switch (dstBlend)
4488 {
4489 case GL_ZERO:
4490 case GL_ONE:
4491 case GL_SRC_COLOR:
4492 case GL_ONE_MINUS_SRC_COLOR:
4493 case GL_DST_COLOR:
4494 case GL_ONE_MINUS_DST_COLOR:
4495 case GL_SRC_ALPHA:
4496 case GL_ONE_MINUS_SRC_ALPHA:
4497 case GL_DST_ALPHA:
4498 case GL_ONE_MINUS_DST_ALPHA:
4499 case GL_CONSTANT_COLOR:
4500 case GL_ONE_MINUS_CONSTANT_COLOR:
4501 case GL_CONSTANT_ALPHA:
4502 case GL_ONE_MINUS_CONSTANT_ALPHA:
4503 return true;
4504
4505 case GL_SRC_ALPHA_SATURATE:
4506 return (contextMajorVersion >= 3);
4507
4508 default:
4509 return false;
4510 }
4511}
4512
4513bool ValidateBlendFuncSeparate(ValidationContext *context,
4514 GLenum srcRGB,
4515 GLenum dstRGB,
4516 GLenum srcAlpha,
4517 GLenum dstAlpha)
4518{
4519 if (!ValidSrcBlendFunc(srcRGB))
4520 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004521 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004522 return false;
4523 }
4524
4525 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4526 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004527 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004528 return false;
4529 }
4530
4531 if (!ValidSrcBlendFunc(srcAlpha))
4532 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004533 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004534 return false;
4535 }
4536
4537 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4538 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004539 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004540 return false;
4541 }
4542
Frank Henigman146e8a12017-03-02 23:22:37 -05004543 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4544 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004545 {
4546 bool constantColorUsed =
4547 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4548 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4549
4550 bool constantAlphaUsed =
4551 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4552 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4553
4554 if (constantColorUsed && constantAlphaUsed)
4555 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004556 const char *msg;
4557 if (context->getExtensions().webglCompatibility)
4558 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004559 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004560 }
4561 else
4562 {
4563 msg =
4564 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4565 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4566 "implementation.";
4567 ERR() << msg;
4568 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004569 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004570 return false;
4571 }
4572 }
4573
4574 return true;
4575}
4576
Geoff Langc339c4e2016-11-29 10:37:36 -05004577bool ValidateGetString(Context *context, GLenum name)
4578{
4579 switch (name)
4580 {
4581 case GL_VENDOR:
4582 case GL_RENDERER:
4583 case GL_VERSION:
4584 case GL_SHADING_LANGUAGE_VERSION:
4585 case GL_EXTENSIONS:
4586 break;
4587
4588 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4589 if (!context->getExtensions().requestExtension)
4590 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004591 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004592 return false;
4593 }
4594 break;
4595
4596 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004597 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004598 return false;
4599 }
4600
4601 return true;
4602}
4603
Geoff Lang47c48082016-12-07 15:38:13 -05004604bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4605{
4606 if (width <= 0.0f || isNaN(width))
4607 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004608 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004609 return false;
4610 }
4611
4612 return true;
4613}
4614
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004615bool ValidateVertexAttribPointer(ValidationContext *context,
4616 GLuint index,
4617 GLint size,
4618 GLenum type,
4619 GLboolean normalized,
4620 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004621 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004622{
Shao80957d92017-02-20 21:25:59 +08004623 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004624 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004625 return false;
4626 }
4627
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004628 if (stride < 0)
4629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004630 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004631 return false;
4632 }
4633
Shao80957d92017-02-20 21:25:59 +08004634 const Caps &caps = context->getCaps();
4635 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004636 {
Shao80957d92017-02-20 21:25:59 +08004637 if (stride > caps.maxVertexAttribStride)
4638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004639 context->handleError(InvalidValue()
4640 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004641 return false;
4642 }
4643
4644 if (index >= caps.maxVertexAttribBindings)
4645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004646 context->handleError(InvalidValue()
4647 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004648 return false;
4649 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004650 }
4651
4652 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4653 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4654 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4655 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004656 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4657 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004658 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004660 context
4661 ->handleError(InvalidOperation()
4662 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004663 return false;
4664 }
4665
4666 if (context->getExtensions().webglCompatibility)
4667 {
4668 // WebGL 1.0 [Section 6.14] Fixed point support
4669 // The WebGL API does not support the GL_FIXED data type.
4670 if (type == GL_FIXED)
4671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004672 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004673 return false;
4674 }
4675
Geoff Lang2d62ab72017-03-23 16:54:40 -04004676 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004677 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004678 return false;
4679 }
4680 }
4681
4682 return true;
4683}
4684
Jamie Madill876429b2017-04-20 15:46:24 -04004685bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004686{
4687 if (context->getExtensions().webglCompatibility && zNear > zFar)
4688 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004690 return false;
4691 }
4692
4693 return true;
4694}
4695
Jamie Madille8fb6402017-02-14 17:56:40 -05004696bool ValidateRenderbufferStorage(ValidationContext *context,
4697 GLenum target,
4698 GLenum internalformat,
4699 GLsizei width,
4700 GLsizei height)
4701{
4702 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4703 height);
4704}
4705
4706bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4707 GLenum target,
4708 GLsizei samples,
4709 GLenum internalformat,
4710 GLsizei width,
4711 GLsizei height)
4712{
4713 if (!context->getExtensions().framebufferMultisample)
4714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004715 context->handleError(InvalidOperation()
4716 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004717 return false;
4718 }
4719
4720 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4721 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4722 // generated.
4723 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004725 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004726 return false;
4727 }
4728
4729 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4730 // the specified storage. This is different than ES 3.0 in which a sample number higher
4731 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4732 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4733 if (context->getClientMajorVersion() >= 3)
4734 {
4735 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4736 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004738 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004739 return false;
4740 }
4741 }
4742
4743 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4744 width, height);
4745}
4746
Jamie Madillc1d770e2017-04-13 17:31:24 -04004747bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4748{
4749 if (!ValidFramebufferTarget(target))
4750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004752 return false;
4753 }
4754
4755 return true;
4756}
4757
4758bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004759 GLfloat red,
4760 GLfloat green,
4761 GLfloat blue,
4762 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004763{
4764 return true;
4765}
4766
Jamie Madill876429b2017-04-20 15:46:24 -04004767bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004768{
4769 return true;
4770}
4771
4772bool ValidateClearStencil(ValidationContext *context, GLint s)
4773{
4774 return true;
4775}
4776
4777bool ValidateColorMask(ValidationContext *context,
4778 GLboolean red,
4779 GLboolean green,
4780 GLboolean blue,
4781 GLboolean alpha)
4782{
4783 return true;
4784}
4785
4786bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4787{
4788 return true;
4789}
4790
4791bool ValidateCreateProgram(ValidationContext *context)
4792{
4793 return true;
4794}
4795
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004796bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004797{
4798 switch (mode)
4799 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004800 case CullFaceMode::Front:
4801 case CullFaceMode::Back:
4802 case CullFaceMode::FrontAndBack:
Jamie Madillc1d770e2017-04-13 17:31:24 -04004803 break;
4804
4805 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004807 return false;
4808 }
4809
4810 return true;
4811}
4812
4813bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4814{
4815 if (program == 0)
4816 {
4817 return false;
4818 }
4819
4820 if (!context->getProgram(program))
4821 {
4822 if (context->getShader(program))
4823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004824 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004825 return false;
4826 }
4827 else
4828 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004829 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004830 return false;
4831 }
4832 }
4833
4834 return true;
4835}
4836
4837bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4838{
4839 if (shader == 0)
4840 {
4841 return false;
4842 }
4843
4844 if (!context->getShader(shader))
4845 {
4846 if (context->getProgram(shader))
4847 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004849 return false;
4850 }
4851 else
4852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004853 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004854 return false;
4855 }
4856 }
4857
4858 return true;
4859}
4860
4861bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4862{
4863 switch (func)
4864 {
4865 case GL_NEVER:
4866 case GL_ALWAYS:
4867 case GL_LESS:
4868 case GL_LEQUAL:
4869 case GL_EQUAL:
4870 case GL_GREATER:
4871 case GL_GEQUAL:
4872 case GL_NOTEQUAL:
4873 break;
4874
4875 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004876 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004877 return false;
4878 }
4879
4880 return true;
4881}
4882
4883bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4884{
4885 return true;
4886}
4887
4888bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4889{
4890 Program *programObject = GetValidProgram(context, program);
4891 if (!programObject)
4892 {
4893 return false;
4894 }
4895
4896 Shader *shaderObject = GetValidShader(context, shader);
4897 if (!shaderObject)
4898 {
4899 return false;
4900 }
4901
4902 const Shader *attachedShader = nullptr;
4903
4904 switch (shaderObject->getType())
4905 {
4906 case GL_VERTEX_SHADER:
4907 {
4908 attachedShader = programObject->getAttachedVertexShader();
4909 break;
4910 }
4911 case GL_FRAGMENT_SHADER:
4912 {
4913 attachedShader = programObject->getAttachedFragmentShader();
4914 break;
4915 }
4916 case GL_COMPUTE_SHADER:
4917 {
4918 attachedShader = programObject->getAttachedComputeShader();
4919 break;
4920 }
4921 default:
4922 UNREACHABLE();
4923 return false;
4924 }
4925
4926 if (attachedShader != shaderObject)
4927 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004929 return false;
4930 }
4931
4932 return true;
4933}
4934
4935bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4936{
4937 if (index >= MAX_VERTEX_ATTRIBS)
4938 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004939 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004940 return false;
4941 }
4942
4943 return true;
4944}
4945
4946bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4947{
4948 if (index >= MAX_VERTEX_ATTRIBS)
4949 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004950 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004951 return false;
4952 }
4953
4954 return true;
4955}
4956
4957bool ValidateFinish(ValidationContext *context)
4958{
4959 return true;
4960}
4961
4962bool ValidateFlush(ValidationContext *context)
4963{
4964 return true;
4965}
4966
4967bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4968{
4969 switch (mode)
4970 {
4971 case GL_CW:
4972 case GL_CCW:
4973 break;
4974 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004975 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004976 return false;
4977 }
4978
4979 return true;
4980}
4981
4982bool ValidateGetActiveAttrib(ValidationContext *context,
4983 GLuint program,
4984 GLuint index,
4985 GLsizei bufsize,
4986 GLsizei *length,
4987 GLint *size,
4988 GLenum *type,
4989 GLchar *name)
4990{
4991 if (bufsize < 0)
4992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004993 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004994 return false;
4995 }
4996
4997 Program *programObject = GetValidProgram(context, program);
4998
4999 if (!programObject)
5000 {
5001 return false;
5002 }
5003
5004 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5005 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005006 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005007 return false;
5008 }
5009
5010 return true;
5011}
5012
5013bool ValidateGetActiveUniform(ValidationContext *context,
5014 GLuint program,
5015 GLuint index,
5016 GLsizei bufsize,
5017 GLsizei *length,
5018 GLint *size,
5019 GLenum *type,
5020 GLchar *name)
5021{
5022 if (bufsize < 0)
5023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005024 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005025 return false;
5026 }
5027
5028 Program *programObject = GetValidProgram(context, program);
5029
5030 if (!programObject)
5031 {
5032 return false;
5033 }
5034
5035 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5036 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005037 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005038 return false;
5039 }
5040
5041 return true;
5042}
5043
5044bool ValidateGetAttachedShaders(ValidationContext *context,
5045 GLuint program,
5046 GLsizei maxcount,
5047 GLsizei *count,
5048 GLuint *shaders)
5049{
5050 if (maxcount < 0)
5051 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005052 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005053 return false;
5054 }
5055
5056 Program *programObject = GetValidProgram(context, program);
5057
5058 if (!programObject)
5059 {
5060 return false;
5061 }
5062
5063 return true;
5064}
5065
5066bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5067{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005068 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5069 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005070 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005071 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005072 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005073 return false;
5074 }
5075
Jamie Madillc1d770e2017-04-13 17:31:24 -04005076 Program *programObject = GetValidProgram(context, program);
5077
5078 if (!programObject)
5079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005081 return false;
5082 }
5083
5084 if (!programObject->isLinked())
5085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005086 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005087 return false;
5088 }
5089
5090 return true;
5091}
5092
5093bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5094{
5095 GLenum nativeType;
5096 unsigned int numParams = 0;
5097 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5098}
5099
5100bool ValidateGetError(ValidationContext *context)
5101{
5102 return true;
5103}
5104
5105bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5106{
5107 GLenum nativeType;
5108 unsigned int numParams = 0;
5109 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5110}
5111
5112bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5113{
5114 GLenum nativeType;
5115 unsigned int numParams = 0;
5116 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5117}
5118
5119bool ValidateGetProgramInfoLog(ValidationContext *context,
5120 GLuint program,
5121 GLsizei bufsize,
5122 GLsizei *length,
5123 GLchar *infolog)
5124{
5125 if (bufsize < 0)
5126 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005127 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005128 return false;
5129 }
5130
5131 Program *programObject = GetValidProgram(context, program);
5132 if (!programObject)
5133 {
5134 return false;
5135 }
5136
5137 return true;
5138}
5139
5140bool ValidateGetShaderInfoLog(ValidationContext *context,
5141 GLuint shader,
5142 GLsizei bufsize,
5143 GLsizei *length,
5144 GLchar *infolog)
5145{
5146 if (bufsize < 0)
5147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005148 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005149 return false;
5150 }
5151
5152 Shader *shaderObject = GetValidShader(context, shader);
5153 if (!shaderObject)
5154 {
5155 return false;
5156 }
5157
5158 return true;
5159}
5160
5161bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5162 GLenum shadertype,
5163 GLenum precisiontype,
5164 GLint *range,
5165 GLint *precision)
5166{
5167 switch (shadertype)
5168 {
5169 case GL_VERTEX_SHADER:
5170 case GL_FRAGMENT_SHADER:
5171 break;
5172 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(InvalidOperation()
5174 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005175 return false;
5176 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005178 return false;
5179 }
5180
5181 switch (precisiontype)
5182 {
5183 case GL_LOW_FLOAT:
5184 case GL_MEDIUM_FLOAT:
5185 case GL_HIGH_FLOAT:
5186 case GL_LOW_INT:
5187 case GL_MEDIUM_INT:
5188 case GL_HIGH_INT:
5189 break;
5190
5191 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005193 return false;
5194 }
5195
5196 return true;
5197}
5198
5199bool ValidateGetShaderSource(ValidationContext *context,
5200 GLuint shader,
5201 GLsizei bufsize,
5202 GLsizei *length,
5203 GLchar *source)
5204{
5205 if (bufsize < 0)
5206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005207 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005208 return false;
5209 }
5210
5211 Shader *shaderObject = GetValidShader(context, shader);
5212 if (!shaderObject)
5213 {
5214 return false;
5215 }
5216
5217 return true;
5218}
5219
5220bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5221{
5222 if (strstr(name, "gl_") == name)
5223 {
5224 return false;
5225 }
5226
Geoff Langfc32e8b2017-05-31 14:16:59 -04005227 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5228 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005229 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005231 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005232 return false;
5233 }
5234
Jamie Madillc1d770e2017-04-13 17:31:24 -04005235 Program *programObject = GetValidProgram(context, program);
5236
5237 if (!programObject)
5238 {
5239 return false;
5240 }
5241
5242 if (!programObject->isLinked())
5243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005245 return false;
5246 }
5247
5248 return true;
5249}
5250
5251bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5252{
5253 switch (mode)
5254 {
5255 case GL_FASTEST:
5256 case GL_NICEST:
5257 case GL_DONT_CARE:
5258 break;
5259
5260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005262 return false;
5263 }
5264
5265 switch (target)
5266 {
5267 case GL_GENERATE_MIPMAP_HINT:
5268 break;
5269
Geoff Lange7bd2182017-06-16 16:13:13 -04005270 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5271 if (context->getClientVersion() < ES_3_0 &&
5272 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005273 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005274 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005275 return false;
5276 }
5277 break;
5278
5279 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005281 return false;
5282 }
5283
5284 return true;
5285}
5286
5287bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5288{
5289 return true;
5290}
5291
5292bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5293{
5294 return true;
5295}
5296
5297bool ValidateIsProgram(ValidationContext *context, GLuint program)
5298{
5299 return true;
5300}
5301
5302bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5303{
5304 return true;
5305}
5306
5307bool ValidateIsShader(ValidationContext *context, GLuint shader)
5308{
5309 return true;
5310}
5311
5312bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5313{
5314 return true;
5315}
5316
5317bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5318{
5319 if (context->getClientMajorVersion() < 3)
5320 {
5321 switch (pname)
5322 {
5323 case GL_UNPACK_IMAGE_HEIGHT:
5324 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005325 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005326 return false;
5327
5328 case GL_UNPACK_ROW_LENGTH:
5329 case GL_UNPACK_SKIP_ROWS:
5330 case GL_UNPACK_SKIP_PIXELS:
5331 if (!context->getExtensions().unpackSubimage)
5332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005333 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005334 return false;
5335 }
5336 break;
5337
5338 case GL_PACK_ROW_LENGTH:
5339 case GL_PACK_SKIP_ROWS:
5340 case GL_PACK_SKIP_PIXELS:
5341 if (!context->getExtensions().packSubimage)
5342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005343 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005344 return false;
5345 }
5346 break;
5347 }
5348 }
5349
5350 if (param < 0)
5351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005352 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005353 return false;
5354 }
5355
5356 switch (pname)
5357 {
5358 case GL_UNPACK_ALIGNMENT:
5359 if (param != 1 && param != 2 && param != 4 && param != 8)
5360 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005361 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005362 return false;
5363 }
5364 break;
5365
5366 case GL_PACK_ALIGNMENT:
5367 if (param != 1 && param != 2 && param != 4 && param != 8)
5368 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005369 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005370 return false;
5371 }
5372 break;
5373
5374 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005375 if (!context->getExtensions().packReverseRowOrder)
5376 {
5377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5378 }
5379 break;
5380
Jamie Madillc1d770e2017-04-13 17:31:24 -04005381 case GL_UNPACK_ROW_LENGTH:
5382 case GL_UNPACK_IMAGE_HEIGHT:
5383 case GL_UNPACK_SKIP_IMAGES:
5384 case GL_UNPACK_SKIP_ROWS:
5385 case GL_UNPACK_SKIP_PIXELS:
5386 case GL_PACK_ROW_LENGTH:
5387 case GL_PACK_SKIP_ROWS:
5388 case GL_PACK_SKIP_PIXELS:
5389 break;
5390
5391 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005393 return false;
5394 }
5395
5396 return true;
5397}
5398
5399bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5400{
5401 return true;
5402}
5403
5404bool ValidateReleaseShaderCompiler(ValidationContext *context)
5405{
5406 return true;
5407}
5408
Jamie Madill876429b2017-04-20 15:46:24 -04005409bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005410{
5411 return true;
5412}
5413
5414bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5415{
5416 if (width < 0 || height < 0)
5417 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005418 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005419 return false;
5420 }
5421
5422 return true;
5423}
5424
5425bool ValidateShaderBinary(ValidationContext *context,
5426 GLsizei n,
5427 const GLuint *shaders,
5428 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005429 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005430 GLsizei length)
5431{
5432 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5433 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5434 shaderBinaryFormats.end())
5435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005436 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005437 return false;
5438 }
5439
5440 return true;
5441}
5442
5443bool ValidateShaderSource(ValidationContext *context,
5444 GLuint shader,
5445 GLsizei count,
5446 const GLchar *const *string,
5447 const GLint *length)
5448{
5449 if (count < 0)
5450 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005451 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005452 return false;
5453 }
5454
Geoff Langfc32e8b2017-05-31 14:16:59 -04005455 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5456 // shader-related entry points
5457 if (context->getExtensions().webglCompatibility)
5458 {
5459 for (GLsizei i = 0; i < count; i++)
5460 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005461 size_t len =
5462 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005463
5464 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005465 if (!IsValidESSLShaderSourceString(string[i], len,
5466 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005467 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005468 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005469 return false;
5470 }
5471 }
5472 }
5473
Jamie Madillc1d770e2017-04-13 17:31:24 -04005474 Shader *shaderObject = GetValidShader(context, shader);
5475 if (!shaderObject)
5476 {
5477 return false;
5478 }
5479
5480 return true;
5481}
5482
5483bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5484{
5485 if (!IsValidStencilFunc(func))
5486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005488 return false;
5489 }
5490
5491 return true;
5492}
5493
5494bool ValidateStencilFuncSeparate(ValidationContext *context,
5495 GLenum face,
5496 GLenum func,
5497 GLint ref,
5498 GLuint mask)
5499{
5500 if (!IsValidStencilFace(face))
5501 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005502 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005503 return false;
5504 }
5505
5506 if (!IsValidStencilFunc(func))
5507 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005508 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005509 return false;
5510 }
5511
5512 return true;
5513}
5514
5515bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5516{
5517 return true;
5518}
5519
5520bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5521{
5522 if (!IsValidStencilFace(face))
5523 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005524 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005525 return false;
5526 }
5527
5528 return true;
5529}
5530
5531bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5532{
5533 if (!IsValidStencilOp(fail))
5534 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005536 return false;
5537 }
5538
5539 if (!IsValidStencilOp(zfail))
5540 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005542 return false;
5543 }
5544
5545 if (!IsValidStencilOp(zpass))
5546 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005547 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005548 return false;
5549 }
5550
5551 return true;
5552}
5553
5554bool ValidateStencilOpSeparate(ValidationContext *context,
5555 GLenum face,
5556 GLenum fail,
5557 GLenum zfail,
5558 GLenum zpass)
5559{
5560 if (!IsValidStencilFace(face))
5561 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005562 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005563 return false;
5564 }
5565
5566 return ValidateStencilOp(context, fail, zfail, zpass);
5567}
5568
5569bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5570{
5571 return ValidateUniform(context, GL_FLOAT, location, 1);
5572}
5573
5574bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5575{
5576 return ValidateUniform(context, GL_FLOAT, location, count);
5577}
5578
Jamie Madillbe849e42017-05-02 15:49:00 -04005579bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5580{
5581 return ValidateUniform1iv(context, location, 1, &x);
5582}
5583
Jamie Madillc1d770e2017-04-13 17:31:24 -04005584bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5585{
5586 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5587}
5588
5589bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5590{
5591 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5592}
5593
5594bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5595{
5596 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5597}
5598
5599bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5600{
5601 return ValidateUniform(context, GL_INT_VEC2, location, count);
5602}
5603
5604bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5605{
5606 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5607}
5608
5609bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5610{
5611 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5612}
5613
5614bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5615{
5616 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5617}
5618
5619bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5620{
5621 return ValidateUniform(context, GL_INT_VEC3, location, count);
5622}
5623
5624bool ValidateUniform4f(ValidationContext *context,
5625 GLint location,
5626 GLfloat x,
5627 GLfloat y,
5628 GLfloat z,
5629 GLfloat w)
5630{
5631 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5632}
5633
5634bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5635{
5636 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5637}
5638
5639bool ValidateUniform4i(ValidationContext *context,
5640 GLint location,
5641 GLint x,
5642 GLint y,
5643 GLint z,
5644 GLint w)
5645{
5646 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5647}
5648
5649bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5650{
5651 return ValidateUniform(context, GL_INT_VEC4, location, count);
5652}
5653
5654bool ValidateUniformMatrix2fv(ValidationContext *context,
5655 GLint location,
5656 GLsizei count,
5657 GLboolean transpose,
5658 const GLfloat *value)
5659{
5660 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5661}
5662
5663bool ValidateUniformMatrix3fv(ValidationContext *context,
5664 GLint location,
5665 GLsizei count,
5666 GLboolean transpose,
5667 const GLfloat *value)
5668{
5669 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5670}
5671
5672bool ValidateUniformMatrix4fv(ValidationContext *context,
5673 GLint location,
5674 GLsizei count,
5675 GLboolean transpose,
5676 const GLfloat *value)
5677{
5678 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5679}
5680
5681bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5682{
5683 Program *programObject = GetValidProgram(context, program);
5684
5685 if (!programObject)
5686 {
5687 return false;
5688 }
5689
5690 return true;
5691}
5692
Jamie Madillc1d770e2017-04-13 17:31:24 -04005693bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5694{
5695 return ValidateVertexAttribIndex(context, index);
5696}
5697
5698bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5699{
5700 return ValidateVertexAttribIndex(context, index);
5701}
5702
5703bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5704{
5705 return ValidateVertexAttribIndex(context, index);
5706}
5707
5708bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5709{
5710 return ValidateVertexAttribIndex(context, index);
5711}
5712
5713bool ValidateVertexAttrib3f(ValidationContext *context,
5714 GLuint index,
5715 GLfloat x,
5716 GLfloat y,
5717 GLfloat z)
5718{
5719 return ValidateVertexAttribIndex(context, index);
5720}
5721
5722bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5723{
5724 return ValidateVertexAttribIndex(context, index);
5725}
5726
5727bool ValidateVertexAttrib4f(ValidationContext *context,
5728 GLuint index,
5729 GLfloat x,
5730 GLfloat y,
5731 GLfloat z,
5732 GLfloat w)
5733{
5734 return ValidateVertexAttribIndex(context, index);
5735}
5736
5737bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5738{
5739 return ValidateVertexAttribIndex(context, index);
5740}
5741
5742bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5743{
5744 if (width < 0 || height < 0)
5745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005746 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005747 return false;
5748 }
5749
5750 return true;
5751}
5752
5753bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5754{
5755 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5756}
5757
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005758bool ValidateDrawElements(ValidationContext *context,
5759 GLenum mode,
5760 GLsizei count,
5761 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005762 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005763{
5764 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5765}
5766
Jamie Madillbe849e42017-05-02 15:49:00 -04005767bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5768 GLenum target,
5769 GLenum attachment,
5770 GLenum pname,
5771 GLint *params)
5772{
5773 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5774 nullptr);
5775}
5776
5777bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5778{
5779 return ValidateGetProgramivBase(context, program, pname, nullptr);
5780}
5781
5782bool ValidateCopyTexImage2D(ValidationContext *context,
5783 GLenum target,
5784 GLint level,
5785 GLenum internalformat,
5786 GLint x,
5787 GLint y,
5788 GLsizei width,
5789 GLsizei height,
5790 GLint border)
5791{
5792 if (context->getClientMajorVersion() < 3)
5793 {
5794 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5795 0, x, y, width, height, border);
5796 }
5797
5798 ASSERT(context->getClientMajorVersion() == 3);
5799 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5800 0, x, y, width, height, border);
5801}
5802
5803bool ValidateCopyTexSubImage2D(Context *context,
5804 GLenum target,
5805 GLint level,
5806 GLint xoffset,
5807 GLint yoffset,
5808 GLint x,
5809 GLint y,
5810 GLsizei width,
5811 GLsizei height)
5812{
5813 if (context->getClientMajorVersion() < 3)
5814 {
5815 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5816 yoffset, x, y, width, height, 0);
5817 }
5818
5819 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5820 yoffset, 0, x, y, width, height, 0);
5821}
5822
5823bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5824{
5825 return ValidateGenOrDelete(context, n);
5826}
5827
5828bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5829{
5830 return ValidateGenOrDelete(context, n);
5831}
5832
5833bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5834{
5835 return ValidateGenOrDelete(context, n);
5836}
5837
5838bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5839{
5840 return ValidateGenOrDelete(context, n);
5841}
5842
5843bool ValidateDisable(Context *context, GLenum cap)
5844{
5845 if (!ValidCap(context, cap, false))
5846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005847 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 return false;
5849 }
5850
5851 return true;
5852}
5853
5854bool ValidateEnable(Context *context, GLenum cap)
5855{
5856 if (!ValidCap(context, cap, false))
5857 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005858 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005859 return false;
5860 }
5861
5862 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5863 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5864 {
5865 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005866 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005867
5868 // We also output an error message to the debugger window if tracing is active, so that
5869 // developers can see the error message.
5870 ERR() << errorMessage;
5871 return false;
5872 }
5873
5874 return true;
5875}
5876
5877bool ValidateFramebufferRenderbuffer(Context *context,
5878 GLenum target,
5879 GLenum attachment,
5880 GLenum renderbuffertarget,
5881 GLuint renderbuffer)
5882{
Brandon Jones6cad5662017-06-14 13:25:13 -07005883 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005884 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5886 return false;
5887 }
5888
5889 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5890 {
5891 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005892 return false;
5893 }
5894
5895 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5896 renderbuffertarget, renderbuffer);
5897}
5898
5899bool ValidateFramebufferTexture2D(Context *context,
5900 GLenum target,
5901 GLenum attachment,
5902 GLenum textarget,
5903 GLuint texture,
5904 GLint level)
5905{
5906 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5907 // extension
5908 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5909 level != 0)
5910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005911 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005912 return false;
5913 }
5914
5915 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5916 {
5917 return false;
5918 }
5919
5920 if (texture != 0)
5921 {
5922 gl::Texture *tex = context->getTexture(texture);
5923 ASSERT(tex);
5924
5925 const gl::Caps &caps = context->getCaps();
5926
5927 switch (textarget)
5928 {
5929 case GL_TEXTURE_2D:
5930 {
5931 if (level > gl::log2(caps.max2DTextureSize))
5932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005933 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 return false;
5935 }
5936 if (tex->getTarget() != GL_TEXTURE_2D)
5937 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005938 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 return false;
5940 }
5941 }
5942 break;
5943
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005944 case GL_TEXTURE_RECTANGLE_ANGLE:
5945 {
5946 if (level != 0)
5947 {
5948 context->handleError(InvalidValue());
5949 return false;
5950 }
5951 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5952 {
5953 context->handleError(InvalidOperation()
5954 << "Textarget must match the texture target type.");
5955 return false;
5956 }
5957 }
5958 break;
5959
Jamie Madillbe849e42017-05-02 15:49:00 -04005960 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5961 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5962 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5963 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5964 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5966 {
5967 if (level > gl::log2(caps.maxCubeMapTextureSize))
5968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005969 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005970 return false;
5971 }
5972 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005974 context->handleError(InvalidOperation()
5975 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005976 return false;
5977 }
5978 }
5979 break;
5980
5981 case GL_TEXTURE_2D_MULTISAMPLE:
5982 {
5983 if (context->getClientVersion() < ES_3_1)
5984 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005986 return false;
5987 }
5988
5989 if (level != 0)
5990 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005991 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 return false;
5993 }
5994 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005996 context->handleError(InvalidOperation()
5997 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005998 return false;
5999 }
6000 }
6001 break;
6002
6003 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006004 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006005 return false;
6006 }
6007
6008 const Format &format = tex->getFormat(textarget, level);
6009 if (format.info->compressed)
6010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006011 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006012 return false;
6013 }
6014 }
6015
6016 return true;
6017}
6018
6019bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6020{
6021 return ValidateGenOrDelete(context, n);
6022}
6023
6024bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6025{
6026 return ValidateGenOrDelete(context, n);
6027}
6028
6029bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6030{
6031 return ValidateGenOrDelete(context, n);
6032}
6033
6034bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6035{
6036 return ValidateGenOrDelete(context, n);
6037}
6038
6039bool ValidateGenerateMipmap(Context *context, GLenum target)
6040{
6041 if (!ValidTextureTarget(context, target))
6042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006044 return false;
6045 }
6046
6047 Texture *texture = context->getTargetTexture(target);
6048
6049 if (texture == nullptr)
6050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006052 return false;
6053 }
6054
6055 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6056
6057 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6058 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6059 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006061 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006062 return false;
6063 }
6064
6065 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006066 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6067 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6068 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006069 {
6070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6071 return false;
6072 }
6073
Geoff Lang536eca12017-09-13 11:23:35 -04006074 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6075 bool formatUnsized = !format.sized;
6076 bool formatColorRenderableAndFilterable =
6077 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6078 format.renderSupport(context->getClientVersion(), context->getExtensions());
6079 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006080 {
Geoff Lang536eca12017-09-13 11:23:35 -04006081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006082 return false;
6083 }
6084
Geoff Lang536eca12017-09-13 11:23:35 -04006085 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6086 // generation
6087 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6088 {
6089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6090 return false;
6091 }
6092
6093 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6094 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006095 bool supportsSRGBMipmapGeneration =
6096 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006097 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006098 {
Geoff Lang536eca12017-09-13 11:23:35 -04006099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006100 return false;
6101 }
6102
6103 // Non-power of 2 ES2 check
6104 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6105 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6106 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6107 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006108 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6109 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006111 return false;
6112 }
6113
6114 // Cube completeness check
6115 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6116 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006118 return false;
6119 }
6120
6121 return true;
6122}
6123
6124bool ValidateGetBufferParameteriv(ValidationContext *context,
6125 GLenum target,
6126 GLenum pname,
6127 GLint *params)
6128{
6129 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6130}
6131
6132bool ValidateGetRenderbufferParameteriv(Context *context,
6133 GLenum target,
6134 GLenum pname,
6135 GLint *params)
6136{
6137 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6138}
6139
6140bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6141{
6142 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6143}
6144
6145bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6146{
6147 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6148}
6149
6150bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6151{
6152 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6153}
6154
6155bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6156{
6157 return ValidateGetUniformBase(context, program, location);
6158}
6159
6160bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6161{
6162 return ValidateGetUniformBase(context, program, location);
6163}
6164
6165bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6166{
6167 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6168}
6169
6170bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6171{
6172 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6173}
6174
6175bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6176{
6177 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6178}
6179
6180bool ValidateIsEnabled(Context *context, GLenum cap)
6181{
6182 if (!ValidCap(context, cap, true))
6183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006185 return false;
6186 }
6187
6188 return true;
6189}
6190
6191bool ValidateLinkProgram(Context *context, GLuint program)
6192{
6193 if (context->hasActiveTransformFeedback(program))
6194 {
6195 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006196 context->handleError(InvalidOperation() << "Cannot link program while program is "
6197 "associated with an active transform "
6198 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006199 return false;
6200 }
6201
6202 Program *programObject = GetValidProgram(context, program);
6203 if (!programObject)
6204 {
6205 return false;
6206 }
6207
6208 return true;
6209}
6210
Jamie Madill4928b7c2017-06-20 12:57:39 -04006211bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006212 GLint x,
6213 GLint y,
6214 GLsizei width,
6215 GLsizei height,
6216 GLenum format,
6217 GLenum type,
6218 void *pixels)
6219{
6220 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6221 nullptr, pixels);
6222}
6223
6224bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6225{
6226 return ValidateTexParameterBase(context, target, pname, -1, &param);
6227}
6228
6229bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6230{
6231 return ValidateTexParameterBase(context, target, pname, -1, params);
6232}
6233
6234bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6235{
6236 return ValidateTexParameterBase(context, target, pname, -1, &param);
6237}
6238
6239bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6240{
6241 return ValidateTexParameterBase(context, target, pname, -1, params);
6242}
6243
6244bool ValidateUseProgram(Context *context, GLuint program)
6245{
6246 if (program != 0)
6247 {
6248 Program *programObject = context->getProgram(program);
6249 if (!programObject)
6250 {
6251 // ES 3.1.0 section 7.3 page 72
6252 if (context->getShader(program))
6253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006255 return false;
6256 }
6257 else
6258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006259 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006260 return false;
6261 }
6262 }
6263 if (!programObject->isLinked())
6264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006266 return false;
6267 }
6268 }
6269 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6270 {
6271 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006272 context
6273 ->handleError(InvalidOperation()
6274 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006275 return false;
6276 }
6277
6278 return true;
6279}
6280
Jamie Madillc29968b2016-01-20 11:17:23 -05006281} // namespace gl