blob: 13e65d20c49d3090e055cd28184ad7e3038c4adf [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:
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -0700922 // Line-continuation characters may not be permitted.
923 // Otherwise, just pass it through. Do not parse comments in this state.
924 if (!lineContinuationAllowed && c == '\\')
925 {
926 return false;
927 }
Geoff Langcab92ee2017-07-19 17:32:07 -0400928 pos++;
929 break;
930
931 case ParseState::IN_SINGLE_LINE_COMMENT:
932 // Line-continuation characters are processed before comment processing.
933 // Advance string if a new line character is immediately behind
934 // line-continuation character.
935 if (c == '\\' && (next == '\n' || next == '\r'))
936 {
937 pos++;
938 }
939 pos++;
940 break;
941
942 case ParseState::IN_MULTI_LINE_COMMENT:
943 if (c == '*' && next == '/')
944 {
945 state = ParseState::MIDDLE_OF_LINE;
946 pos++;
947 }
948 pos++;
949 break;
950 }
951 }
952
953 return true;
954}
955
Brandon Jonesed5b46f2017-07-21 08:39:17 -0700956bool ValidateWebGLNamePrefix(ValidationContext *context, const GLchar *name)
957{
958 ASSERT(context->isWebGL());
959
960 // WebGL 1.0 [Section 6.16] GLSL Constructs
961 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
962 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
963 {
964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), WebglBindAttribLocationReservedPrefix);
965 return false;
966 }
967
968 return true;
969}
970
971bool ValidateWebGLNameLength(ValidationContext *context, size_t length)
972{
973 ASSERT(context->isWebGL());
974
975 if (context->isWebGL1() && length > 256)
976 {
977 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
978 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
979 // locations.
980 ANGLE_VALIDATION_ERR(context, InvalidValue(), WebglNameLengthLimitExceeded);
981
982 return false;
983 }
984 else if (length > 1024)
985 {
986 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
987 // uniform and attribute locations.
988 ANGLE_VALIDATION_ERR(context, InvalidValue(), Webgl2NameLengthLimitExceeded);
989 return false;
990 }
991
992 return true;
993}
994
Jamie Madillc29968b2016-01-20 11:17:23 -0500995} // anonymous namespace
996
Geoff Langff5b2d52016-09-07 11:32:23 -0400997bool ValidateES2TexImageParameters(Context *context,
998 GLenum target,
999 GLint level,
1000 GLenum internalformat,
1001 bool isCompressed,
1002 bool isSubImage,
1003 GLint xoffset,
1004 GLint yoffset,
1005 GLsizei width,
1006 GLsizei height,
1007 GLint border,
1008 GLenum format,
1009 GLenum type,
1010 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001011 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012{
Jamie Madill6f38f822014-06-06 17:12:20 -04001013 if (!ValidTexture2DDestinationTarget(context, target))
1014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001017 }
1018
Austin Kinross08528e12015-10-07 16:24:40 -07001019 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001021 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024
Brandon Jones6cad5662017-06-14 13:25:13 -07001025 if (!ValidMipLevel(context, target, level))
1026 {
1027 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
1028 return false;
1029 }
1030
1031 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 std::numeric_limits<GLsizei>::max() - yoffset < height)
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
1037
Geoff Lang6e898aa2017-06-02 11:17:26 -04001038 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1039 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1040 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1041 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1042 // case.
1043 bool nonEqualFormatsAllowed =
1044 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
1045 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
1046
1047 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001049 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052
Geoff Langaae65a42014-05-26 12:43:44 -04001053 const gl::Caps &caps = context->getCaps();
1054
Geoff Langa9be0dc2014-12-17 12:34:40 -05001055 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001057 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
1058 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001060 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001061 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001063 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001064 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
1065 {
1066 ASSERT(level == 0);
1067 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1068 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
1069 {
1070 context->handleError(InvalidValue());
1071 return false;
1072 }
1073 if (isCompressed)
1074 {
1075 context->handleError(InvalidEnum()
1076 << "Rectangle texture cannot have a compressed format.");
1077 return false;
1078 }
1079 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001080 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001081 {
1082 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001084 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001085 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087
Geoff Langa9be0dc2014-12-17 12:34:40 -05001088 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1089 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001091 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001092 return false;
1093 }
1094 }
1095 else
1096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001097 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001098 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 }
1100
He Yunchaoced53ae2016-11-29 15:00:51 +08001101 gl::Texture *texture =
1102 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 if (!texture)
1104 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
Geoff Langa9be0dc2014-12-17 12:34:40 -05001109 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 {
Geoff Langca271392017-04-05 12:30:00 -04001111 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1112 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001114 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001115 return false;
1116 }
1117
Geoff Langa9be0dc2014-12-17 12:34:40 -05001118 if (format != GL_NONE)
1119 {
Geoff Langca271392017-04-05 12:30:00 -04001120 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1121 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001124 return false;
1125 }
1126 }
1127
1128 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1129 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001131 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001132 return false;
1133 }
1134 }
1135 else
1136 {
Geoff Lang69cce582015-09-17 13:20:36 -04001137 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001139 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001140 return false;
1141 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 }
1143
1144 // Verify zero border
1145 if (border != 0)
1146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001147 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 if (isCompressed)
1152 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001153 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001154 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1155 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 switch (actualInternalFormat)
1157 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001158 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1160 if (!context->getExtensions().textureCompressionDXT1)
1161 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001162 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 return false;
1164 }
1165 break;
1166 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1167 if (!context->getExtensions().textureCompressionDXT1)
1168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001169 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001170 return false;
1171 }
1172 break;
1173 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1174 if (!context->getExtensions().textureCompressionDXT5)
1175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 return false;
1178 }
1179 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001180 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1181 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1182 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1183 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1184 if (!context->getExtensions().textureCompressionS3TCsRGB)
1185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001187 return false;
1188 }
1189 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 case GL_ETC1_RGB8_OES:
1191 if (!context->getExtensions().compressedETC1RGB8Texture)
1192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 return false;
1195 }
1196 break;
1197 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001198 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1199 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1200 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1201 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 if (!context->getExtensions().lossyETCDecode)
1203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001204 context->handleError(InvalidEnum()
1205 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
1207 }
1208 break;
1209 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001211 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001212 }
Geoff Lang966c9402017-04-18 12:38:27 -04001213
1214 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001215 {
Geoff Lang966c9402017-04-18 12:38:27 -04001216 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1217 height, texture->getWidth(target, level),
1218 texture->getHeight(target, level)))
1219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001221 return false;
1222 }
1223
1224 if (format != actualInternalFormat)
1225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001227 return false;
1228 }
1229 }
1230 else
1231 {
1232 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001235 return false;
1236 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237 }
1238 }
1239 else
1240 {
1241 // validate <type> by itself (used as secondary key below)
1242 switch (type)
1243 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001244 case GL_UNSIGNED_BYTE:
1245 case GL_UNSIGNED_SHORT_5_6_5:
1246 case GL_UNSIGNED_SHORT_4_4_4_4:
1247 case GL_UNSIGNED_SHORT_5_5_5_1:
1248 case GL_UNSIGNED_SHORT:
1249 case GL_UNSIGNED_INT:
1250 case GL_UNSIGNED_INT_24_8_OES:
1251 case GL_HALF_FLOAT_OES:
1252 case GL_FLOAT:
1253 break;
1254 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
1259 // validate <format> + <type> combinations
1260 // - invalid <format> -> sets INVALID_ENUM
1261 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1262 switch (format)
1263 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001264 case GL_ALPHA:
1265 case GL_LUMINANCE:
1266 case GL_LUMINANCE_ALPHA:
1267 switch (type)
1268 {
1269 case GL_UNSIGNED_BYTE:
1270 case GL_FLOAT:
1271 case GL_HALF_FLOAT_OES:
1272 break;
1273 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001274 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001275 return false;
1276 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001278 case GL_RED:
1279 case GL_RG:
1280 if (!context->getExtensions().textureRG)
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001283 return false;
1284 }
1285 switch (type)
1286 {
1287 case GL_UNSIGNED_BYTE:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001288 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001289 case GL_FLOAT:
1290 case GL_HALF_FLOAT_OES:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001291 if (!context->getExtensions().textureFloat)
1292 {
1293 context->handleError(InvalidEnum());
1294 return false;
1295 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001296 break;
1297 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001298 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001299 return false;
1300 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001302 case GL_RGB:
1303 switch (type)
1304 {
1305 case GL_UNSIGNED_BYTE:
1306 case GL_UNSIGNED_SHORT_5_6_5:
1307 case GL_FLOAT:
1308 case GL_HALF_FLOAT_OES:
1309 break;
1310 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001312 return false;
1313 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001315 case GL_RGBA:
1316 switch (type)
1317 {
1318 case GL_UNSIGNED_BYTE:
1319 case GL_UNSIGNED_SHORT_4_4_4_4:
1320 case GL_UNSIGNED_SHORT_5_5_5_1:
1321 case GL_FLOAT:
1322 case GL_HALF_FLOAT_OES:
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 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001329 case GL_BGRA_EXT:
Bryan Bernhart (Intel Americas Inc)2a357412017-09-05 10:42:47 -07001330 if (!context->getExtensions().textureFormatBGRA8888)
1331 {
1332 context->handleError(InvalidEnum());
1333 return false;
1334 }
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 switch (type)
1336 {
1337 case GL_UNSIGNED_BYTE:
1338 break;
1339 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001340 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 return false;
1342 }
1343 break;
1344 case GL_SRGB_EXT:
1345 case GL_SRGB_ALPHA_EXT:
1346 if (!context->getExtensions().sRGB)
1347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001349 return false;
1350 }
1351 switch (type)
1352 {
1353 case GL_UNSIGNED_BYTE:
1354 break;
1355 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001357 return false;
1358 }
1359 break;
1360 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1361 // handled below
1362 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1363 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1364 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1365 break;
1366 case GL_DEPTH_COMPONENT:
1367 switch (type)
1368 {
1369 case GL_UNSIGNED_SHORT:
1370 case GL_UNSIGNED_INT:
1371 break;
1372 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001373 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001374 return false;
1375 }
1376 break;
1377 case GL_DEPTH_STENCIL_OES:
1378 switch (type)
1379 {
1380 case GL_UNSIGNED_INT_24_8_OES:
1381 break;
1382 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001383 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001384 return false;
1385 }
1386 break;
1387 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001388 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
1391
1392 switch (format)
1393 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001394 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1395 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1396 if (context->getExtensions().textureCompressionDXT1)
1397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001398 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001399 return false;
1400 }
1401 else
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 return false;
1405 }
1406 break;
1407 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1408 if (context->getExtensions().textureCompressionDXT3)
1409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001410 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001411 return false;
1412 }
1413 else
1414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001416 return false;
1417 }
1418 break;
1419 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1420 if (context->getExtensions().textureCompressionDXT5)
1421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001422 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001423 return false;
1424 }
1425 else
1426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001428 return false;
1429 }
1430 break;
1431 case GL_ETC1_RGB8_OES:
1432 if (context->getExtensions().compressedETC1RGB8Texture)
1433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001435 return false;
1436 }
1437 else
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001440 return false;
1441 }
1442 break;
1443 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001444 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1445 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1446 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1447 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 if (context->getExtensions().lossyETCDecode)
1449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001450 context->handleError(InvalidOperation()
1451 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001452 return false;
1453 }
1454 else
1455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001456 context->handleError(InvalidEnum()
1457 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001458 return false;
1459 }
1460 break;
1461 case GL_DEPTH_COMPONENT:
1462 case GL_DEPTH_STENCIL_OES:
1463 if (!context->getExtensions().depthTextures)
1464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001465 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001466 return false;
1467 }
1468 if (target != GL_TEXTURE_2D)
1469 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001471 return false;
1472 }
1473 // OES_depth_texture supports loading depth data and multiple levels,
1474 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001475 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1478 return false;
1479 }
1480 if (level != 0)
1481 {
1482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001483 return false;
1484 }
1485 break;
1486 default:
1487 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001488 }
1489
Geoff Lang6e898aa2017-06-02 11:17:26 -04001490 if (!isSubImage)
1491 {
1492 switch (internalformat)
1493 {
1494 case GL_RGBA32F:
1495 if (!context->getExtensions().colorBufferFloatRGBA)
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidValue()
1498 << "Sized GL_RGBA32F internal format requires "
1499 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001500 return false;
1501 }
1502 if (type != GL_FLOAT)
1503 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001504 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001505 return false;
1506 }
1507 if (format != GL_RGBA)
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 break;
1513
1514 case GL_RGB32F:
1515 if (!context->getExtensions().colorBufferFloatRGB)
1516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidValue()
1518 << "Sized GL_RGB32F internal format requires "
1519 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001520 return false;
1521 }
1522 if (type != GL_FLOAT)
1523 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001525 return false;
1526 }
1527 if (format != GL_RGB)
1528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001530 return false;
1531 }
1532 break;
1533
1534 default:
1535 break;
1536 }
1537 }
1538
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 if (type == GL_FLOAT)
1540 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001541 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001543 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001544 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545 }
1546 }
1547 else if (type == GL_HALF_FLOAT_OES)
1548 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001549 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001552 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001553 }
1554 }
1555 }
1556
Geoff Langdbcced82017-06-06 15:55:54 -04001557 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1558 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001559 imageSize))
1560 {
1561 return false;
1562 }
1563
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001564 return true;
1565}
1566
He Yunchaoced53ae2016-11-29 15:00:51 +08001567bool ValidateES2TexStorageParameters(Context *context,
1568 GLenum target,
1569 GLsizei levels,
1570 GLenum internalformat,
1571 GLsizei width,
1572 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001573{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001574 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1575 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001577 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001579 }
1580
1581 if (width < 1 || height < 1 || levels < 1)
1582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001583 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001584 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001585 }
1586
1587 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001589 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001590 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001591 }
1592
1593 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001595 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001596 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001597 }
1598
Geoff Langca271392017-04-05 12:30:00 -04001599 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001600 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001602 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001603 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001604 }
1605
Geoff Langaae65a42014-05-26 12:43:44 -04001606 const gl::Caps &caps = context->getCaps();
1607
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001608 switch (target)
1609 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001610 case GL_TEXTURE_2D:
1611 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1612 static_cast<GLuint>(height) > caps.max2DTextureSize)
1613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001614 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001615 return false;
1616 }
1617 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001618 case GL_TEXTURE_RECTANGLE_ANGLE:
1619 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1620 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1621 {
1622 context->handleError(InvalidValue());
1623 return false;
1624 }
1625 if (formatInfo.compressed)
1626 {
1627 context->handleError(InvalidEnum()
1628 << "Rectangle texture cannot have a compressed format.");
1629 return false;
1630 }
1631 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001632 case GL_TEXTURE_CUBE_MAP:
1633 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1634 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001636 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001637 return false;
1638 }
1639 break;
1640 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001642 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001643 }
1644
Geoff Langc0b9ef42014-07-02 10:02:37 -04001645 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001646 {
1647 if (!gl::isPow2(width) || !gl::isPow2(height))
1648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001649 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001650 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651 }
1652 }
1653
1654 switch (internalformat)
1655 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001656 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1657 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1658 if (!context->getExtensions().textureCompressionDXT1)
1659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001661 return false;
1662 }
1663 break;
1664 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1665 if (!context->getExtensions().textureCompressionDXT3)
1666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001667 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001668 return false;
1669 }
1670 break;
1671 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1672 if (!context->getExtensions().textureCompressionDXT5)
1673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001674 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001675 return false;
1676 }
1677 break;
1678 case GL_ETC1_RGB8_OES:
1679 if (!context->getExtensions().compressedETC1RGB8Texture)
1680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001681 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001682 return false;
1683 }
1684 break;
1685 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001686 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1687 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1688 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1689 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001690 if (!context->getExtensions().lossyETCDecode)
1691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001692 context->handleError(InvalidEnum()
1693 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001694 return false;
1695 }
1696 break;
1697 case GL_RGBA32F_EXT:
1698 case GL_RGB32F_EXT:
1699 case GL_ALPHA32F_EXT:
1700 case GL_LUMINANCE32F_EXT:
1701 case GL_LUMINANCE_ALPHA32F_EXT:
1702 if (!context->getExtensions().textureFloat)
1703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001704 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001705 return false;
1706 }
1707 break;
1708 case GL_RGBA16F_EXT:
1709 case GL_RGB16F_EXT:
1710 case GL_ALPHA16F_EXT:
1711 case GL_LUMINANCE16F_EXT:
1712 case GL_LUMINANCE_ALPHA16F_EXT:
1713 if (!context->getExtensions().textureHalfFloat)
1714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001716 return false;
1717 }
1718 break;
1719 case GL_R8_EXT:
1720 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001721 if (!context->getExtensions().textureRG)
1722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001724 return false;
1725 }
1726 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001727 case GL_R16F_EXT:
1728 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001729 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001732 return false;
1733 }
1734 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001735 case GL_R32F_EXT:
1736 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001737 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001739 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001740 return false;
1741 }
1742 break;
1743 case GL_DEPTH_COMPONENT16:
1744 case GL_DEPTH_COMPONENT32_OES:
1745 case GL_DEPTH24_STENCIL8_OES:
1746 if (!context->getExtensions().depthTextures)
1747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001749 return false;
1750 }
1751 if (target != GL_TEXTURE_2D)
1752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001753 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001754 return false;
1755 }
1756 // ANGLE_depth_texture only supports 1-level textures
1757 if (levels != 1)
1758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001759 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001760 return false;
1761 }
1762 break;
1763 default:
1764 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001765 }
1766
Geoff Lang691e58c2014-12-19 17:03:25 -05001767 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001768 if (!texture || texture->id() == 0)
1769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001770 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001771 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001772 }
1773
Geoff Lang69cce582015-09-17 13:20:36 -04001774 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001776 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001777 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001778 }
1779
1780 return true;
1781}
1782
He Yunchaoced53ae2016-11-29 15:00:51 +08001783bool ValidateDiscardFramebufferEXT(Context *context,
1784 GLenum target,
1785 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001786 const GLenum *attachments)
1787{
Jamie Madillc29968b2016-01-20 11:17:23 -05001788 if (!context->getExtensions().discardFramebuffer)
1789 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001790 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001791 return false;
1792 }
1793
Austin Kinross08332632015-05-05 13:35:47 -07001794 bool defaultFramebuffer = false;
1795
1796 switch (target)
1797 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001798 case GL_FRAMEBUFFER:
1799 defaultFramebuffer =
1800 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1801 break;
1802 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001804 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001805 }
1806
He Yunchaoced53ae2016-11-29 15:00:51 +08001807 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1808 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001809}
1810
Austin Kinrossbc781f32015-10-26 09:27:38 -07001811bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1812{
1813 if (!context->getExtensions().vertexArrayObject)
1814 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001815 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001816 return false;
1817 }
1818
1819 return ValidateBindVertexArrayBase(context, array);
1820}
1821
Jamie Madilld7576732017-08-26 18:49:50 -04001822bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001823{
1824 if (!context->getExtensions().vertexArrayObject)
1825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001827 return false;
1828 }
1829
Olli Etuaho41997e72016-03-10 13:38:39 +02001830 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001831}
1832
Jamie Madilld7576732017-08-26 18:49:50 -04001833bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001834{
1835 if (!context->getExtensions().vertexArrayObject)
1836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001838 return false;
1839 }
1840
Olli Etuaho41997e72016-03-10 13:38:39 +02001841 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001842}
1843
Jamie Madilld7576732017-08-26 18:49:50 -04001844bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001845{
1846 if (!context->getExtensions().vertexArrayObject)
1847 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001849 return false;
1850 }
1851
1852 return true;
1853}
Geoff Langc5629752015-12-07 16:29:04 -05001854
1855bool ValidateProgramBinaryOES(Context *context,
1856 GLuint program,
1857 GLenum binaryFormat,
1858 const void *binary,
1859 GLint length)
1860{
1861 if (!context->getExtensions().getProgramBinary)
1862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001864 return false;
1865 }
1866
1867 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1868}
1869
1870bool ValidateGetProgramBinaryOES(Context *context,
1871 GLuint program,
1872 GLsizei bufSize,
1873 GLsizei *length,
1874 GLenum *binaryFormat,
1875 void *binary)
1876{
1877 if (!context->getExtensions().getProgramBinary)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001880 return false;
1881 }
1882
1883 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1884}
Geoff Lange102fee2015-12-10 11:23:30 -05001885
Geoff Lang70d0f492015-12-10 17:45:46 -05001886static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1887{
1888 switch (source)
1889 {
1890 case GL_DEBUG_SOURCE_API:
1891 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1892 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1893 case GL_DEBUG_SOURCE_OTHER:
1894 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1895 return !mustBeThirdPartyOrApplication;
1896
1897 case GL_DEBUG_SOURCE_THIRD_PARTY:
1898 case GL_DEBUG_SOURCE_APPLICATION:
1899 return true;
1900
1901 default:
1902 return false;
1903 }
1904}
1905
1906static bool ValidDebugType(GLenum type)
1907{
1908 switch (type)
1909 {
1910 case GL_DEBUG_TYPE_ERROR:
1911 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1912 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1913 case GL_DEBUG_TYPE_PERFORMANCE:
1914 case GL_DEBUG_TYPE_PORTABILITY:
1915 case GL_DEBUG_TYPE_OTHER:
1916 case GL_DEBUG_TYPE_MARKER:
1917 case GL_DEBUG_TYPE_PUSH_GROUP:
1918 case GL_DEBUG_TYPE_POP_GROUP:
1919 return true;
1920
1921 default:
1922 return false;
1923 }
1924}
1925
1926static bool ValidDebugSeverity(GLenum severity)
1927{
1928 switch (severity)
1929 {
1930 case GL_DEBUG_SEVERITY_HIGH:
1931 case GL_DEBUG_SEVERITY_MEDIUM:
1932 case GL_DEBUG_SEVERITY_LOW:
1933 case GL_DEBUG_SEVERITY_NOTIFICATION:
1934 return true;
1935
1936 default:
1937 return false;
1938 }
1939}
1940
Geoff Lange102fee2015-12-10 11:23:30 -05001941bool ValidateDebugMessageControlKHR(Context *context,
1942 GLenum source,
1943 GLenum type,
1944 GLenum severity,
1945 GLsizei count,
1946 const GLuint *ids,
1947 GLboolean enabled)
1948{
1949 if (!context->getExtensions().debug)
1950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001952 return false;
1953 }
1954
Geoff Lang70d0f492015-12-10 17:45:46 -05001955 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1956 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001958 return false;
1959 }
1960
1961 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1962 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001963 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001964 return false;
1965 }
1966
1967 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1968 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001970 return false;
1971 }
1972
1973 if (count > 0)
1974 {
1975 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001977 context->handleError(
1978 InvalidOperation()
1979 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001980 return false;
1981 }
1982
1983 if (severity != GL_DONT_CARE)
1984 {
Jamie Madill437fa652016-05-03 15:13:24 -04001985 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001986 InvalidOperation()
1987 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001988 return false;
1989 }
1990 }
1991
Geoff Lange102fee2015-12-10 11:23:30 -05001992 return true;
1993}
1994
1995bool ValidateDebugMessageInsertKHR(Context *context,
1996 GLenum source,
1997 GLenum type,
1998 GLuint id,
1999 GLenum severity,
2000 GLsizei length,
2001 const GLchar *buf)
2002{
2003 if (!context->getExtensions().debug)
2004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002006 return false;
2007 }
2008
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002009 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05002010 {
2011 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2012 // not generate an error.
2013 return false;
2014 }
2015
2016 if (!ValidDebugSeverity(severity))
2017 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002018 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002019 return false;
2020 }
2021
2022 if (!ValidDebugType(type))
2023 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002024 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05002025 return false;
2026 }
2027
2028 if (!ValidDebugSource(source, true))
2029 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002031 return false;
2032 }
2033
2034 size_t messageLength = (length < 0) ? strlen(buf) : length;
2035 if (messageLength > context->getExtensions().maxDebugMessageLength)
2036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002037 context->handleError(InvalidValue()
2038 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002039 return false;
2040 }
2041
Geoff Lange102fee2015-12-10 11:23:30 -05002042 return true;
2043}
2044
2045bool ValidateDebugMessageCallbackKHR(Context *context,
2046 GLDEBUGPROCKHR callback,
2047 const void *userParam)
2048{
2049 if (!context->getExtensions().debug)
2050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002052 return false;
2053 }
2054
Geoff Lange102fee2015-12-10 11:23:30 -05002055 return true;
2056}
2057
2058bool ValidateGetDebugMessageLogKHR(Context *context,
2059 GLuint count,
2060 GLsizei bufSize,
2061 GLenum *sources,
2062 GLenum *types,
2063 GLuint *ids,
2064 GLenum *severities,
2065 GLsizei *lengths,
2066 GLchar *messageLog)
2067{
2068 if (!context->getExtensions().debug)
2069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002071 return false;
2072 }
2073
Geoff Lang70d0f492015-12-10 17:45:46 -05002074 if (bufSize < 0 && messageLog != nullptr)
2075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002076 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002077 return false;
2078 }
2079
Geoff Lange102fee2015-12-10 11:23:30 -05002080 return true;
2081}
2082
2083bool ValidatePushDebugGroupKHR(Context *context,
2084 GLenum source,
2085 GLuint id,
2086 GLsizei length,
2087 const GLchar *message)
2088{
2089 if (!context->getExtensions().debug)
2090 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002092 return false;
2093 }
2094
Geoff Lang70d0f492015-12-10 17:45:46 -05002095 if (!ValidDebugSource(source, true))
2096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002098 return false;
2099 }
2100
2101 size_t messageLength = (length < 0) ? strlen(message) : length;
2102 if (messageLength > context->getExtensions().maxDebugMessageLength)
2103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002104 context->handleError(InvalidValue()
2105 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002106 return false;
2107 }
2108
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002109 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002110 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context
2113 ->handleError(StackOverflow()
2114 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002115 return false;
2116 }
2117
Geoff Lange102fee2015-12-10 11:23:30 -05002118 return true;
2119}
2120
2121bool ValidatePopDebugGroupKHR(Context *context)
2122{
2123 if (!context->getExtensions().debug)
2124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002126 return false;
2127 }
2128
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002129 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002130 if (currentStackSize <= 1)
2131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002132 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002133 return false;
2134 }
2135
2136 return true;
2137}
2138
2139static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2140{
2141 switch (identifier)
2142 {
2143 case GL_BUFFER:
2144 if (context->getBuffer(name) == nullptr)
2145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002147 return false;
2148 }
2149 return true;
2150
2151 case GL_SHADER:
2152 if (context->getShader(name) == nullptr)
2153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002154 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002155 return false;
2156 }
2157 return true;
2158
2159 case GL_PROGRAM:
2160 if (context->getProgram(name) == nullptr)
2161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002162 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002163 return false;
2164 }
2165 return true;
2166
2167 case GL_VERTEX_ARRAY:
2168 if (context->getVertexArray(name) == nullptr)
2169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002170 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002171 return false;
2172 }
2173 return true;
2174
2175 case GL_QUERY:
2176 if (context->getQuery(name) == nullptr)
2177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002178 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002179 return false;
2180 }
2181 return true;
2182
2183 case GL_TRANSFORM_FEEDBACK:
2184 if (context->getTransformFeedback(name) == nullptr)
2185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002186 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002187 return false;
2188 }
2189 return true;
2190
2191 case GL_SAMPLER:
2192 if (context->getSampler(name) == nullptr)
2193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002194 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002195 return false;
2196 }
2197 return true;
2198
2199 case GL_TEXTURE:
2200 if (context->getTexture(name) == nullptr)
2201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002202 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002203 return false;
2204 }
2205 return true;
2206
2207 case GL_RENDERBUFFER:
2208 if (context->getRenderbuffer(name) == nullptr)
2209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002211 return false;
2212 }
2213 return true;
2214
2215 case GL_FRAMEBUFFER:
2216 if (context->getFramebuffer(name) == nullptr)
2217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002218 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002219 return false;
2220 }
2221 return true;
2222
2223 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002224 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002225 return false;
2226 }
Geoff Lange102fee2015-12-10 11:23:30 -05002227}
2228
Martin Radev9d901792016-07-15 15:58:58 +03002229static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2230{
2231 size_t labelLength = 0;
2232
2233 if (length < 0)
2234 {
2235 if (label != nullptr)
2236 {
2237 labelLength = strlen(label);
2238 }
2239 }
2240 else
2241 {
2242 labelLength = static_cast<size_t>(length);
2243 }
2244
2245 if (labelLength > context->getExtensions().maxLabelLength)
2246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002247 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002248 return false;
2249 }
2250
2251 return true;
2252}
2253
Geoff Lange102fee2015-12-10 11:23:30 -05002254bool ValidateObjectLabelKHR(Context *context,
2255 GLenum identifier,
2256 GLuint name,
2257 GLsizei length,
2258 const GLchar *label)
2259{
2260 if (!context->getExtensions().debug)
2261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002263 return false;
2264 }
2265
Geoff Lang70d0f492015-12-10 17:45:46 -05002266 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2267 {
2268 return false;
2269 }
2270
Martin Radev9d901792016-07-15 15:58:58 +03002271 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002272 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002273 return false;
2274 }
2275
Geoff Lange102fee2015-12-10 11:23:30 -05002276 return true;
2277}
2278
2279bool ValidateGetObjectLabelKHR(Context *context,
2280 GLenum identifier,
2281 GLuint name,
2282 GLsizei bufSize,
2283 GLsizei *length,
2284 GLchar *label)
2285{
2286 if (!context->getExtensions().debug)
2287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002289 return false;
2290 }
2291
Geoff Lang70d0f492015-12-10 17:45:46 -05002292 if (bufSize < 0)
2293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002294 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002295 return false;
2296 }
2297
2298 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2299 {
2300 return false;
2301 }
2302
Martin Radev9d901792016-07-15 15:58:58 +03002303 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002304}
2305
2306static bool ValidateObjectPtrName(Context *context, const void *ptr)
2307{
Jamie Madill70b5bb02017-08-28 13:32:37 -04002308 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
Geoff Lang70d0f492015-12-10 17:45:46 -05002309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002310 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002311 return false;
2312 }
2313
Geoff Lange102fee2015-12-10 11:23:30 -05002314 return true;
2315}
2316
2317bool ValidateObjectPtrLabelKHR(Context *context,
2318 const void *ptr,
2319 GLsizei length,
2320 const GLchar *label)
2321{
2322 if (!context->getExtensions().debug)
2323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002325 return false;
2326 }
2327
Geoff Lang70d0f492015-12-10 17:45:46 -05002328 if (!ValidateObjectPtrName(context, ptr))
2329 {
2330 return false;
2331 }
2332
Martin Radev9d901792016-07-15 15:58:58 +03002333 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002334 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002335 return false;
2336 }
2337
Geoff Lange102fee2015-12-10 11:23:30 -05002338 return true;
2339}
2340
2341bool ValidateGetObjectPtrLabelKHR(Context *context,
2342 const void *ptr,
2343 GLsizei bufSize,
2344 GLsizei *length,
2345 GLchar *label)
2346{
2347 if (!context->getExtensions().debug)
2348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002349 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002350 return false;
2351 }
2352
Geoff Lang70d0f492015-12-10 17:45:46 -05002353 if (bufSize < 0)
2354 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002355 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002356 return false;
2357 }
2358
2359 if (!ValidateObjectPtrName(context, ptr))
2360 {
2361 return false;
2362 }
2363
Martin Radev9d901792016-07-15 15:58:58 +03002364 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002365}
2366
2367bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2368{
2369 if (!context->getExtensions().debug)
2370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002372 return false;
2373 }
2374
Geoff Lang70d0f492015-12-10 17:45:46 -05002375 // TODO: represent this in Context::getQueryParameterInfo.
2376 switch (pname)
2377 {
2378 case GL_DEBUG_CALLBACK_FUNCTION:
2379 case GL_DEBUG_CALLBACK_USER_PARAM:
2380 break;
2381
2382 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002383 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002384 return false;
2385 }
2386
Geoff Lange102fee2015-12-10 11:23:30 -05002387 return true;
2388}
Jamie Madillc29968b2016-01-20 11:17:23 -05002389
2390bool ValidateBlitFramebufferANGLE(Context *context,
2391 GLint srcX0,
2392 GLint srcY0,
2393 GLint srcX1,
2394 GLint srcY1,
2395 GLint dstX0,
2396 GLint dstY0,
2397 GLint dstX1,
2398 GLint dstY1,
2399 GLbitfield mask,
2400 GLenum filter)
2401{
2402 if (!context->getExtensions().framebufferBlit)
2403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002404 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002405 return false;
2406 }
2407
2408 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2409 {
2410 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002411 context->handleError(InvalidOperation() << "Scaling and flipping in "
2412 "BlitFramebufferANGLE not supported by this "
2413 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002414 return false;
2415 }
2416
2417 if (filter == GL_LINEAR)
2418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002419 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002420 return false;
2421 }
2422
Jamie Madill51f40ec2016-06-15 14:06:00 -04002423 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2424 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002425
2426 if (mask & GL_COLOR_BUFFER_BIT)
2427 {
2428 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2429 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2430
2431 if (readColorAttachment && drawColorAttachment)
2432 {
2433 if (!(readColorAttachment->type() == GL_TEXTURE &&
2434 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2435 readColorAttachment->type() != GL_RENDERBUFFER &&
2436 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002438 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002439 return false;
2440 }
2441
Geoff Langa15472a2015-08-11 11:48:03 -04002442 for (size_t drawbufferIdx = 0;
2443 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002444 {
Geoff Langa15472a2015-08-11 11:48:03 -04002445 const FramebufferAttachment *attachment =
2446 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2447 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002448 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002449 if (!(attachment->type() == GL_TEXTURE &&
2450 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2451 attachment->type() != GL_RENDERBUFFER &&
2452 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002454 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002455 return false;
2456 }
2457
2458 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002459 if (!Format::EquivalentForBlit(attachment->getFormat(),
2460 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002462 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002463 return false;
2464 }
2465 }
2466 }
2467
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002468 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002469 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2470 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002472 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002473 return false;
2474 }
2475 }
2476 }
2477
2478 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2479 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2480 for (size_t i = 0; i < 2; i++)
2481 {
2482 if (mask & masks[i])
2483 {
2484 const FramebufferAttachment *readBuffer =
2485 readFramebuffer->getAttachment(attachments[i]);
2486 const FramebufferAttachment *drawBuffer =
2487 drawFramebuffer->getAttachment(attachments[i]);
2488
2489 if (readBuffer && drawBuffer)
2490 {
2491 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2492 dstX0, dstY0, dstX1, dstY1))
2493 {
2494 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002495 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2496 "stencil blits are supported by "
2497 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002498 return false;
2499 }
2500
2501 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002503 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002504 return false;
2505 }
2506 }
2507 }
2508 }
2509
2510 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2511 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002512}
Jamie Madillc29968b2016-01-20 11:17:23 -05002513
2514bool ValidateClear(ValidationContext *context, GLbitfield mask)
2515{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002516 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002517 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002519 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002520 return false;
2521 }
2522
2523 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2524 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002525 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002526 return false;
2527 }
2528
Geoff Lang76e65652017-03-27 14:58:02 -04002529 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2530 {
2531 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2532 GL_SIGNED_NORMALIZED};
2533
Corentin Wallez59c41592017-07-11 13:19:54 -04002534 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002535 drawBufferIdx++)
2536 {
2537 if (!ValidateWebGLFramebufferAttachmentClearType(
2538 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2539 {
2540 return false;
2541 }
2542 }
2543 }
2544
Jamie Madillc29968b2016-01-20 11:17:23 -05002545 return true;
2546}
2547
2548bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2549{
2550 if (!context->getExtensions().drawBuffers)
2551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002552 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002553 return false;
2554 }
2555
2556 return ValidateDrawBuffersBase(context, n, bufs);
2557}
2558
Jamie Madill73a84962016-02-12 09:27:23 -05002559bool ValidateTexImage2D(Context *context,
2560 GLenum target,
2561 GLint level,
2562 GLint internalformat,
2563 GLsizei width,
2564 GLsizei height,
2565 GLint border,
2566 GLenum format,
2567 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002568 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002569{
Martin Radev1be913c2016-07-11 17:59:16 +03002570 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002571 {
2572 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002573 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002574 }
2575
Martin Radev1be913c2016-07-11 17:59:16 +03002576 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002577 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002578 0, 0, width, height, 1, border, format, type, -1,
2579 pixels);
2580}
2581
2582bool ValidateTexImage2DRobust(Context *context,
2583 GLenum target,
2584 GLint level,
2585 GLint internalformat,
2586 GLsizei width,
2587 GLsizei height,
2588 GLint border,
2589 GLenum format,
2590 GLenum type,
2591 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002592 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002593{
2594 if (!ValidateRobustEntryPoint(context, bufSize))
2595 {
2596 return false;
2597 }
2598
2599 if (context->getClientMajorVersion() < 3)
2600 {
2601 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2602 0, 0, width, height, border, format, type, bufSize,
2603 pixels);
2604 }
2605
2606 ASSERT(context->getClientMajorVersion() >= 3);
2607 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2608 0, 0, width, height, 1, border, format, type, bufSize,
2609 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002610}
2611
2612bool ValidateTexSubImage2D(Context *context,
2613 GLenum target,
2614 GLint level,
2615 GLint xoffset,
2616 GLint yoffset,
2617 GLsizei width,
2618 GLsizei height,
2619 GLenum format,
2620 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002621 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002622{
2623
Martin Radev1be913c2016-07-11 17:59:16 +03002624 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002625 {
2626 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002627 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002628 }
2629
Martin Radev1be913c2016-07-11 17:59:16 +03002630 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002631 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002632 yoffset, 0, width, height, 1, 0, format, type, -1,
2633 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002634}
2635
Geoff Langc52f6f12016-10-14 10:18:00 -04002636bool ValidateTexSubImage2DRobustANGLE(Context *context,
2637 GLenum target,
2638 GLint level,
2639 GLint xoffset,
2640 GLint yoffset,
2641 GLsizei width,
2642 GLsizei height,
2643 GLenum format,
2644 GLenum type,
2645 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002646 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002647{
2648 if (!ValidateRobustEntryPoint(context, bufSize))
2649 {
2650 return false;
2651 }
2652
2653 if (context->getClientMajorVersion() < 3)
2654 {
2655 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2656 yoffset, width, height, 0, format, type, bufSize,
2657 pixels);
2658 }
2659
2660 ASSERT(context->getClientMajorVersion() >= 3);
2661 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2662 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2663 pixels);
2664}
2665
Jamie Madill73a84962016-02-12 09:27:23 -05002666bool ValidateCompressedTexImage2D(Context *context,
2667 GLenum target,
2668 GLint level,
2669 GLenum internalformat,
2670 GLsizei width,
2671 GLsizei height,
2672 GLint border,
2673 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002674 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002675{
Martin Radev1be913c2016-07-11 17:59:16 +03002676 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002677 {
2678 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002679 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002680 {
2681 return false;
2682 }
2683 }
2684 else
2685 {
Martin Radev1be913c2016-07-11 17:59:16 +03002686 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002687 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002688 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002689 data))
2690 {
2691 return false;
2692 }
2693 }
2694
Geoff Langca271392017-04-05 12:30:00 -04002695 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002696 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002697 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002698 if (blockSizeOrErr.isError())
2699 {
2700 context->handleError(blockSizeOrErr.getError());
2701 return false;
2702 }
2703
2704 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002706 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002707 return false;
2708 }
2709
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002710 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2711 {
2712 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2713 return false;
2714 }
2715
Jamie Madill73a84962016-02-12 09:27:23 -05002716 return true;
2717}
2718
Corentin Wallezb2931602017-04-11 15:58:57 -04002719bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2720 GLenum target,
2721 GLint level,
2722 GLenum internalformat,
2723 GLsizei width,
2724 GLsizei height,
2725 GLint border,
2726 GLsizei imageSize,
2727 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002728 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002729{
2730 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2731 {
2732 return false;
2733 }
2734
2735 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2736 border, imageSize, data);
2737}
2738bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2739 GLenum target,
2740 GLint level,
2741 GLint xoffset,
2742 GLint yoffset,
2743 GLsizei width,
2744 GLsizei height,
2745 GLenum format,
2746 GLsizei imageSize,
2747 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002748 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002749{
2750 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2751 {
2752 return false;
2753 }
2754
2755 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2756 format, imageSize, data);
2757}
2758
Jamie Madill73a84962016-02-12 09:27:23 -05002759bool ValidateCompressedTexSubImage2D(Context *context,
2760 GLenum target,
2761 GLint level,
2762 GLint xoffset,
2763 GLint yoffset,
2764 GLsizei width,
2765 GLsizei height,
2766 GLenum format,
2767 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002768 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002769{
Martin Radev1be913c2016-07-11 17:59:16 +03002770 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002771 {
2772 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002773 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002774 {
2775 return false;
2776 }
2777 }
2778 else
2779 {
Martin Radev1be913c2016-07-11 17:59:16 +03002780 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002781 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002782 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002783 data))
2784 {
2785 return false;
2786 }
2787 }
2788
Geoff Langca271392017-04-05 12:30:00 -04002789 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002790 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002791 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002792 if (blockSizeOrErr.isError())
2793 {
2794 context->handleError(blockSizeOrErr.getError());
2795 return false;
2796 }
2797
2798 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002800 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002801 return false;
2802 }
2803
2804 return true;
2805}
2806
Olli Etuaho4f667482016-03-30 15:56:35 +03002807bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2808{
Geoff Lang496c02d2016-10-20 11:38:11 -07002809 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002810}
2811
2812bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2813{
2814 if (!context->getExtensions().mapBuffer)
2815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002816 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002817 return false;
2818 }
2819
2820 if (!ValidBufferTarget(context, target))
2821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002823 return false;
2824 }
2825
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002826 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002827
2828 if (buffer == nullptr)
2829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002830 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002831 return false;
2832 }
2833
2834 if (access != GL_WRITE_ONLY_OES)
2835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002836 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002837 return false;
2838 }
2839
2840 if (buffer->isMapped())
2841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002842 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002843 return false;
2844 }
2845
Geoff Lang79f71042017-08-14 16:43:43 -04002846 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002847}
2848
2849bool ValidateUnmapBufferOES(Context *context, GLenum target)
2850{
2851 if (!context->getExtensions().mapBuffer)
2852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002853 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002854 return false;
2855 }
2856
2857 return ValidateUnmapBufferBase(context, target);
2858}
2859
2860bool ValidateMapBufferRangeEXT(Context *context,
2861 GLenum target,
2862 GLintptr offset,
2863 GLsizeiptr length,
2864 GLbitfield access)
2865{
2866 if (!context->getExtensions().mapBufferRange)
2867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002868 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002869 return false;
2870 }
2871
2872 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2873}
2874
Geoff Lang79f71042017-08-14 16:43:43 -04002875bool ValidateMapBufferBase(Context *context, GLenum target)
2876{
2877 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2878 ASSERT(buffer != nullptr);
2879
2880 // Check if this buffer is currently being used as a transform feedback output buffer
2881 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2882 if (transformFeedback != nullptr && transformFeedback->isActive())
2883 {
2884 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2885 {
2886 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2887 if (transformFeedbackBuffer.get() == buffer)
2888 {
2889 context->handleError(InvalidOperation()
2890 << "Buffer is currently bound for transform feedback.");
2891 return false;
2892 }
2893 }
2894 }
2895
2896 return true;
2897}
2898
Olli Etuaho4f667482016-03-30 15:56:35 +03002899bool ValidateFlushMappedBufferRangeEXT(Context *context,
2900 GLenum target,
2901 GLintptr offset,
2902 GLsizeiptr length)
2903{
2904 if (!context->getExtensions().mapBufferRange)
2905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002906 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002907 return false;
2908 }
2909
2910 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2911}
2912
Ian Ewell54f87462016-03-10 13:47:21 -05002913bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2914{
2915 Texture *textureObject = context->getTexture(texture);
2916 if (textureObject && textureObject->getTarget() != target && texture != 0)
2917 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002919 return false;
2920 }
2921
Geoff Langf41a7152016-09-19 15:11:17 -04002922 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2923 !context->isTextureGenerated(texture))
2924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002925 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002926 return false;
2927 }
2928
Ian Ewell54f87462016-03-10 13:47:21 -05002929 switch (target)
2930 {
2931 case GL_TEXTURE_2D:
2932 case GL_TEXTURE_CUBE_MAP:
2933 break;
2934
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002935 case GL_TEXTURE_RECTANGLE_ANGLE:
2936 if (!context->getExtensions().textureRectangle)
2937 {
2938 context->handleError(InvalidEnum()
2939 << "Context does not support GL_ANGLE_texture_rectangle");
2940 return false;
2941 }
2942 break;
2943
Ian Ewell54f87462016-03-10 13:47:21 -05002944 case GL_TEXTURE_3D:
2945 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002946 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002947 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002949 return false;
2950 }
2951 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002952
2953 case GL_TEXTURE_2D_MULTISAMPLE:
2954 if (context->getClientVersion() < Version(3, 1))
2955 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002957 return false;
2958 }
Geoff Lang3b573612016-10-31 14:08:10 -04002959 break;
2960
Ian Ewell54f87462016-03-10 13:47:21 -05002961 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002962 if (!context->getExtensions().eglImageExternal &&
2963 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002965 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002966 return false;
2967 }
2968 break;
2969 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002970 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002971 return false;
2972 }
2973
2974 return true;
2975}
2976
Geoff Langd8605522016-04-13 10:19:12 -04002977bool ValidateBindUniformLocationCHROMIUM(Context *context,
2978 GLuint program,
2979 GLint location,
2980 const GLchar *name)
2981{
2982 if (!context->getExtensions().bindUniformLocation)
2983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002984 context->handleError(InvalidOperation()
2985 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002986 return false;
2987 }
2988
2989 Program *programObject = GetValidProgram(context, program);
2990 if (!programObject)
2991 {
2992 return false;
2993 }
2994
2995 if (location < 0)
2996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002997 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002998 return false;
2999 }
3000
3001 const Caps &caps = context->getCaps();
3002 if (static_cast<size_t>(location) >=
3003 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003005 context->handleError(InvalidValue() << "Location must be less than "
3006 "(MAX_VERTEX_UNIFORM_VECTORS + "
3007 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04003008 return false;
3009 }
3010
Geoff Langfc32e8b2017-05-31 14:16:59 -04003011 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3012 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04003013 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04003014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003015 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04003016 return false;
3017 }
3018
Geoff Langd8605522016-04-13 10:19:12 -04003019 if (strncmp(name, "gl_", 3) == 0)
3020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003021 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04003022 return false;
3023 }
3024
3025 return true;
3026}
3027
Jamie Madille2e406c2016-06-02 13:04:10 -04003028bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03003029{
3030 if (!context->getExtensions().framebufferMixedSamples)
3031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003032 context->handleError(InvalidOperation()
3033 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03003034 return false;
3035 }
3036 switch (components)
3037 {
3038 case GL_RGB:
3039 case GL_RGBA:
3040 case GL_ALPHA:
3041 case GL_NONE:
3042 break;
3043 default:
3044 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003045 InvalidEnum()
3046 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03003047 return false;
3048 }
3049
3050 return true;
3051}
3052
Sami Väisänene45e53b2016-05-25 10:36:04 +03003053// CHROMIUM_path_rendering
3054
3055bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3056{
3057 if (!context->getExtensions().pathRendering)
3058 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003059 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003060 return false;
3061 }
3062 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3063 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003065 return false;
3066 }
3067 if (matrix == nullptr)
3068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003069 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003070 return false;
3071 }
3072 return true;
3073}
3074
3075bool ValidateMatrixMode(Context *context, GLenum matrixMode)
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 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3083 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003085 return false;
3086 }
3087 return true;
3088}
3089
3090bool ValidateGenPaths(Context *context, GLsizei range)
3091{
3092 if (!context->getExtensions().pathRendering)
3093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003094 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003095 return false;
3096 }
3097
3098 // range = 0 is undefined in NV_path_rendering.
3099 // we add stricter semantic check here and require a non zero positive range.
3100 if (range <= 0)
3101 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003102 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003103 return false;
3104 }
3105
3106 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003109 return false;
3110 }
3111
3112 return true;
3113}
3114
3115bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3116{
3117 if (!context->getExtensions().pathRendering)
3118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003119 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003120 return false;
3121 }
3122
3123 // range = 0 is undefined in NV_path_rendering.
3124 // we add stricter semantic check here and require a non zero positive range.
3125 if (range <= 0)
3126 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003127 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003128 return false;
3129 }
3130
3131 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3132 checkedRange += range;
3133
3134 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003137 return false;
3138 }
3139 return true;
3140}
3141
3142bool ValidatePathCommands(Context *context,
3143 GLuint path,
3144 GLsizei numCommands,
3145 const GLubyte *commands,
3146 GLsizei numCoords,
3147 GLenum coordType,
3148 const void *coords)
3149{
3150 if (!context->getExtensions().pathRendering)
3151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003152 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003153 return false;
3154 }
3155 if (!context->hasPath(path))
3156 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003158 return false;
3159 }
3160
3161 if (numCommands < 0)
3162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003163 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003164 return false;
3165 }
3166 else if (numCommands > 0)
3167 {
3168 if (!commands)
3169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003170 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003171 return false;
3172 }
3173 }
3174
3175 if (numCoords < 0)
3176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003177 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003178 return false;
3179 }
3180 else if (numCoords > 0)
3181 {
3182 if (!coords)
3183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003184 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003185 return false;
3186 }
3187 }
3188
3189 std::uint32_t coordTypeSize = 0;
3190 switch (coordType)
3191 {
3192 case GL_BYTE:
3193 coordTypeSize = sizeof(GLbyte);
3194 break;
3195
3196 case GL_UNSIGNED_BYTE:
3197 coordTypeSize = sizeof(GLubyte);
3198 break;
3199
3200 case GL_SHORT:
3201 coordTypeSize = sizeof(GLshort);
3202 break;
3203
3204 case GL_UNSIGNED_SHORT:
3205 coordTypeSize = sizeof(GLushort);
3206 break;
3207
3208 case GL_FLOAT:
3209 coordTypeSize = sizeof(GLfloat);
3210 break;
3211
3212 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003213 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003214 return false;
3215 }
3216
3217 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3218 checkedSize += (coordTypeSize * numCoords);
3219 if (!checkedSize.IsValid())
3220 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003222 return false;
3223 }
3224
3225 // early return skips command data validation when it doesn't exist.
3226 if (!commands)
3227 return true;
3228
3229 GLsizei expectedNumCoords = 0;
3230 for (GLsizei i = 0; i < numCommands; ++i)
3231 {
3232 switch (commands[i])
3233 {
3234 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3235 break;
3236 case GL_MOVE_TO_CHROMIUM:
3237 case GL_LINE_TO_CHROMIUM:
3238 expectedNumCoords += 2;
3239 break;
3240 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3241 expectedNumCoords += 4;
3242 break;
3243 case GL_CUBIC_CURVE_TO_CHROMIUM:
3244 expectedNumCoords += 6;
3245 break;
3246 case GL_CONIC_CURVE_TO_CHROMIUM:
3247 expectedNumCoords += 5;
3248 break;
3249 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003250 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003251 return false;
3252 }
3253 }
3254 if (expectedNumCoords != numCoords)
3255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003256 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003257 return false;
3258 }
3259
3260 return true;
3261}
3262
3263bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3264{
3265 if (!context->getExtensions().pathRendering)
3266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003267 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003268 return false;
3269 }
3270 if (!context->hasPath(path))
3271 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003273 return false;
3274 }
3275
3276 switch (pname)
3277 {
3278 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3279 if (value < 0.0f)
3280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003281 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003282 return false;
3283 }
3284 break;
3285 case GL_PATH_END_CAPS_CHROMIUM:
3286 switch (static_cast<GLenum>(value))
3287 {
3288 case GL_FLAT_CHROMIUM:
3289 case GL_SQUARE_CHROMIUM:
3290 case GL_ROUND_CHROMIUM:
3291 break;
3292 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003293 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003294 return false;
3295 }
3296 break;
3297 case GL_PATH_JOIN_STYLE_CHROMIUM:
3298 switch (static_cast<GLenum>(value))
3299 {
3300 case GL_MITER_REVERT_CHROMIUM:
3301 case GL_BEVEL_CHROMIUM:
3302 case GL_ROUND_CHROMIUM:
3303 break;
3304 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003305 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003306 return false;
3307 }
3308 case GL_PATH_MITER_LIMIT_CHROMIUM:
3309 if (value < 0.0f)
3310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003311 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003312 return false;
3313 }
3314 break;
3315
3316 case GL_PATH_STROKE_BOUND_CHROMIUM:
3317 // no errors, only clamping.
3318 break;
3319
3320 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003321 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003322 return false;
3323 }
3324 return true;
3325}
3326
3327bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3328{
3329 if (!context->getExtensions().pathRendering)
3330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003331 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003332 return false;
3333 }
3334
3335 if (!context->hasPath(path))
3336 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003337 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003338 return false;
3339 }
3340 if (!value)
3341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003342 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003343 return false;
3344 }
3345
3346 switch (pname)
3347 {
3348 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3349 case GL_PATH_END_CAPS_CHROMIUM:
3350 case GL_PATH_JOIN_STYLE_CHROMIUM:
3351 case GL_PATH_MITER_LIMIT_CHROMIUM:
3352 case GL_PATH_STROKE_BOUND_CHROMIUM:
3353 break;
3354
3355 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003356 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003357 return false;
3358 }
3359
3360 return true;
3361}
3362
3363bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3364{
3365 if (!context->getExtensions().pathRendering)
3366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003367 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003368 return false;
3369 }
3370
3371 switch (func)
3372 {
3373 case GL_NEVER:
3374 case GL_ALWAYS:
3375 case GL_LESS:
3376 case GL_LEQUAL:
3377 case GL_EQUAL:
3378 case GL_GEQUAL:
3379 case GL_GREATER:
3380 case GL_NOTEQUAL:
3381 break;
3382 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003383 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003384 return false;
3385 }
3386
3387 return true;
3388}
3389
3390// Note that the spec specifies that for the path drawing commands
3391// if the path object is not an existing path object the command
3392// does nothing and no error is generated.
3393// However if the path object exists but has not been specified any
3394// commands then an error is generated.
3395
3396bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3397{
3398 if (!context->getExtensions().pathRendering)
3399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003400 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003401 return false;
3402 }
3403 if (context->hasPath(path) && !context->hasPathData(path))
3404 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003405 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003406 return false;
3407 }
3408
3409 switch (fillMode)
3410 {
3411 case GL_COUNT_UP_CHROMIUM:
3412 case GL_COUNT_DOWN_CHROMIUM:
3413 break;
3414 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003416 return false;
3417 }
3418
3419 if (!isPow2(mask + 1))
3420 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003421 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003422 return false;
3423 }
3424
3425 return true;
3426}
3427
3428bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3429{
3430 if (!context->getExtensions().pathRendering)
3431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003432 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003433 return false;
3434 }
3435 if (context->hasPath(path) && !context->hasPathData(path))
3436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003438 return false;
3439 }
3440
3441 return true;
3442}
3443
3444bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3445{
3446 if (!context->getExtensions().pathRendering)
3447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003448 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003449 return false;
3450 }
3451 if (context->hasPath(path) && !context->hasPathData(path))
3452 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003454 return false;
3455 }
3456
3457 switch (coverMode)
3458 {
3459 case GL_CONVEX_HULL_CHROMIUM:
3460 case GL_BOUNDING_BOX_CHROMIUM:
3461 break;
3462 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003463 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003464 return false;
3465 }
3466 return true;
3467}
3468
3469bool ValidateStencilThenCoverFillPath(Context *context,
3470 GLuint path,
3471 GLenum fillMode,
3472 GLuint mask,
3473 GLenum coverMode)
3474{
3475 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3476 ValidateCoverPath(context, path, coverMode);
3477}
3478
3479bool ValidateStencilThenCoverStrokePath(Context *context,
3480 GLuint path,
3481 GLint reference,
3482 GLuint mask,
3483 GLenum coverMode)
3484{
3485 return ValidateStencilStrokePath(context, path, reference, mask) &&
3486 ValidateCoverPath(context, path, coverMode);
3487}
3488
3489bool ValidateIsPath(Context *context)
3490{
3491 if (!context->getExtensions().pathRendering)
3492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003493 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003494 return false;
3495 }
3496 return true;
3497}
3498
Sami Väisänend59ca052016-06-21 16:10:00 +03003499bool ValidateCoverFillPathInstanced(Context *context,
3500 GLsizei numPaths,
3501 GLenum pathNameType,
3502 const void *paths,
3503 GLuint pathBase,
3504 GLenum coverMode,
3505 GLenum transformType,
3506 const GLfloat *transformValues)
3507{
3508 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3509 transformType, transformValues))
3510 return false;
3511
3512 switch (coverMode)
3513 {
3514 case GL_CONVEX_HULL_CHROMIUM:
3515 case GL_BOUNDING_BOX_CHROMIUM:
3516 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3517 break;
3518 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003520 return false;
3521 }
3522
3523 return true;
3524}
3525
3526bool ValidateCoverStrokePathInstanced(Context *context,
3527 GLsizei numPaths,
3528 GLenum pathNameType,
3529 const void *paths,
3530 GLuint pathBase,
3531 GLenum coverMode,
3532 GLenum transformType,
3533 const GLfloat *transformValues)
3534{
3535 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3536 transformType, transformValues))
3537 return false;
3538
3539 switch (coverMode)
3540 {
3541 case GL_CONVEX_HULL_CHROMIUM:
3542 case GL_BOUNDING_BOX_CHROMIUM:
3543 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3544 break;
3545 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003546 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003547 return false;
3548 }
3549
3550 return true;
3551}
3552
3553bool ValidateStencilFillPathInstanced(Context *context,
3554 GLsizei numPaths,
3555 GLenum pathNameType,
3556 const void *paths,
3557 GLuint pathBase,
3558 GLenum fillMode,
3559 GLuint mask,
3560 GLenum transformType,
3561 const GLfloat *transformValues)
3562{
3563
3564 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3565 transformType, transformValues))
3566 return false;
3567
3568 switch (fillMode)
3569 {
3570 case GL_COUNT_UP_CHROMIUM:
3571 case GL_COUNT_DOWN_CHROMIUM:
3572 break;
3573 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003574 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003575 return false;
3576 }
3577 if (!isPow2(mask + 1))
3578 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003579 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003580 return false;
3581 }
3582 return true;
3583}
3584
3585bool ValidateStencilStrokePathInstanced(Context *context,
3586 GLsizei numPaths,
3587 GLenum pathNameType,
3588 const void *paths,
3589 GLuint pathBase,
3590 GLint reference,
3591 GLuint mask,
3592 GLenum transformType,
3593 const GLfloat *transformValues)
3594{
3595 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3596 transformType, transformValues))
3597 return false;
3598
3599 // no more validation here.
3600
3601 return true;
3602}
3603
3604bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3605 GLsizei numPaths,
3606 GLenum pathNameType,
3607 const void *paths,
3608 GLuint pathBase,
3609 GLenum fillMode,
3610 GLuint mask,
3611 GLenum coverMode,
3612 GLenum transformType,
3613 const GLfloat *transformValues)
3614{
3615 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3616 transformType, transformValues))
3617 return false;
3618
3619 switch (coverMode)
3620 {
3621 case GL_CONVEX_HULL_CHROMIUM:
3622 case GL_BOUNDING_BOX_CHROMIUM:
3623 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3624 break;
3625 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003626 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003627 return false;
3628 }
3629
3630 switch (fillMode)
3631 {
3632 case GL_COUNT_UP_CHROMIUM:
3633 case GL_COUNT_DOWN_CHROMIUM:
3634 break;
3635 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003637 return false;
3638 }
3639 if (!isPow2(mask + 1))
3640 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003641 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003642 return false;
3643 }
3644
3645 return true;
3646}
3647
3648bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3649 GLsizei numPaths,
3650 GLenum pathNameType,
3651 const void *paths,
3652 GLuint pathBase,
3653 GLint reference,
3654 GLuint mask,
3655 GLenum coverMode,
3656 GLenum transformType,
3657 const GLfloat *transformValues)
3658{
3659 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3660 transformType, transformValues))
3661 return false;
3662
3663 switch (coverMode)
3664 {
3665 case GL_CONVEX_HULL_CHROMIUM:
3666 case GL_BOUNDING_BOX_CHROMIUM:
3667 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3668 break;
3669 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003670 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003671 return false;
3672 }
3673
3674 return true;
3675}
3676
Sami Väisänen46eaa942016-06-29 10:26:37 +03003677bool ValidateBindFragmentInputLocation(Context *context,
3678 GLuint program,
3679 GLint location,
3680 const GLchar *name)
3681{
3682 if (!context->getExtensions().pathRendering)
3683 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003684 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003685 return false;
3686 }
3687
3688 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3689 if (location >= MaxLocation)
3690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003691 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003692 return false;
3693 }
3694
3695 const auto *programObject = context->getProgram(program);
3696 if (!programObject)
3697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003699 return false;
3700 }
3701
3702 if (!name)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003705 return false;
3706 }
3707
3708 if (angle::BeginsWith(name, "gl_"))
3709 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003710 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003711 return false;
3712 }
3713
3714 return true;
3715}
3716
3717bool ValidateProgramPathFragmentInputGen(Context *context,
3718 GLuint program,
3719 GLint location,
3720 GLenum genMode,
3721 GLint components,
3722 const GLfloat *coeffs)
3723{
3724 if (!context->getExtensions().pathRendering)
3725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003727 return false;
3728 }
3729
3730 const auto *programObject = context->getProgram(program);
3731 if (!programObject || programObject->isFlaggedForDeletion())
3732 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003734 return false;
3735 }
3736
3737 if (!programObject->isLinked())
3738 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003740 return false;
3741 }
3742
3743 switch (genMode)
3744 {
3745 case GL_NONE:
3746 if (components != 0)
3747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003749 return false;
3750 }
3751 break;
3752
3753 case GL_OBJECT_LINEAR_CHROMIUM:
3754 case GL_EYE_LINEAR_CHROMIUM:
3755 case GL_CONSTANT_CHROMIUM:
3756 if (components < 1 || components > 4)
3757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003758 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003759 return false;
3760 }
3761 if (!coeffs)
3762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003764 return false;
3765 }
3766 break;
3767
3768 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003770 return false;
3771 }
3772
3773 // If the location is -1 then the command is silently ignored
3774 // and no further validation is needed.
3775 if (location == -1)
3776 return true;
3777
Jamie Madillbd044ed2017-06-05 12:59:21 -04003778 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003779
3780 if (!binding.valid)
3781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003783 return false;
3784 }
3785
3786 if (binding.type != GL_NONE)
3787 {
3788 GLint expectedComponents = 0;
3789 switch (binding.type)
3790 {
3791 case GL_FLOAT:
3792 expectedComponents = 1;
3793 break;
3794 case GL_FLOAT_VEC2:
3795 expectedComponents = 2;
3796 break;
3797 case GL_FLOAT_VEC3:
3798 expectedComponents = 3;
3799 break;
3800 case GL_FLOAT_VEC4:
3801 expectedComponents = 4;
3802 break;
3803 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003804 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 InvalidOperation()
3806 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003807 return false;
3808 }
3809 if (expectedComponents != components && genMode != GL_NONE)
3810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003811 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003812 return false;
3813 }
3814 }
3815 return true;
3816}
3817
Geoff Lang97073d12016-04-20 10:42:34 -07003818bool ValidateCopyTextureCHROMIUM(Context *context,
3819 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003820 GLint sourceLevel,
3821 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003822 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003823 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003824 GLint internalFormat,
3825 GLenum destType,
3826 GLboolean unpackFlipY,
3827 GLboolean unpackPremultiplyAlpha,
3828 GLboolean unpackUnmultiplyAlpha)
3829{
3830 if (!context->getExtensions().copyTexture)
3831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003832 context->handleError(InvalidOperation()
3833 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003834 return false;
3835 }
3836
Geoff Lang4f0e0032017-05-01 16:04:35 -04003837 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003838 if (source == nullptr)
3839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003841 return false;
3842 }
3843
3844 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003846 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003847 return false;
3848 }
3849
3850 GLenum sourceTarget = source->getTarget();
3851 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003852
3853 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003856 return false;
3857 }
3858
Geoff Lang4f0e0032017-05-01 16:04:35 -04003859 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3860 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3861 if (sourceWidth == 0 || sourceHeight == 0)
3862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003864 return false;
3865 }
3866
3867 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3868 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003871 return false;
3872 }
3873
Geoff Lang4f0e0032017-05-01 16:04:35 -04003874 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003875 if (dest == nullptr)
3876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidValue()
3878 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003879 return false;
3880 }
3881
Geoff Lang4f0e0032017-05-01 16:04:35 -04003882 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003884 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003885 return false;
3886 }
3887
Geoff Lang4f0e0032017-05-01 16:04:35 -04003888 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3889 sourceHeight))
3890 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003891 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003892 return false;
3893 }
3894
Geoff Lang97073d12016-04-20 10:42:34 -07003895 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003898 return false;
3899 }
3900
Geoff Lang4f0e0032017-05-01 16:04:35 -04003901 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003903 context->handleError(
3904 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003905 return false;
3906 }
3907
Geoff Lang97073d12016-04-20 10:42:34 -07003908 if (dest->getImmutableFormat())
3909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003910 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003911 return false;
3912 }
3913
3914 return true;
3915}
3916
3917bool ValidateCopySubTextureCHROMIUM(Context *context,
3918 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003919 GLint sourceLevel,
3920 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003921 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003922 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003923 GLint xoffset,
3924 GLint yoffset,
3925 GLint x,
3926 GLint y,
3927 GLsizei width,
3928 GLsizei height,
3929 GLboolean unpackFlipY,
3930 GLboolean unpackPremultiplyAlpha,
3931 GLboolean unpackUnmultiplyAlpha)
3932{
3933 if (!context->getExtensions().copyTexture)
3934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003935 context->handleError(InvalidOperation()
3936 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003937 return false;
3938 }
3939
Geoff Lang4f0e0032017-05-01 16:04:35 -04003940 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003941 if (source == nullptr)
3942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003943 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003944 return false;
3945 }
3946
3947 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003949 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003950 return false;
3951 }
3952
3953 GLenum sourceTarget = source->getTarget();
3954 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003955
3956 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003958 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003959 return false;
3960 }
3961
3962 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3963 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003965 context->handleError(InvalidValue()
3966 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003967 return false;
3968 }
3969
3970 if (x < 0 || y < 0)
3971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003972 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003973 return false;
3974 }
3975
3976 if (width < 0 || height < 0)
3977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003978 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003979 return false;
3980 }
3981
Geoff Lang4f0e0032017-05-01 16:04:35 -04003982 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3983 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003985 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003986 return false;
3987 }
3988
Geoff Lang4f0e0032017-05-01 16:04:35 -04003989 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3990 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003993 return false;
3994 }
3995
Geoff Lang4f0e0032017-05-01 16:04:35 -04003996 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003997 if (dest == nullptr)
3998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003999 context->handleError(InvalidValue()
4000 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07004001 return false;
4002 }
4003
Geoff Lang4f0e0032017-05-01 16:04:35 -04004004 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07004005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004006 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07004007 return false;
4008 }
4009
Geoff Lang4f0e0032017-05-01 16:04:35 -04004010 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07004011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004012 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004013 return false;
4014 }
4015
Geoff Lang4f0e0032017-05-01 16:04:35 -04004016 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
4017 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04004018 context
4019 ->handleError(InvalidOperation()
4020 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04004021 return false;
4022 }
4023
4024 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
4025 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidOperation()
4028 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004029 return false;
4030 }
4031
4032 if (xoffset < 0 || yoffset < 0)
4033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004034 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07004035 return false;
4036 }
4037
Geoff Lang4f0e0032017-05-01 16:04:35 -04004038 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
4039 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004041 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07004042 return false;
4043 }
4044
4045 return true;
4046}
4047
Geoff Lang47110bf2016-04-20 11:13:22 -07004048bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
4049{
4050 if (!context->getExtensions().copyCompressedTexture)
4051 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004052 context->handleError(InvalidOperation()
4053 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004054 return false;
4055 }
4056
4057 const gl::Texture *source = context->getTexture(sourceId);
4058 if (source == nullptr)
4059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004060 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004061 return false;
4062 }
4063
4064 if (source->getTarget() != GL_TEXTURE_2D)
4065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004066 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004067 return false;
4068 }
4069
4070 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004072 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004073 return false;
4074 }
4075
4076 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4077 if (!sourceFormat.info->compressed)
4078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004079 context->handleError(InvalidOperation()
4080 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004081 return false;
4082 }
4083
4084 const gl::Texture *dest = context->getTexture(destId);
4085 if (dest == nullptr)
4086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004087 context->handleError(InvalidValue()
4088 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004089 return false;
4090 }
4091
4092 if (dest->getTarget() != GL_TEXTURE_2D)
4093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004094 context->handleError(InvalidValue()
4095 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004096 return false;
4097 }
4098
4099 if (dest->getImmutableFormat())
4100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004101 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004102 return false;
4103 }
4104
4105 return true;
4106}
4107
Martin Radev4c4c8e72016-08-04 12:25:34 +03004108bool ValidateCreateShader(Context *context, GLenum type)
4109{
4110 switch (type)
4111 {
4112 case GL_VERTEX_SHADER:
4113 case GL_FRAGMENT_SHADER:
4114 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004115
Martin Radev4c4c8e72016-08-04 12:25:34 +03004116 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004117 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004118 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Langeb66a6e2016-10-31 13:06:12 -04004120 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004121 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004122 break;
4123
Martin Radev4c4c8e72016-08-04 12:25:34 +03004124 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004126 return false;
4127 }
Jamie Madill29639852016-09-02 15:00:09 -04004128
4129 return true;
4130}
4131
4132bool ValidateBufferData(ValidationContext *context,
4133 GLenum target,
4134 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004135 const void *data,
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004136 BufferUsage usage)
Jamie Madill29639852016-09-02 15:00:09 -04004137{
4138 if (size < 0)
4139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004140 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004141 return false;
4142 }
4143
4144 switch (usage)
4145 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004146 case BufferUsage::StreamDraw:
4147 case BufferUsage::StaticDraw:
4148 case BufferUsage::DynamicDraw:
Jamie Madill29639852016-09-02 15:00:09 -04004149 break;
4150
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004151 case BufferUsage::StreamRead:
4152 case BufferUsage::StaticRead:
4153 case BufferUsage::DynamicRead:
4154 case BufferUsage::StreamCopy:
4155 case BufferUsage::StaticCopy:
4156 case BufferUsage::DynamicCopy:
Jamie Madill29639852016-09-02 15:00:09 -04004157 if (context->getClientMajorVersion() < 3)
4158 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004160 return false;
4161 }
4162 break;
4163
4164 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004166 return false;
4167 }
4168
4169 if (!ValidBufferTarget(context, target))
4170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004172 return false;
4173 }
4174
4175 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4176
4177 if (!buffer)
4178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004180 return false;
4181 }
4182
4183 return true;
4184}
4185
4186bool ValidateBufferSubData(ValidationContext *context,
4187 GLenum target,
4188 GLintptr offset,
4189 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004190 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004191{
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004193 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004194 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4195 return false;
4196 }
4197
4198 if (offset < 0)
4199 {
4200 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004201 return false;
4202 }
4203
4204 if (!ValidBufferTarget(context, target))
4205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004207 return false;
4208 }
4209
4210 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4211
4212 if (!buffer)
4213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004215 return false;
4216 }
4217
4218 if (buffer->isMapped())
4219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004220 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004221 return false;
4222 }
4223
4224 // Check for possible overflow of size + offset
4225 angle::CheckedNumeric<size_t> checkedSize(size);
4226 checkedSize += offset;
4227 if (!checkedSize.IsValid())
4228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004229 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004230 return false;
4231 }
4232
4233 if (size + offset > buffer->getSize())
4234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004235 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004236 return false;
4237 }
4238
Martin Radev4c4c8e72016-08-04 12:25:34 +03004239 return true;
4240}
4241
Geoff Lang111a99e2017-10-17 10:58:41 -04004242bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004243{
Geoff Langc339c4e2016-11-29 10:37:36 -05004244 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004246 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004247 return false;
4248 }
4249
Geoff Lang111a99e2017-10-17 10:58:41 -04004250 if (!context->isExtensionRequestable(name))
Geoff Langc287ea62016-09-16 14:46:51 -04004251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004252 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004253 return false;
4254 }
4255
4256 return true;
4257}
4258
Jamie Madillef300b12016-10-07 15:12:09 -04004259bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4260{
4261 if (texture < GL_TEXTURE0 ||
4262 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004264 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004265 return false;
4266 }
4267
4268 return true;
4269}
4270
4271bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4272{
4273 Program *programObject = GetValidProgram(context, program);
4274 if (!programObject)
4275 {
4276 return false;
4277 }
4278
4279 Shader *shaderObject = GetValidShader(context, shader);
4280 if (!shaderObject)
4281 {
4282 return false;
4283 }
4284
4285 switch (shaderObject->getType())
4286 {
4287 case GL_VERTEX_SHADER:
4288 {
4289 if (programObject->getAttachedVertexShader())
4290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004292 return false;
4293 }
4294 break;
4295 }
4296 case GL_FRAGMENT_SHADER:
4297 {
4298 if (programObject->getAttachedFragmentShader())
4299 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004300 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004301 return false;
4302 }
4303 break;
4304 }
4305 case GL_COMPUTE_SHADER:
4306 {
4307 if (programObject->getAttachedComputeShader())
4308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004310 return false;
4311 }
4312 break;
4313 }
4314 default:
4315 UNREACHABLE();
4316 break;
4317 }
4318
4319 return true;
4320}
4321
Jamie Madill01a80ee2016-11-07 12:06:18 -05004322bool ValidateBindAttribLocation(ValidationContext *context,
4323 GLuint program,
4324 GLuint index,
4325 const GLchar *name)
4326{
4327 if (index >= MAX_VERTEX_ATTRIBS)
4328 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004329 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004330 return false;
4331 }
4332
4333 if (strncmp(name, "gl_", 3) == 0)
4334 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004335 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004336 return false;
4337 }
4338
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004339 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004340 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004341 const size_t length = strlen(name);
4342
4343 if (!IsValidESSLString(name, length))
4344 {
4345 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4346 // for shader-related entry points
4347 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4348 return false;
4349 }
4350
4351 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4352 {
4353 return false;
4354 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004355 }
4356
Jamie Madill01a80ee2016-11-07 12:06:18 -05004357 return GetValidProgram(context, program) != nullptr;
4358}
4359
4360bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4361{
4362 if (!ValidBufferTarget(context, target))
4363 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004365 return false;
4366 }
4367
4368 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4369 !context->isBufferGenerated(buffer))
4370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004372 return false;
4373 }
4374
4375 return true;
4376}
4377
4378bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4379{
4380 if (!ValidFramebufferTarget(target))
4381 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004383 return false;
4384 }
4385
4386 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4387 !context->isFramebufferGenerated(framebuffer))
4388 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004389 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004390 return false;
4391 }
4392
4393 return true;
4394}
4395
4396bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4397{
4398 if (target != GL_RENDERBUFFER)
4399 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004400 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004401 return false;
4402 }
4403
4404 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4405 !context->isRenderbufferGenerated(renderbuffer))
4406 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004407 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004408 return false;
4409 }
4410
4411 return true;
4412}
4413
Geoff Lang50cac572017-09-26 17:37:43 -04004414static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004415{
4416 switch (mode)
4417 {
4418 case GL_FUNC_ADD:
4419 case GL_FUNC_SUBTRACT:
4420 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004421 return true;
4422
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004423 case GL_MIN:
4424 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004425 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004426
4427 default:
4428 return false;
4429 }
4430}
4431
Jamie Madillc1d770e2017-04-13 17:31:24 -04004432bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004433 GLfloat red,
4434 GLfloat green,
4435 GLfloat blue,
4436 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004437{
4438 return true;
4439}
4440
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004441bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4442{
Geoff Lang50cac572017-09-26 17:37:43 -04004443 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004444 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004446 return false;
4447 }
4448
4449 return true;
4450}
4451
4452bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4453{
Geoff Lang50cac572017-09-26 17:37:43 -04004454 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004455 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004456 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004457 return false;
4458 }
4459
Geoff Lang50cac572017-09-26 17:37:43 -04004460 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004461 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004462 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004463 return false;
4464 }
4465
4466 return true;
4467}
4468
4469bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4470{
4471 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4472}
4473
4474static bool ValidSrcBlendFunc(GLenum srcBlend)
4475{
4476 switch (srcBlend)
4477 {
4478 case GL_ZERO:
4479 case GL_ONE:
4480 case GL_SRC_COLOR:
4481 case GL_ONE_MINUS_SRC_COLOR:
4482 case GL_DST_COLOR:
4483 case GL_ONE_MINUS_DST_COLOR:
4484 case GL_SRC_ALPHA:
4485 case GL_ONE_MINUS_SRC_ALPHA:
4486 case GL_DST_ALPHA:
4487 case GL_ONE_MINUS_DST_ALPHA:
4488 case GL_CONSTANT_COLOR:
4489 case GL_ONE_MINUS_CONSTANT_COLOR:
4490 case GL_CONSTANT_ALPHA:
4491 case GL_ONE_MINUS_CONSTANT_ALPHA:
4492 case GL_SRC_ALPHA_SATURATE:
4493 return true;
4494
4495 default:
4496 return false;
4497 }
4498}
4499
4500static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4501{
4502 switch (dstBlend)
4503 {
4504 case GL_ZERO:
4505 case GL_ONE:
4506 case GL_SRC_COLOR:
4507 case GL_ONE_MINUS_SRC_COLOR:
4508 case GL_DST_COLOR:
4509 case GL_ONE_MINUS_DST_COLOR:
4510 case GL_SRC_ALPHA:
4511 case GL_ONE_MINUS_SRC_ALPHA:
4512 case GL_DST_ALPHA:
4513 case GL_ONE_MINUS_DST_ALPHA:
4514 case GL_CONSTANT_COLOR:
4515 case GL_ONE_MINUS_CONSTANT_COLOR:
4516 case GL_CONSTANT_ALPHA:
4517 case GL_ONE_MINUS_CONSTANT_ALPHA:
4518 return true;
4519
4520 case GL_SRC_ALPHA_SATURATE:
4521 return (contextMajorVersion >= 3);
4522
4523 default:
4524 return false;
4525 }
4526}
4527
4528bool ValidateBlendFuncSeparate(ValidationContext *context,
4529 GLenum srcRGB,
4530 GLenum dstRGB,
4531 GLenum srcAlpha,
4532 GLenum dstAlpha)
4533{
4534 if (!ValidSrcBlendFunc(srcRGB))
4535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004537 return false;
4538 }
4539
4540 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4541 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004543 return false;
4544 }
4545
4546 if (!ValidSrcBlendFunc(srcAlpha))
4547 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004549 return false;
4550 }
4551
4552 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4553 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004555 return false;
4556 }
4557
Frank Henigman146e8a12017-03-02 23:22:37 -05004558 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4559 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004560 {
4561 bool constantColorUsed =
4562 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4563 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4564
4565 bool constantAlphaUsed =
4566 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4567 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4568
4569 if (constantColorUsed && constantAlphaUsed)
4570 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004571 const char *msg;
4572 if (context->getExtensions().webglCompatibility)
4573 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004574 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004575 }
4576 else
4577 {
4578 msg =
4579 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4580 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4581 "implementation.";
4582 ERR() << msg;
4583 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004584 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004585 return false;
4586 }
4587 }
4588
4589 return true;
4590}
4591
Geoff Langc339c4e2016-11-29 10:37:36 -05004592bool ValidateGetString(Context *context, GLenum name)
4593{
4594 switch (name)
4595 {
4596 case GL_VENDOR:
4597 case GL_RENDERER:
4598 case GL_VERSION:
4599 case GL_SHADING_LANGUAGE_VERSION:
4600 case GL_EXTENSIONS:
4601 break;
4602
4603 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4604 if (!context->getExtensions().requestExtension)
4605 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004606 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004607 return false;
4608 }
4609 break;
4610
4611 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004613 return false;
4614 }
4615
4616 return true;
4617}
4618
Geoff Lang47c48082016-12-07 15:38:13 -05004619bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4620{
4621 if (width <= 0.0f || isNaN(width))
4622 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004623 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004624 return false;
4625 }
4626
4627 return true;
4628}
4629
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004630bool ValidateVertexAttribPointer(ValidationContext *context,
4631 GLuint index,
4632 GLint size,
4633 GLenum type,
4634 GLboolean normalized,
4635 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004636 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004637{
Shao80957d92017-02-20 21:25:59 +08004638 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004639 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004640 return false;
4641 }
4642
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004643 if (stride < 0)
4644 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004645 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004646 return false;
4647 }
4648
Shao80957d92017-02-20 21:25:59 +08004649 const Caps &caps = context->getCaps();
4650 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004651 {
Shao80957d92017-02-20 21:25:59 +08004652 if (stride > caps.maxVertexAttribStride)
4653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004654 context->handleError(InvalidValue()
4655 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004656 return false;
4657 }
4658
4659 if (index >= caps.maxVertexAttribBindings)
4660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004661 context->handleError(InvalidValue()
4662 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004663 return false;
4664 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004665 }
4666
4667 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4668 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4669 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4670 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004671 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4672 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004673 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004675 context
4676 ->handleError(InvalidOperation()
4677 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004678 return false;
4679 }
4680
4681 if (context->getExtensions().webglCompatibility)
4682 {
4683 // WebGL 1.0 [Section 6.14] Fixed point support
4684 // The WebGL API does not support the GL_FIXED data type.
4685 if (type == GL_FIXED)
4686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004687 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004688 return false;
4689 }
4690
Geoff Lang2d62ab72017-03-23 16:54:40 -04004691 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004692 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004693 return false;
4694 }
4695 }
4696
4697 return true;
4698}
4699
Jamie Madill876429b2017-04-20 15:46:24 -04004700bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004701{
4702 if (context->getExtensions().webglCompatibility && zNear > zFar)
4703 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004705 return false;
4706 }
4707
4708 return true;
4709}
4710
Jamie Madille8fb6402017-02-14 17:56:40 -05004711bool ValidateRenderbufferStorage(ValidationContext *context,
4712 GLenum target,
4713 GLenum internalformat,
4714 GLsizei width,
4715 GLsizei height)
4716{
4717 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4718 height);
4719}
4720
4721bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4722 GLenum target,
4723 GLsizei samples,
4724 GLenum internalformat,
4725 GLsizei width,
4726 GLsizei height)
4727{
4728 if (!context->getExtensions().framebufferMultisample)
4729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004730 context->handleError(InvalidOperation()
4731 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004732 return false;
4733 }
4734
4735 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4736 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4737 // generated.
4738 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004740 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004741 return false;
4742 }
4743
4744 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4745 // the specified storage. This is different than ES 3.0 in which a sample number higher
4746 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4747 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4748 if (context->getClientMajorVersion() >= 3)
4749 {
4750 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4751 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004753 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004754 return false;
4755 }
4756 }
4757
4758 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4759 width, height);
4760}
4761
Jamie Madillc1d770e2017-04-13 17:31:24 -04004762bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4763{
4764 if (!ValidFramebufferTarget(target))
4765 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004767 return false;
4768 }
4769
4770 return true;
4771}
4772
4773bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004774 GLfloat red,
4775 GLfloat green,
4776 GLfloat blue,
4777 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004778{
4779 return true;
4780}
4781
Jamie Madill876429b2017-04-20 15:46:24 -04004782bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004783{
4784 return true;
4785}
4786
4787bool ValidateClearStencil(ValidationContext *context, GLint s)
4788{
4789 return true;
4790}
4791
4792bool ValidateColorMask(ValidationContext *context,
4793 GLboolean red,
4794 GLboolean green,
4795 GLboolean blue,
4796 GLboolean alpha)
4797{
4798 return true;
4799}
4800
4801bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4802{
4803 return true;
4804}
4805
4806bool ValidateCreateProgram(ValidationContext *context)
4807{
4808 return true;
4809}
4810
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004811bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004812{
4813 switch (mode)
4814 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004815 case CullFaceMode::Front:
4816 case CullFaceMode::Back:
4817 case CullFaceMode::FrontAndBack:
Jamie Madillc1d770e2017-04-13 17:31:24 -04004818 break;
4819
4820 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004821 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004822 return false;
4823 }
4824
4825 return true;
4826}
4827
4828bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4829{
4830 if (program == 0)
4831 {
4832 return false;
4833 }
4834
4835 if (!context->getProgram(program))
4836 {
4837 if (context->getShader(program))
4838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004840 return false;
4841 }
4842 else
4843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004844 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004845 return false;
4846 }
4847 }
4848
4849 return true;
4850}
4851
4852bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4853{
4854 if (shader == 0)
4855 {
4856 return false;
4857 }
4858
4859 if (!context->getShader(shader))
4860 {
4861 if (context->getProgram(shader))
4862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004864 return false;
4865 }
4866 else
4867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004868 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004869 return false;
4870 }
4871 }
4872
4873 return true;
4874}
4875
4876bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4877{
4878 switch (func)
4879 {
4880 case GL_NEVER:
4881 case GL_ALWAYS:
4882 case GL_LESS:
4883 case GL_LEQUAL:
4884 case GL_EQUAL:
4885 case GL_GREATER:
4886 case GL_GEQUAL:
4887 case GL_NOTEQUAL:
4888 break;
4889
4890 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004891 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004892 return false;
4893 }
4894
4895 return true;
4896}
4897
4898bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4899{
4900 return true;
4901}
4902
4903bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4904{
4905 Program *programObject = GetValidProgram(context, program);
4906 if (!programObject)
4907 {
4908 return false;
4909 }
4910
4911 Shader *shaderObject = GetValidShader(context, shader);
4912 if (!shaderObject)
4913 {
4914 return false;
4915 }
4916
4917 const Shader *attachedShader = nullptr;
4918
4919 switch (shaderObject->getType())
4920 {
4921 case GL_VERTEX_SHADER:
4922 {
4923 attachedShader = programObject->getAttachedVertexShader();
4924 break;
4925 }
4926 case GL_FRAGMENT_SHADER:
4927 {
4928 attachedShader = programObject->getAttachedFragmentShader();
4929 break;
4930 }
4931 case GL_COMPUTE_SHADER:
4932 {
4933 attachedShader = programObject->getAttachedComputeShader();
4934 break;
4935 }
4936 default:
4937 UNREACHABLE();
4938 return false;
4939 }
4940
4941 if (attachedShader != shaderObject)
4942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004943 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004944 return false;
4945 }
4946
4947 return true;
4948}
4949
4950bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4951{
4952 if (index >= MAX_VERTEX_ATTRIBS)
4953 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004954 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004955 return false;
4956 }
4957
4958 return true;
4959}
4960
4961bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4962{
4963 if (index >= MAX_VERTEX_ATTRIBS)
4964 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004965 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004966 return false;
4967 }
4968
4969 return true;
4970}
4971
4972bool ValidateFinish(ValidationContext *context)
4973{
4974 return true;
4975}
4976
4977bool ValidateFlush(ValidationContext *context)
4978{
4979 return true;
4980}
4981
4982bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4983{
4984 switch (mode)
4985 {
4986 case GL_CW:
4987 case GL_CCW:
4988 break;
4989 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004990 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004991 return false;
4992 }
4993
4994 return true;
4995}
4996
4997bool ValidateGetActiveAttrib(ValidationContext *context,
4998 GLuint program,
4999 GLuint index,
5000 GLsizei bufsize,
5001 GLsizei *length,
5002 GLint *size,
5003 GLenum *type,
5004 GLchar *name)
5005{
5006 if (bufsize < 0)
5007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005009 return false;
5010 }
5011
5012 Program *programObject = GetValidProgram(context, program);
5013
5014 if (!programObject)
5015 {
5016 return false;
5017 }
5018
5019 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5020 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005021 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005022 return false;
5023 }
5024
5025 return true;
5026}
5027
5028bool ValidateGetActiveUniform(ValidationContext *context,
5029 GLuint program,
5030 GLuint index,
5031 GLsizei bufsize,
5032 GLsizei *length,
5033 GLint *size,
5034 GLenum *type,
5035 GLchar *name)
5036{
5037 if (bufsize < 0)
5038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005039 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005040 return false;
5041 }
5042
5043 Program *programObject = GetValidProgram(context, program);
5044
5045 if (!programObject)
5046 {
5047 return false;
5048 }
5049
5050 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5051 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005052 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005053 return false;
5054 }
5055
5056 return true;
5057}
5058
5059bool ValidateGetAttachedShaders(ValidationContext *context,
5060 GLuint program,
5061 GLsizei maxcount,
5062 GLsizei *count,
5063 GLuint *shaders)
5064{
5065 if (maxcount < 0)
5066 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005067 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005068 return false;
5069 }
5070
5071 Program *programObject = GetValidProgram(context, program);
5072
5073 if (!programObject)
5074 {
5075 return false;
5076 }
5077
5078 return true;
5079}
5080
5081bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5082{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005083 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5084 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005085 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005087 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005088 return false;
5089 }
5090
Jamie Madillc1d770e2017-04-13 17:31:24 -04005091 Program *programObject = GetValidProgram(context, program);
5092
5093 if (!programObject)
5094 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005096 return false;
5097 }
5098
5099 if (!programObject->isLinked())
5100 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005101 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005102 return false;
5103 }
5104
5105 return true;
5106}
5107
5108bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5109{
5110 GLenum nativeType;
5111 unsigned int numParams = 0;
5112 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5113}
5114
5115bool ValidateGetError(ValidationContext *context)
5116{
5117 return true;
5118}
5119
5120bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5121{
5122 GLenum nativeType;
5123 unsigned int numParams = 0;
5124 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5125}
5126
5127bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5128{
5129 GLenum nativeType;
5130 unsigned int numParams = 0;
5131 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5132}
5133
5134bool ValidateGetProgramInfoLog(ValidationContext *context,
5135 GLuint program,
5136 GLsizei bufsize,
5137 GLsizei *length,
5138 GLchar *infolog)
5139{
5140 if (bufsize < 0)
5141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005142 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005143 return false;
5144 }
5145
5146 Program *programObject = GetValidProgram(context, program);
5147 if (!programObject)
5148 {
5149 return false;
5150 }
5151
5152 return true;
5153}
5154
5155bool ValidateGetShaderInfoLog(ValidationContext *context,
5156 GLuint shader,
5157 GLsizei bufsize,
5158 GLsizei *length,
5159 GLchar *infolog)
5160{
5161 if (bufsize < 0)
5162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005163 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005164 return false;
5165 }
5166
5167 Shader *shaderObject = GetValidShader(context, shader);
5168 if (!shaderObject)
5169 {
5170 return false;
5171 }
5172
5173 return true;
5174}
5175
5176bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5177 GLenum shadertype,
5178 GLenum precisiontype,
5179 GLint *range,
5180 GLint *precision)
5181{
5182 switch (shadertype)
5183 {
5184 case GL_VERTEX_SHADER:
5185 case GL_FRAGMENT_SHADER:
5186 break;
5187 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 context->handleError(InvalidOperation()
5189 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005190 return false;
5191 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005193 return false;
5194 }
5195
5196 switch (precisiontype)
5197 {
5198 case GL_LOW_FLOAT:
5199 case GL_MEDIUM_FLOAT:
5200 case GL_HIGH_FLOAT:
5201 case GL_LOW_INT:
5202 case GL_MEDIUM_INT:
5203 case GL_HIGH_INT:
5204 break;
5205
5206 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005208 return false;
5209 }
5210
5211 return true;
5212}
5213
5214bool ValidateGetShaderSource(ValidationContext *context,
5215 GLuint shader,
5216 GLsizei bufsize,
5217 GLsizei *length,
5218 GLchar *source)
5219{
5220 if (bufsize < 0)
5221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005223 return false;
5224 }
5225
5226 Shader *shaderObject = GetValidShader(context, shader);
5227 if (!shaderObject)
5228 {
5229 return false;
5230 }
5231
5232 return true;
5233}
5234
5235bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5236{
5237 if (strstr(name, "gl_") == name)
5238 {
5239 return false;
5240 }
5241
Geoff Langfc32e8b2017-05-31 14:16:59 -04005242 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5243 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005244 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005246 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005247 return false;
5248 }
5249
Jamie Madillc1d770e2017-04-13 17:31:24 -04005250 Program *programObject = GetValidProgram(context, program);
5251
5252 if (!programObject)
5253 {
5254 return false;
5255 }
5256
5257 if (!programObject->isLinked())
5258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005260 return false;
5261 }
5262
5263 return true;
5264}
5265
5266bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5267{
5268 switch (mode)
5269 {
5270 case GL_FASTEST:
5271 case GL_NICEST:
5272 case GL_DONT_CARE:
5273 break;
5274
5275 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005277 return false;
5278 }
5279
5280 switch (target)
5281 {
5282 case GL_GENERATE_MIPMAP_HINT:
5283 break;
5284
Geoff Lange7bd2182017-06-16 16:13:13 -04005285 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5286 if (context->getClientVersion() < ES_3_0 &&
5287 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005288 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005289 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005290 return false;
5291 }
5292 break;
5293
5294 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005295 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005296 return false;
5297 }
5298
5299 return true;
5300}
5301
5302bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5303{
5304 return true;
5305}
5306
5307bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5308{
5309 return true;
5310}
5311
5312bool ValidateIsProgram(ValidationContext *context, GLuint program)
5313{
5314 return true;
5315}
5316
5317bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5318{
5319 return true;
5320}
5321
5322bool ValidateIsShader(ValidationContext *context, GLuint shader)
5323{
5324 return true;
5325}
5326
5327bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5328{
5329 return true;
5330}
5331
5332bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5333{
5334 if (context->getClientMajorVersion() < 3)
5335 {
5336 switch (pname)
5337 {
5338 case GL_UNPACK_IMAGE_HEIGHT:
5339 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005340 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005341 return false;
5342
5343 case GL_UNPACK_ROW_LENGTH:
5344 case GL_UNPACK_SKIP_ROWS:
5345 case GL_UNPACK_SKIP_PIXELS:
5346 if (!context->getExtensions().unpackSubimage)
5347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005348 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005349 return false;
5350 }
5351 break;
5352
5353 case GL_PACK_ROW_LENGTH:
5354 case GL_PACK_SKIP_ROWS:
5355 case GL_PACK_SKIP_PIXELS:
5356 if (!context->getExtensions().packSubimage)
5357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005358 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005359 return false;
5360 }
5361 break;
5362 }
5363 }
5364
5365 if (param < 0)
5366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005367 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005368 return false;
5369 }
5370
5371 switch (pname)
5372 {
5373 case GL_UNPACK_ALIGNMENT:
5374 if (param != 1 && param != 2 && param != 4 && param != 8)
5375 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005376 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005377 return false;
5378 }
5379 break;
5380
5381 case GL_PACK_ALIGNMENT:
5382 if (param != 1 && param != 2 && param != 4 && param != 8)
5383 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005384 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005385 return false;
5386 }
5387 break;
5388
5389 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005390 if (!context->getExtensions().packReverseRowOrder)
5391 {
5392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5393 }
5394 break;
5395
Jamie Madillc1d770e2017-04-13 17:31:24 -04005396 case GL_UNPACK_ROW_LENGTH:
5397 case GL_UNPACK_IMAGE_HEIGHT:
5398 case GL_UNPACK_SKIP_IMAGES:
5399 case GL_UNPACK_SKIP_ROWS:
5400 case GL_UNPACK_SKIP_PIXELS:
5401 case GL_PACK_ROW_LENGTH:
5402 case GL_PACK_SKIP_ROWS:
5403 case GL_PACK_SKIP_PIXELS:
5404 break;
5405
5406 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005408 return false;
5409 }
5410
5411 return true;
5412}
5413
5414bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5415{
5416 return true;
5417}
5418
5419bool ValidateReleaseShaderCompiler(ValidationContext *context)
5420{
5421 return true;
5422}
5423
Jamie Madill876429b2017-04-20 15:46:24 -04005424bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005425{
5426 return true;
5427}
5428
5429bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5430{
5431 if (width < 0 || height < 0)
5432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005433 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005434 return false;
5435 }
5436
5437 return true;
5438}
5439
5440bool ValidateShaderBinary(ValidationContext *context,
5441 GLsizei n,
5442 const GLuint *shaders,
5443 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005444 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005445 GLsizei length)
5446{
5447 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5448 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5449 shaderBinaryFormats.end())
5450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005451 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005452 return false;
5453 }
5454
5455 return true;
5456}
5457
5458bool ValidateShaderSource(ValidationContext *context,
5459 GLuint shader,
5460 GLsizei count,
5461 const GLchar *const *string,
5462 const GLint *length)
5463{
5464 if (count < 0)
5465 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005466 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005467 return false;
5468 }
5469
Geoff Langfc32e8b2017-05-31 14:16:59 -04005470 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5471 // shader-related entry points
5472 if (context->getExtensions().webglCompatibility)
5473 {
5474 for (GLsizei i = 0; i < count; i++)
5475 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005476 size_t len =
5477 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005478
5479 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005480 if (!IsValidESSLShaderSourceString(string[i], len,
5481 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005484 return false;
5485 }
5486 }
5487 }
5488
Jamie Madillc1d770e2017-04-13 17:31:24 -04005489 Shader *shaderObject = GetValidShader(context, shader);
5490 if (!shaderObject)
5491 {
5492 return false;
5493 }
5494
5495 return true;
5496}
5497
5498bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5499{
5500 if (!IsValidStencilFunc(func))
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 return true;
5507}
5508
5509bool ValidateStencilFuncSeparate(ValidationContext *context,
5510 GLenum face,
5511 GLenum func,
5512 GLint ref,
5513 GLuint mask)
5514{
5515 if (!IsValidStencilFace(face))
5516 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005517 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005518 return false;
5519 }
5520
5521 if (!IsValidStencilFunc(func))
5522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005524 return false;
5525 }
5526
5527 return true;
5528}
5529
5530bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5531{
5532 return true;
5533}
5534
5535bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5536{
5537 if (!IsValidStencilFace(face))
5538 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005539 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005540 return false;
5541 }
5542
5543 return true;
5544}
5545
5546bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5547{
5548 if (!IsValidStencilOp(fail))
5549 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005550 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005551 return false;
5552 }
5553
5554 if (!IsValidStencilOp(zfail))
5555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005557 return false;
5558 }
5559
5560 if (!IsValidStencilOp(zpass))
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 true;
5567}
5568
5569bool ValidateStencilOpSeparate(ValidationContext *context,
5570 GLenum face,
5571 GLenum fail,
5572 GLenum zfail,
5573 GLenum zpass)
5574{
5575 if (!IsValidStencilFace(face))
5576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005578 return false;
5579 }
5580
5581 return ValidateStencilOp(context, fail, zfail, zpass);
5582}
5583
5584bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5585{
5586 return ValidateUniform(context, GL_FLOAT, location, 1);
5587}
5588
5589bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5590{
5591 return ValidateUniform(context, GL_FLOAT, location, count);
5592}
5593
Jamie Madillbe849e42017-05-02 15:49:00 -04005594bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5595{
5596 return ValidateUniform1iv(context, location, 1, &x);
5597}
5598
Jamie Madillc1d770e2017-04-13 17:31:24 -04005599bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5600{
5601 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5602}
5603
5604bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5605{
5606 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5607}
5608
5609bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5610{
5611 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5612}
5613
5614bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5615{
5616 return ValidateUniform(context, GL_INT_VEC2, location, count);
5617}
5618
5619bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5620{
5621 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5622}
5623
5624bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5625{
5626 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5627}
5628
5629bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5630{
5631 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5632}
5633
5634bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5635{
5636 return ValidateUniform(context, GL_INT_VEC3, location, count);
5637}
5638
5639bool ValidateUniform4f(ValidationContext *context,
5640 GLint location,
5641 GLfloat x,
5642 GLfloat y,
5643 GLfloat z,
5644 GLfloat w)
5645{
5646 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5647}
5648
5649bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5650{
5651 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5652}
5653
5654bool ValidateUniform4i(ValidationContext *context,
5655 GLint location,
5656 GLint x,
5657 GLint y,
5658 GLint z,
5659 GLint w)
5660{
5661 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5662}
5663
5664bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5665{
5666 return ValidateUniform(context, GL_INT_VEC4, location, count);
5667}
5668
5669bool ValidateUniformMatrix2fv(ValidationContext *context,
5670 GLint location,
5671 GLsizei count,
5672 GLboolean transpose,
5673 const GLfloat *value)
5674{
5675 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5676}
5677
5678bool ValidateUniformMatrix3fv(ValidationContext *context,
5679 GLint location,
5680 GLsizei count,
5681 GLboolean transpose,
5682 const GLfloat *value)
5683{
5684 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5685}
5686
5687bool ValidateUniformMatrix4fv(ValidationContext *context,
5688 GLint location,
5689 GLsizei count,
5690 GLboolean transpose,
5691 const GLfloat *value)
5692{
5693 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5694}
5695
5696bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5697{
5698 Program *programObject = GetValidProgram(context, program);
5699
5700 if (!programObject)
5701 {
5702 return false;
5703 }
5704
5705 return true;
5706}
5707
Jamie Madillc1d770e2017-04-13 17:31:24 -04005708bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5709{
5710 return ValidateVertexAttribIndex(context, index);
5711}
5712
5713bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5714{
5715 return ValidateVertexAttribIndex(context, index);
5716}
5717
5718bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5719{
5720 return ValidateVertexAttribIndex(context, index);
5721}
5722
5723bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5724{
5725 return ValidateVertexAttribIndex(context, index);
5726}
5727
5728bool ValidateVertexAttrib3f(ValidationContext *context,
5729 GLuint index,
5730 GLfloat x,
5731 GLfloat y,
5732 GLfloat z)
5733{
5734 return ValidateVertexAttribIndex(context, index);
5735}
5736
5737bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5738{
5739 return ValidateVertexAttribIndex(context, index);
5740}
5741
5742bool ValidateVertexAttrib4f(ValidationContext *context,
5743 GLuint index,
5744 GLfloat x,
5745 GLfloat y,
5746 GLfloat z,
5747 GLfloat w)
5748{
5749 return ValidateVertexAttribIndex(context, index);
5750}
5751
5752bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5753{
5754 return ValidateVertexAttribIndex(context, index);
5755}
5756
5757bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5758{
5759 if (width < 0 || height < 0)
5760 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005761 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005762 return false;
5763 }
5764
5765 return true;
5766}
5767
5768bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5769{
5770 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5771}
5772
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005773bool ValidateDrawElements(ValidationContext *context,
5774 GLenum mode,
5775 GLsizei count,
5776 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005777 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005778{
5779 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5780}
5781
Jamie Madillbe849e42017-05-02 15:49:00 -04005782bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5783 GLenum target,
5784 GLenum attachment,
5785 GLenum pname,
5786 GLint *params)
5787{
5788 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5789 nullptr);
5790}
5791
5792bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5793{
5794 return ValidateGetProgramivBase(context, program, pname, nullptr);
5795}
5796
5797bool ValidateCopyTexImage2D(ValidationContext *context,
5798 GLenum target,
5799 GLint level,
5800 GLenum internalformat,
5801 GLint x,
5802 GLint y,
5803 GLsizei width,
5804 GLsizei height,
5805 GLint border)
5806{
5807 if (context->getClientMajorVersion() < 3)
5808 {
5809 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5810 0, x, y, width, height, border);
5811 }
5812
5813 ASSERT(context->getClientMajorVersion() == 3);
5814 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5815 0, x, y, width, height, border);
5816}
5817
5818bool ValidateCopyTexSubImage2D(Context *context,
5819 GLenum target,
5820 GLint level,
5821 GLint xoffset,
5822 GLint yoffset,
5823 GLint x,
5824 GLint y,
5825 GLsizei width,
5826 GLsizei height)
5827{
5828 if (context->getClientMajorVersion() < 3)
5829 {
5830 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5831 yoffset, x, y, width, height, 0);
5832 }
5833
5834 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5835 yoffset, 0, x, y, width, height, 0);
5836}
5837
5838bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5839{
5840 return ValidateGenOrDelete(context, n);
5841}
5842
5843bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5844{
5845 return ValidateGenOrDelete(context, n);
5846}
5847
5848bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5849{
5850 return ValidateGenOrDelete(context, n);
5851}
5852
5853bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5854{
5855 return ValidateGenOrDelete(context, n);
5856}
5857
5858bool ValidateDisable(Context *context, GLenum cap)
5859{
5860 if (!ValidCap(context, cap, false))
5861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005862 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005863 return false;
5864 }
5865
5866 return true;
5867}
5868
5869bool ValidateEnable(Context *context, GLenum cap)
5870{
5871 if (!ValidCap(context, cap, false))
5872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005873 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005874 return false;
5875 }
5876
5877 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5878 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5879 {
5880 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005881 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005882
5883 // We also output an error message to the debugger window if tracing is active, so that
5884 // developers can see the error message.
5885 ERR() << errorMessage;
5886 return false;
5887 }
5888
5889 return true;
5890}
5891
5892bool ValidateFramebufferRenderbuffer(Context *context,
5893 GLenum target,
5894 GLenum attachment,
5895 GLenum renderbuffertarget,
5896 GLuint renderbuffer)
5897{
Brandon Jones6cad5662017-06-14 13:25:13 -07005898 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5901 return false;
5902 }
5903
5904 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5905 {
5906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005907 return false;
5908 }
5909
5910 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5911 renderbuffertarget, renderbuffer);
5912}
5913
5914bool ValidateFramebufferTexture2D(Context *context,
5915 GLenum target,
5916 GLenum attachment,
5917 GLenum textarget,
5918 GLuint texture,
5919 GLint level)
5920{
5921 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5922 // extension
5923 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5924 level != 0)
5925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005926 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005927 return false;
5928 }
5929
5930 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5931 {
5932 return false;
5933 }
5934
5935 if (texture != 0)
5936 {
5937 gl::Texture *tex = context->getTexture(texture);
5938 ASSERT(tex);
5939
5940 const gl::Caps &caps = context->getCaps();
5941
5942 switch (textarget)
5943 {
5944 case GL_TEXTURE_2D:
5945 {
5946 if (level > gl::log2(caps.max2DTextureSize))
5947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005948 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005949 return false;
5950 }
5951 if (tex->getTarget() != GL_TEXTURE_2D)
5952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005953 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005954 return false;
5955 }
5956 }
5957 break;
5958
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005959 case GL_TEXTURE_RECTANGLE_ANGLE:
5960 {
5961 if (level != 0)
5962 {
5963 context->handleError(InvalidValue());
5964 return false;
5965 }
5966 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5967 {
5968 context->handleError(InvalidOperation()
5969 << "Textarget must match the texture target type.");
5970 return false;
5971 }
5972 }
5973 break;
5974
Jamie Madillbe849e42017-05-02 15:49:00 -04005975 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5976 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5977 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5978 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5979 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5980 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5981 {
5982 if (level > gl::log2(caps.maxCubeMapTextureSize))
5983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005984 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005985 return false;
5986 }
5987 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005989 context->handleError(InvalidOperation()
5990 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 return false;
5992 }
5993 }
5994 break;
5995
5996 case GL_TEXTURE_2D_MULTISAMPLE:
5997 {
5998 if (context->getClientVersion() < ES_3_1)
5999 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04006001 return false;
6002 }
6003
6004 if (level != 0)
6005 {
Brandon Jonesafa75152017-07-21 13:11:29 -07006006 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04006007 return false;
6008 }
6009 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
6010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006011 context->handleError(InvalidOperation()
6012 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006013 return false;
6014 }
6015 }
6016 break;
6017
6018 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006019 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006020 return false;
6021 }
6022
6023 const Format &format = tex->getFormat(textarget, level);
6024 if (format.info->compressed)
6025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006026 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 return false;
6028 }
6029 }
6030
6031 return true;
6032}
6033
6034bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6035{
6036 return ValidateGenOrDelete(context, n);
6037}
6038
6039bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6040{
6041 return ValidateGenOrDelete(context, n);
6042}
6043
6044bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6045{
6046 return ValidateGenOrDelete(context, n);
6047}
6048
6049bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6050{
6051 return ValidateGenOrDelete(context, n);
6052}
6053
6054bool ValidateGenerateMipmap(Context *context, GLenum target)
6055{
6056 if (!ValidTextureTarget(context, target))
6057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006059 return false;
6060 }
6061
6062 Texture *texture = context->getTargetTexture(target);
6063
6064 if (texture == nullptr)
6065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006067 return false;
6068 }
6069
6070 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6071
6072 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6073 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6074 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006076 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006077 return false;
6078 }
6079
6080 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006081 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6082 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6083 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006084 {
6085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6086 return false;
6087 }
6088
Geoff Lang536eca12017-09-13 11:23:35 -04006089 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6090 bool formatUnsized = !format.sized;
6091 bool formatColorRenderableAndFilterable =
6092 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6093 format.renderSupport(context->getClientVersion(), context->getExtensions());
6094 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006095 {
Geoff Lang536eca12017-09-13 11:23:35 -04006096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006097 return false;
6098 }
6099
Geoff Lang536eca12017-09-13 11:23:35 -04006100 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6101 // generation
6102 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6103 {
6104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6105 return false;
6106 }
6107
6108 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6109 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006110 bool supportsSRGBMipmapGeneration =
6111 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006112 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006113 {
Geoff Lang536eca12017-09-13 11:23:35 -04006114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006115 return false;
6116 }
6117
6118 // Non-power of 2 ES2 check
6119 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6120 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6121 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6122 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006123 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6124 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006126 return false;
6127 }
6128
6129 // Cube completeness check
6130 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6131 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006133 return false;
6134 }
6135
6136 return true;
6137}
6138
6139bool ValidateGetBufferParameteriv(ValidationContext *context,
6140 GLenum target,
6141 GLenum pname,
6142 GLint *params)
6143{
6144 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6145}
6146
6147bool ValidateGetRenderbufferParameteriv(Context *context,
6148 GLenum target,
6149 GLenum pname,
6150 GLint *params)
6151{
6152 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6153}
6154
6155bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6156{
6157 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6158}
6159
6160bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6161{
6162 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6163}
6164
6165bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6166{
6167 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6168}
6169
6170bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6171{
6172 return ValidateGetUniformBase(context, program, location);
6173}
6174
6175bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6176{
6177 return ValidateGetUniformBase(context, program, location);
6178}
6179
6180bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6181{
6182 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6183}
6184
6185bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6186{
6187 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6188}
6189
6190bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6191{
6192 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6193}
6194
6195bool ValidateIsEnabled(Context *context, GLenum cap)
6196{
6197 if (!ValidCap(context, cap, true))
6198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006200 return false;
6201 }
6202
6203 return true;
6204}
6205
6206bool ValidateLinkProgram(Context *context, GLuint program)
6207{
6208 if (context->hasActiveTransformFeedback(program))
6209 {
6210 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006211 context->handleError(InvalidOperation() << "Cannot link program while program is "
6212 "associated with an active transform "
6213 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006214 return false;
6215 }
6216
6217 Program *programObject = GetValidProgram(context, program);
6218 if (!programObject)
6219 {
6220 return false;
6221 }
6222
6223 return true;
6224}
6225
Jamie Madill4928b7c2017-06-20 12:57:39 -04006226bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006227 GLint x,
6228 GLint y,
6229 GLsizei width,
6230 GLsizei height,
6231 GLenum format,
6232 GLenum type,
6233 void *pixels)
6234{
6235 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6236 nullptr, pixels);
6237}
6238
6239bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6240{
6241 return ValidateTexParameterBase(context, target, pname, -1, &param);
6242}
6243
6244bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6245{
6246 return ValidateTexParameterBase(context, target, pname, -1, params);
6247}
6248
6249bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6250{
6251 return ValidateTexParameterBase(context, target, pname, -1, &param);
6252}
6253
6254bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6255{
6256 return ValidateTexParameterBase(context, target, pname, -1, params);
6257}
6258
6259bool ValidateUseProgram(Context *context, GLuint program)
6260{
6261 if (program != 0)
6262 {
6263 Program *programObject = context->getProgram(program);
6264 if (!programObject)
6265 {
6266 // ES 3.1.0 section 7.3 page 72
6267 if (context->getShader(program))
6268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006270 return false;
6271 }
6272 else
6273 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006274 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006275 return false;
6276 }
6277 }
6278 if (!programObject->isLinked())
6279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006281 return false;
6282 }
6283 }
6284 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6285 {
6286 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006287 context
6288 ->handleError(InvalidOperation()
6289 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006290 return false;
6291 }
6292
6293 return true;
6294}
6295
Jamie Madillc29968b2016-01-20 11:17:23 -05006296} // namespace gl