blob: 3ad049cf5e7434bf4c7c2c7599a5c65364060d16 [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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050079 context->handleError(InvalidOperation() << "No such path object.");
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 Lang4f0e0032017-05-01 16:04:35 -0400293 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
294 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700295 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400296 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700297 }
298
299 return true;
300}
301
Geoff Lang4f0e0032017-05-01 16:04:35 -0400302bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700303{
304 switch (target)
305 {
306 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400307 return textureType == GL_TEXTURE_2D;
308
309 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
310 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
311 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
312 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
313 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
314 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
315 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700316
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400317 case GL_TEXTURE_RECTANGLE_ANGLE:
318 return textureType == GL_TEXTURE_RECTANGLE_ANGLE &&
319 context->getExtensions().textureRectangle;
Geoff Lang97073d12016-04-20 10:42:34 -0700320
321 default:
322 return false;
323 }
324}
325
326bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
327{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400328 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700329 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400330 case GL_TEXTURE_2D:
331 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400332 case GL_TEXTURE_RECTANGLE_ANGLE:
333 return context->getExtensions().textureRectangle;
Geoff Lang4f0e0032017-05-01 16:04:35 -0400334
335 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
336 // supported
337
338 default:
339 return false;
340 }
341}
342
343bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
344{
Geoff Lang3847f942017-07-12 11:17:28 -0400345 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400346 {
347 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700348 }
349
Geoff Lang4f0e0032017-05-01 16:04:35 -0400350 if (level > 0 && context->getClientVersion() < ES_3_0)
351 {
352 return false;
353 }
Geoff Lang97073d12016-04-20 10:42:34 -0700354
Geoff Lang4f0e0032017-05-01 16:04:35 -0400355 return true;
356}
357
358bool IsValidCopyTextureDestinationLevel(Context *context,
359 GLenum target,
360 GLint level,
361 GLsizei width,
362 GLsizei height)
363{
Geoff Lang3847f942017-07-12 11:17:28 -0400364 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400365 {
366 return false;
367 }
368
Geoff Lang4f0e0032017-05-01 16:04:35 -0400369 const Caps &caps = context->getCaps();
370 if (target == GL_TEXTURE_2D)
371 {
372 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
373 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
374 {
375 return false;
376 }
377 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400378 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
379 {
380 ASSERT(level == 0);
381 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
382 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
383 {
384 return false;
385 }
386 }
Geoff Lang4f0e0032017-05-01 16:04:35 -0400387 else if (IsCubeMapTextureTarget(target))
388 {
389 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
390 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
391 {
392 return false;
393 }
394 }
395
396 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700397}
398
Jamie Madillc1d770e2017-04-13 17:31:24 -0400399bool IsValidStencilFunc(GLenum func)
400{
401 switch (func)
402 {
403 case GL_NEVER:
404 case GL_ALWAYS:
405 case GL_LESS:
406 case GL_LEQUAL:
407 case GL_EQUAL:
408 case GL_GEQUAL:
409 case GL_GREATER:
410 case GL_NOTEQUAL:
411 return true;
412
413 default:
414 return false;
415 }
416}
417
418bool IsValidStencilFace(GLenum face)
419{
420 switch (face)
421 {
422 case GL_FRONT:
423 case GL_BACK:
424 case GL_FRONT_AND_BACK:
425 return true;
426
427 default:
428 return false;
429 }
430}
431
432bool IsValidStencilOp(GLenum op)
433{
434 switch (op)
435 {
436 case GL_ZERO:
437 case GL_KEEP:
438 case GL_REPLACE:
439 case GL_INCR:
440 case GL_DECR:
441 case GL_INVERT:
442 case GL_INCR_WRAP:
443 case GL_DECR_WRAP:
444 return true;
445
446 default:
447 return false;
448 }
449}
450
Jamie Madillbe849e42017-05-02 15:49:00 -0400451bool ValidateES2CopyTexImageParameters(ValidationContext *context,
452 GLenum target,
453 GLint level,
454 GLenum internalformat,
455 bool isSubImage,
456 GLint xoffset,
457 GLint yoffset,
458 GLint x,
459 GLint y,
460 GLsizei width,
461 GLsizei height,
462 GLint border)
463{
464 if (!ValidTexture2DDestinationTarget(context, target))
465 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700466 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400467 return false;
468 }
469
470 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500472 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400473 return false;
474 }
475
476 Format textureFormat = Format::Invalid();
477 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
478 xoffset, yoffset, 0, x, y, width, height, border,
479 &textureFormat))
480 {
481 return false;
482 }
483
484 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
485 GLenum colorbufferFormat =
486 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
487 const auto &formatInfo = *textureFormat.info;
488
489 // [OpenGL ES 2.0.24] table 3.9
490 if (isSubImage)
491 {
492 switch (formatInfo.format)
493 {
494 case GL_ALPHA:
495 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400496 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
497 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400498 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400500 return false;
501 }
502 break;
503 case GL_LUMINANCE:
504 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
505 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
506 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400507 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
508 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400509 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700510 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400511 return false;
512 }
513 break;
514 case GL_RED_EXT:
515 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
516 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
517 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
518 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
519 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400520 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
521 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400522 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400524 return false;
525 }
526 break;
527 case GL_RG_EXT:
528 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
529 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
530 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
531 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400532 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
533 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400534 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400536 return false;
537 }
538 break;
539 case GL_RGB:
540 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
541 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
542 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400543 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
544 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400545 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400547 return false;
548 }
549 break;
550 case GL_LUMINANCE_ALPHA:
551 case GL_RGBA:
552 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400553 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
554 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400555 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400557 return false;
558 }
559 break;
560 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
561 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
562 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
563 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
564 case GL_ETC1_RGB8_OES:
565 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
566 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
567 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
568 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
569 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700570 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400571 return false;
572 case GL_DEPTH_COMPONENT:
573 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700574 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400575 return false;
576 default:
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 }
580
581 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
582 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400584 return false;
585 }
586 }
587 else
588 {
589 switch (internalformat)
590 {
591 case GL_ALPHA:
592 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
593 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
594 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
595 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400597 return false;
598 }
599 break;
600 case GL_LUMINANCE:
601 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
602 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
603 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
604 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
605 colorbufferFormat != GL_BGR5_A1_ANGLEX)
606 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400608 return false;
609 }
610 break;
611 case GL_RED_EXT:
612 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
613 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
614 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
615 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
616 colorbufferFormat != GL_BGR5_A1_ANGLEX)
617 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400619 return false;
620 }
621 break;
622 case GL_RG_EXT:
623 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
624 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
625 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
626 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
627 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400629 return false;
630 }
631 break;
632 case GL_RGB:
633 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
634 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
635 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
636 colorbufferFormat != GL_BGR5_A1_ANGLEX)
637 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400639 return false;
640 }
641 break;
642 case GL_LUMINANCE_ALPHA:
643 case GL_RGBA:
644 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
645 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
646 colorbufferFormat != GL_BGR5_A1_ANGLEX)
647 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400649 return false;
650 }
651 break;
652 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
653 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
654 if (context->getExtensions().textureCompressionDXT1)
655 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400657 return false;
658 }
659 else
660 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400662 return false;
663 }
664 break;
665 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
666 if (context->getExtensions().textureCompressionDXT3)
667 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400669 return false;
670 }
671 else
672 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700673 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400674 return false;
675 }
676 break;
677 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
678 if (context->getExtensions().textureCompressionDXT5)
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400681 return false;
682 }
683 else
684 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400686 return false;
687 }
688 break;
689 case GL_ETC1_RGB8_OES:
690 if (context->getExtensions().compressedETC1RGB8Texture)
691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500692 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400693 return false;
694 }
695 else
696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500697 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400698 return false;
699 }
700 break;
701 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
702 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
703 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
704 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
705 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
706 if (context->getExtensions().lossyETCDecode)
707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500708 context->handleError(InvalidOperation()
709 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400710 return false;
711 }
712 else
713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500714 context->handleError(InvalidEnum()
715 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400716 return false;
717 }
718 break;
719 case GL_DEPTH_COMPONENT:
720 case GL_DEPTH_COMPONENT16:
721 case GL_DEPTH_COMPONENT32_OES:
722 case GL_DEPTH_STENCIL_OES:
723 case GL_DEPTH24_STENCIL8_OES:
724 if (context->getExtensions().depthTextures)
725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400727 return false;
728 }
729 else
730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500731 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400732 return false;
733 }
734 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500735 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400736 return false;
737 }
738 }
739
740 // If width or height is zero, it is a no-op. Return false without setting an error.
741 return (width > 0 && height > 0);
742}
743
744bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
745{
746 switch (cap)
747 {
748 // EXT_multisample_compatibility
749 case GL_MULTISAMPLE_EXT:
750 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
751 return context->getExtensions().multisampleCompatibility;
752
753 case GL_CULL_FACE:
754 case GL_POLYGON_OFFSET_FILL:
755 case GL_SAMPLE_ALPHA_TO_COVERAGE:
756 case GL_SAMPLE_COVERAGE:
757 case GL_SCISSOR_TEST:
758 case GL_STENCIL_TEST:
759 case GL_DEPTH_TEST:
760 case GL_BLEND:
761 case GL_DITHER:
762 return true;
763
764 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
765 case GL_RASTERIZER_DISCARD:
766 return (context->getClientMajorVersion() >= 3);
767
768 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
769 case GL_DEBUG_OUTPUT:
770 return context->getExtensions().debug;
771
772 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
773 return queryOnly && context->getExtensions().bindGeneratesResource;
774
775 case GL_CLIENT_ARRAYS_ANGLE:
776 return queryOnly && context->getExtensions().clientArrays;
777
778 case GL_FRAMEBUFFER_SRGB_EXT:
779 return context->getExtensions().sRGBWriteControl;
780
781 case GL_SAMPLE_MASK:
782 return context->getClientVersion() >= Version(3, 1);
783
784 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
785 return queryOnly && context->getExtensions().robustResourceInitialization;
786
787 default:
788 return false;
789 }
790}
791
Geoff Langfc32e8b2017-05-31 14:16:59 -0400792// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
793// 3.1.
Geoff Langcab92ee2017-07-19 17:32:07 -0400794bool IsValidESSLCharacter(unsigned char c)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400795{
796 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langcab92ee2017-07-19 17:32:07 -0400797 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
798 c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400799 {
800 return true;
801 }
802
803 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
804 if (c >= 9 && c <= 13)
805 {
806 return true;
807 }
808
809 return false;
810}
811
Geoff Langcab92ee2017-07-19 17:32:07 -0400812bool IsValidESSLString(const char *str, size_t len)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400813{
Geoff Langa71a98e2017-06-19 15:15:00 -0400814 for (size_t i = 0; i < len; i++)
815 {
Geoff Langcab92ee2017-07-19 17:32:07 -0400816 if (!IsValidESSLCharacter(str[i]))
Geoff Langa71a98e2017-06-19 15:15:00 -0400817 {
818 return false;
819 }
820 }
821
822 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400823}
824
Geoff Langcab92ee2017-07-19 17:32:07 -0400825bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
826{
827 enum class ParseState
828 {
829 // Have not seen an ASCII non-whitespace character yet on
830 // this line. Possible that we might see a preprocessor
831 // directive.
832 BEGINING_OF_LINE,
833
834 // Have seen at least one ASCII non-whitespace character
835 // on this line.
836 MIDDLE_OF_LINE,
837
838 // Handling a preprocessor directive. Passes through all
839 // characters up to the end of the line. Disables comment
840 // processing.
841 IN_PREPROCESSOR_DIRECTIVE,
842
843 // Handling a single-line comment. The comment text is
844 // replaced with a single space.
845 IN_SINGLE_LINE_COMMENT,
846
847 // Handling a multi-line comment. Newlines are passed
848 // through to preserve line numbers.
849 IN_MULTI_LINE_COMMENT
850 };
851
852 ParseState state = ParseState::BEGINING_OF_LINE;
853 size_t pos = 0;
854
855 while (pos < len)
856 {
857 char c = str[pos];
858 char next = pos + 1 < len ? str[pos + 1] : 0;
859
860 // Check for newlines
861 if (c == '\n' || c == '\r')
862 {
863 if (state != ParseState::IN_MULTI_LINE_COMMENT)
864 {
865 state = ParseState::BEGINING_OF_LINE;
866 }
867
868 pos++;
869 continue;
870 }
871
872 switch (state)
873 {
874 case ParseState::BEGINING_OF_LINE:
875 if (c == ' ')
876 {
877 // Maintain the BEGINING_OF_LINE state until a non-space is seen
878 pos++;
879 }
880 else if (c == '#')
881 {
882 state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
883 pos++;
884 }
885 else
886 {
887 // Don't advance, re-process this character with the MIDDLE_OF_LINE state
888 state = ParseState::MIDDLE_OF_LINE;
889 }
890 break;
891
892 case ParseState::MIDDLE_OF_LINE:
893 if (c == '/' && next == '/')
894 {
895 state = ParseState::IN_SINGLE_LINE_COMMENT;
896 pos++;
897 }
898 else if (c == '/' && next == '*')
899 {
900 state = ParseState::IN_MULTI_LINE_COMMENT;
901 pos++;
902 }
903 else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
904 {
905 // Skip line continuation characters
906 }
907 else if (!IsValidESSLCharacter(c))
908 {
909 return false;
910 }
911 pos++;
912 break;
913
914 case ParseState::IN_PREPROCESSOR_DIRECTIVE:
915 // No matter what the character is, just pass it
916 // through. Do not parse comments in this state.
917 pos++;
918 break;
919
920 case ParseState::IN_SINGLE_LINE_COMMENT:
921 // Line-continuation characters are processed before comment processing.
922 // Advance string if a new line character is immediately behind
923 // line-continuation character.
924 if (c == '\\' && (next == '\n' || next == '\r'))
925 {
926 pos++;
927 }
928 pos++;
929 break;
930
931 case ParseState::IN_MULTI_LINE_COMMENT:
932 if (c == '*' && next == '/')
933 {
934 state = ParseState::MIDDLE_OF_LINE;
935 pos++;
936 }
937 pos++;
938 break;
939 }
940 }
941
942 return true;
943}
944
Jamie Madillc29968b2016-01-20 11:17:23 -0500945} // anonymous namespace
946
Geoff Langff5b2d52016-09-07 11:32:23 -0400947bool ValidateES2TexImageParameters(Context *context,
948 GLenum target,
949 GLint level,
950 GLenum internalformat,
951 bool isCompressed,
952 bool isSubImage,
953 GLint xoffset,
954 GLint yoffset,
955 GLsizei width,
956 GLsizei height,
957 GLint border,
958 GLenum format,
959 GLenum type,
960 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400961 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962{
Jamie Madill6f38f822014-06-06 17:12:20 -0400963 if (!ValidTexture2DDestinationTarget(context, target))
964 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -0400966 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400967 }
968
Austin Kinross08528e12015-10-07 16:24:40 -0700969 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400972 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973 }
974
Brandon Jones6cad5662017-06-14 13:25:13 -0700975 if (!ValidMipLevel(context, target, level))
976 {
977 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
978 return false;
979 }
980
981 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400982 std::numeric_limits<GLsizei>::max() - yoffset < height)
983 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700984 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -0400985 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400986 }
987
Geoff Lang6e898aa2017-06-02 11:17:26 -0400988 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
989 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
990 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
991 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
992 // case.
993 bool nonEqualFormatsAllowed =
994 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
995 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
996
997 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500999 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001000 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001001 }
1002
Geoff Langaae65a42014-05-26 12:43:44 -04001003 const gl::Caps &caps = context->getCaps();
1004
Geoff Langa9be0dc2014-12-17 12:34:40 -05001005 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001006 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001007 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
1008 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001010 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001011 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001013 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001014 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
1015 {
1016 ASSERT(level == 0);
1017 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1018 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
1019 {
1020 context->handleError(InvalidValue());
1021 return false;
1022 }
1023 if (isCompressed)
1024 {
1025 context->handleError(InvalidEnum()
1026 << "Rectangle texture cannot have a compressed format.");
1027 return false;
1028 }
1029 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001030 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001031 {
1032 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037
Geoff Langa9be0dc2014-12-17 12:34:40 -05001038 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1039 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001041 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001042 return false;
1043 }
1044 }
1045 else
1046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001047 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001048 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 }
1050
He Yunchaoced53ae2016-11-29 15:00:51 +08001051 gl::Texture *texture =
1052 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001053 if (!texture)
1054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001056 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057 }
1058
Geoff Langa9be0dc2014-12-17 12:34:40 -05001059 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001060 {
Geoff Langca271392017-04-05 12:30:00 -04001061 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1062 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001064 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001065 return false;
1066 }
1067
Geoff Langa9be0dc2014-12-17 12:34:40 -05001068 if (format != GL_NONE)
1069 {
Geoff Langca271392017-04-05 12:30:00 -04001070 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1071 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001072 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001074 return false;
1075 }
1076 }
1077
1078 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1079 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001081 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001082 return false;
1083 }
1084 }
1085 else
1086 {
Geoff Lang69cce582015-09-17 13:20:36 -04001087 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001089 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001090 return false;
1091 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093
1094 // Verify zero border
1095 if (border != 0)
1096 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001097 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001098 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 }
1100
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 if (isCompressed)
1102 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001103 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001104 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1105 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 switch (actualInternalFormat)
1107 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001108 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1109 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1110 if (!context->getExtensions().textureCompressionDXT1)
1111 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001113 return false;
1114 }
1115 break;
1116 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1117 if (!context->getExtensions().textureCompressionDXT1)
1118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
1121 }
1122 break;
1123 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1124 if (!context->getExtensions().textureCompressionDXT5)
1125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 return false;
1128 }
1129 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001130 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1131 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1132 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1133 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1134 if (!context->getExtensions().textureCompressionS3TCsRGB)
1135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001136 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001137 return false;
1138 }
1139 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 case GL_ETC1_RGB8_OES:
1141 if (!context->getExtensions().compressedETC1RGB8Texture)
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001144 return false;
1145 }
1146 break;
1147 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001148 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1149 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1150 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1151 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001152 if (!context->getExtensions().lossyETCDecode)
1153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001154 context->handleError(InvalidEnum()
1155 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001156 return false;
1157 }
1158 break;
1159 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001161 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001162 }
Geoff Lang966c9402017-04-18 12:38:27 -04001163
1164 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001165 {
Geoff Lang966c9402017-04-18 12:38:27 -04001166 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1167 height, texture->getWidth(target, level),
1168 texture->getHeight(target, level)))
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001171 return false;
1172 }
1173
1174 if (format != actualInternalFormat)
1175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001177 return false;
1178 }
1179 }
1180 else
1181 {
1182 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001184 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001185 return false;
1186 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001187 }
1188 }
1189 else
1190 {
1191 // validate <type> by itself (used as secondary key below)
1192 switch (type)
1193 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 case GL_UNSIGNED_BYTE:
1195 case GL_UNSIGNED_SHORT_5_6_5:
1196 case GL_UNSIGNED_SHORT_4_4_4_4:
1197 case GL_UNSIGNED_SHORT_5_5_5_1:
1198 case GL_UNSIGNED_SHORT:
1199 case GL_UNSIGNED_INT:
1200 case GL_UNSIGNED_INT_24_8_OES:
1201 case GL_HALF_FLOAT_OES:
1202 case GL_FLOAT:
1203 break;
1204 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001207 }
1208
1209 // validate <format> + <type> combinations
1210 // - invalid <format> -> sets INVALID_ENUM
1211 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1212 switch (format)
1213 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 case GL_ALPHA:
1215 case GL_LUMINANCE:
1216 case GL_LUMINANCE_ALPHA:
1217 switch (type)
1218 {
1219 case GL_UNSIGNED_BYTE:
1220 case GL_FLOAT:
1221 case GL_HALF_FLOAT_OES:
1222 break;
1223 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 return false;
1226 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001228 case GL_RED:
1229 case GL_RG:
1230 if (!context->getExtensions().textureRG)
1231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001232 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001233 return false;
1234 }
1235 switch (type)
1236 {
1237 case GL_UNSIGNED_BYTE:
1238 case GL_FLOAT:
1239 case GL_HALF_FLOAT_OES:
1240 break;
1241 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001242 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001243 return false;
1244 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001245 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001246 case GL_RGB:
1247 switch (type)
1248 {
1249 case GL_UNSIGNED_BYTE:
1250 case GL_UNSIGNED_SHORT_5_6_5:
1251 case GL_FLOAT:
1252 case GL_HALF_FLOAT_OES:
1253 break;
1254 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001256 return false;
1257 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001259 case GL_RGBA:
1260 switch (type)
1261 {
1262 case GL_UNSIGNED_BYTE:
1263 case GL_UNSIGNED_SHORT_4_4_4_4:
1264 case GL_UNSIGNED_SHORT_5_5_5_1:
1265 case GL_FLOAT:
1266 case GL_HALF_FLOAT_OES:
1267 break;
1268 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001270 return false;
1271 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001273 case GL_BGRA_EXT:
1274 switch (type)
1275 {
1276 case GL_UNSIGNED_BYTE:
1277 break;
1278 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001279 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001280 return false;
1281 }
1282 break;
1283 case GL_SRGB_EXT:
1284 case GL_SRGB_ALPHA_EXT:
1285 if (!context->getExtensions().sRGB)
1286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001287 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001288 return false;
1289 }
1290 switch (type)
1291 {
1292 case GL_UNSIGNED_BYTE:
1293 break;
1294 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001296 return false;
1297 }
1298 break;
1299 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1300 // handled below
1301 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1302 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1303 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1304 break;
1305 case GL_DEPTH_COMPONENT:
1306 switch (type)
1307 {
1308 case GL_UNSIGNED_SHORT:
1309 case GL_UNSIGNED_INT:
1310 break;
1311 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001313 return false;
1314 }
1315 break;
1316 case GL_DEPTH_STENCIL_OES:
1317 switch (type)
1318 {
1319 case GL_UNSIGNED_INT_24_8_OES:
1320 break;
1321 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 return false;
1324 }
1325 break;
1326 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001328 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 }
1330
1331 switch (format)
1332 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1334 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1335 if (context->getExtensions().textureCompressionDXT1)
1336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001338 return false;
1339 }
1340 else
1341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001343 return false;
1344 }
1345 break;
1346 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1347 if (context->getExtensions().textureCompressionDXT3)
1348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001350 return false;
1351 }
1352 else
1353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001354 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001355 return false;
1356 }
1357 break;
1358 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1359 if (context->getExtensions().textureCompressionDXT5)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001362 return false;
1363 }
1364 else
1365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 return false;
1368 }
1369 break;
1370 case GL_ETC1_RGB8_OES:
1371 if (context->getExtensions().compressedETC1RGB8Texture)
1372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001374 return false;
1375 }
1376 else
1377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 return false;
1380 }
1381 break;
1382 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001383 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1384 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1385 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1386 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001387 if (context->getExtensions().lossyETCDecode)
1388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001389 context->handleError(InvalidOperation()
1390 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001391 return false;
1392 }
1393 else
1394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidEnum()
1396 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001397 return false;
1398 }
1399 break;
1400 case GL_DEPTH_COMPONENT:
1401 case GL_DEPTH_STENCIL_OES:
1402 if (!context->getExtensions().depthTextures)
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001405 return false;
1406 }
1407 if (target != GL_TEXTURE_2D)
1408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001409 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001410 return false;
1411 }
1412 // OES_depth_texture supports loading depth data and multiple levels,
1413 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001414 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 return false;
1418 }
1419 break;
1420 default:
1421 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423
Geoff Lang6e898aa2017-06-02 11:17:26 -04001424 if (!isSubImage)
1425 {
1426 switch (internalformat)
1427 {
1428 case GL_RGBA32F:
1429 if (!context->getExtensions().colorBufferFloatRGBA)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidValue()
1432 << "Sized GL_RGBA32F internal format requires "
1433 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001434 return false;
1435 }
1436 if (type != GL_FLOAT)
1437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001439 return false;
1440 }
1441 if (format != GL_RGBA)
1442 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001444 return false;
1445 }
1446 break;
1447
1448 case GL_RGB32F:
1449 if (!context->getExtensions().colorBufferFloatRGB)
1450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001451 context->handleError(InvalidValue()
1452 << "Sized GL_RGB32F internal format requires "
1453 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001454 return false;
1455 }
1456 if (type != GL_FLOAT)
1457 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001459 return false;
1460 }
1461 if (format != GL_RGB)
1462 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001464 return false;
1465 }
1466 break;
1467
1468 default:
1469 break;
1470 }
1471 }
1472
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 if (type == GL_FLOAT)
1474 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001475 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001478 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001479 }
1480 }
1481 else if (type == GL_HALF_FLOAT_OES)
1482 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001483 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001486 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001487 }
1488 }
1489 }
1490
Geoff Langdbcced82017-06-06 15:55:54 -04001491 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1492 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001493 imageSize))
1494 {
1495 return false;
1496 }
1497
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001498 return true;
1499}
1500
He Yunchaoced53ae2016-11-29 15:00:51 +08001501bool ValidateES2TexStorageParameters(Context *context,
1502 GLenum target,
1503 GLsizei levels,
1504 GLenum internalformat,
1505 GLsizei width,
1506 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001507{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001508 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1509 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001511 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001512 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001513 }
1514
1515 if (width < 1 || height < 1 || levels < 1)
1516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001518 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001519 }
1520
1521 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
1527 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Geoff Langca271392017-04-05 12:30:00 -04001533 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001534 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001536 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539
Geoff Langaae65a42014-05-26 12:43:44 -04001540 const gl::Caps &caps = context->getCaps();
1541
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 switch (target)
1543 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001544 case GL_TEXTURE_2D:
1545 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1546 static_cast<GLuint>(height) > caps.max2DTextureSize)
1547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001548 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001549 return false;
1550 }
1551 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001552 case GL_TEXTURE_RECTANGLE_ANGLE:
1553 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1554 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1555 {
1556 context->handleError(InvalidValue());
1557 return false;
1558 }
1559 if (formatInfo.compressed)
1560 {
1561 context->handleError(InvalidEnum()
1562 << "Rectangle texture cannot have a compressed format.");
1563 return false;
1564 }
1565 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001566 case GL_TEXTURE_CUBE_MAP:
1567 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1568 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001571 return false;
1572 }
1573 break;
1574 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001575 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001576 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001577 }
1578
Geoff Langc0b9ef42014-07-02 10:02:37 -04001579 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001580 {
1581 if (!gl::isPow2(width) || !gl::isPow2(height))
1582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001583 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001584 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001585 }
1586 }
1587
1588 switch (internalformat)
1589 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001590 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1591 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1592 if (!context->getExtensions().textureCompressionDXT1)
1593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001595 return false;
1596 }
1597 break;
1598 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1599 if (!context->getExtensions().textureCompressionDXT3)
1600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001601 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001602 return false;
1603 }
1604 break;
1605 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1606 if (!context->getExtensions().textureCompressionDXT5)
1607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001609 return false;
1610 }
1611 break;
1612 case GL_ETC1_RGB8_OES:
1613 if (!context->getExtensions().compressedETC1RGB8Texture)
1614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001616 return false;
1617 }
1618 break;
1619 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001620 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1621 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1622 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1623 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001624 if (!context->getExtensions().lossyETCDecode)
1625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001626 context->handleError(InvalidEnum()
1627 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001628 return false;
1629 }
1630 break;
1631 case GL_RGBA32F_EXT:
1632 case GL_RGB32F_EXT:
1633 case GL_ALPHA32F_EXT:
1634 case GL_LUMINANCE32F_EXT:
1635 case GL_LUMINANCE_ALPHA32F_EXT:
1636 if (!context->getExtensions().textureFloat)
1637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001639 return false;
1640 }
1641 break;
1642 case GL_RGBA16F_EXT:
1643 case GL_RGB16F_EXT:
1644 case GL_ALPHA16F_EXT:
1645 case GL_LUMINANCE16F_EXT:
1646 case GL_LUMINANCE_ALPHA16F_EXT:
1647 if (!context->getExtensions().textureHalfFloat)
1648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001649 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001650 return false;
1651 }
1652 break;
1653 case GL_R8_EXT:
1654 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001655 if (!context->getExtensions().textureRG)
1656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001657 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001658 return false;
1659 }
1660 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001661 case GL_R16F_EXT:
1662 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001663 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001665 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001666 return false;
1667 }
1668 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001669 case GL_R32F_EXT:
1670 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001671 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001673 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001674 return false;
1675 }
1676 break;
1677 case GL_DEPTH_COMPONENT16:
1678 case GL_DEPTH_COMPONENT32_OES:
1679 case GL_DEPTH24_STENCIL8_OES:
1680 if (!context->getExtensions().depthTextures)
1681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001682 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001683 return false;
1684 }
1685 if (target != GL_TEXTURE_2D)
1686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001687 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001688 return false;
1689 }
1690 // ANGLE_depth_texture only supports 1-level textures
1691 if (levels != 1)
1692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001693 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001694 return false;
1695 }
1696 break;
1697 default:
1698 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001699 }
1700
Geoff Lang691e58c2014-12-19 17:03:25 -05001701 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001702 if (!texture || texture->id() == 0)
1703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001704 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001705 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001706 }
1707
Geoff Lang69cce582015-09-17 13:20:36 -04001708 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001711 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001712 }
1713
1714 return true;
1715}
1716
He Yunchaoced53ae2016-11-29 15:00:51 +08001717bool ValidateDiscardFramebufferEXT(Context *context,
1718 GLenum target,
1719 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001720 const GLenum *attachments)
1721{
Jamie Madillc29968b2016-01-20 11:17:23 -05001722 if (!context->getExtensions().discardFramebuffer)
1723 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
1727
Austin Kinross08332632015-05-05 13:35:47 -07001728 bool defaultFramebuffer = false;
1729
1730 switch (target)
1731 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001732 case GL_FRAMEBUFFER:
1733 defaultFramebuffer =
1734 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1735 break;
1736 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001738 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001739 }
1740
He Yunchaoced53ae2016-11-29 15:00:51 +08001741 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1742 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001743}
1744
Austin Kinrossbc781f32015-10-26 09:27:38 -07001745bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1746{
1747 if (!context->getExtensions().vertexArrayObject)
1748 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001749 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001750 return false;
1751 }
1752
1753 return ValidateBindVertexArrayBase(context, array);
1754}
1755
1756bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1757{
1758 if (!context->getExtensions().vertexArrayObject)
1759 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001760 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001761 return false;
1762 }
1763
Olli Etuaho41997e72016-03-10 13:38:39 +02001764 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001765}
1766
1767bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1768{
1769 if (!context->getExtensions().vertexArrayObject)
1770 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001771 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001772 return false;
1773 }
1774
Olli Etuaho41997e72016-03-10 13:38:39 +02001775 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001776}
1777
1778bool ValidateIsVertexArrayOES(Context *context)
1779{
1780 if (!context->getExtensions().vertexArrayObject)
1781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001783 return false;
1784 }
1785
1786 return true;
1787}
Geoff Langc5629752015-12-07 16:29:04 -05001788
1789bool ValidateProgramBinaryOES(Context *context,
1790 GLuint program,
1791 GLenum binaryFormat,
1792 const void *binary,
1793 GLint length)
1794{
1795 if (!context->getExtensions().getProgramBinary)
1796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001798 return false;
1799 }
1800
1801 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1802}
1803
1804bool ValidateGetProgramBinaryOES(Context *context,
1805 GLuint program,
1806 GLsizei bufSize,
1807 GLsizei *length,
1808 GLenum *binaryFormat,
1809 void *binary)
1810{
1811 if (!context->getExtensions().getProgramBinary)
1812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001814 return false;
1815 }
1816
1817 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1818}
Geoff Lange102fee2015-12-10 11:23:30 -05001819
Geoff Lang70d0f492015-12-10 17:45:46 -05001820static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1821{
1822 switch (source)
1823 {
1824 case GL_DEBUG_SOURCE_API:
1825 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1826 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1827 case GL_DEBUG_SOURCE_OTHER:
1828 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1829 return !mustBeThirdPartyOrApplication;
1830
1831 case GL_DEBUG_SOURCE_THIRD_PARTY:
1832 case GL_DEBUG_SOURCE_APPLICATION:
1833 return true;
1834
1835 default:
1836 return false;
1837 }
1838}
1839
1840static bool ValidDebugType(GLenum type)
1841{
1842 switch (type)
1843 {
1844 case GL_DEBUG_TYPE_ERROR:
1845 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1846 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1847 case GL_DEBUG_TYPE_PERFORMANCE:
1848 case GL_DEBUG_TYPE_PORTABILITY:
1849 case GL_DEBUG_TYPE_OTHER:
1850 case GL_DEBUG_TYPE_MARKER:
1851 case GL_DEBUG_TYPE_PUSH_GROUP:
1852 case GL_DEBUG_TYPE_POP_GROUP:
1853 return true;
1854
1855 default:
1856 return false;
1857 }
1858}
1859
1860static bool ValidDebugSeverity(GLenum severity)
1861{
1862 switch (severity)
1863 {
1864 case GL_DEBUG_SEVERITY_HIGH:
1865 case GL_DEBUG_SEVERITY_MEDIUM:
1866 case GL_DEBUG_SEVERITY_LOW:
1867 case GL_DEBUG_SEVERITY_NOTIFICATION:
1868 return true;
1869
1870 default:
1871 return false;
1872 }
1873}
1874
Geoff Lange102fee2015-12-10 11:23:30 -05001875bool ValidateDebugMessageControlKHR(Context *context,
1876 GLenum source,
1877 GLenum type,
1878 GLenum severity,
1879 GLsizei count,
1880 const GLuint *ids,
1881 GLboolean enabled)
1882{
1883 if (!context->getExtensions().debug)
1884 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001885 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001886 return false;
1887 }
1888
Geoff Lang70d0f492015-12-10 17:45:46 -05001889 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001891 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001892 return false;
1893 }
1894
1895 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001897 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001898 return false;
1899 }
1900
1901 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001903 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 return false;
1905 }
1906
1907 if (count > 0)
1908 {
1909 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001911 context->handleError(
1912 InvalidOperation()
1913 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001914 return false;
1915 }
1916
1917 if (severity != GL_DONT_CARE)
1918 {
Jamie Madill437fa652016-05-03 15:13:24 -04001919 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001920 InvalidOperation()
1921 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001922 return false;
1923 }
1924 }
1925
Geoff Lange102fee2015-12-10 11:23:30 -05001926 return true;
1927}
1928
1929bool ValidateDebugMessageInsertKHR(Context *context,
1930 GLenum source,
1931 GLenum type,
1932 GLuint id,
1933 GLenum severity,
1934 GLsizei length,
1935 const GLchar *buf)
1936{
1937 if (!context->getExtensions().debug)
1938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001940 return false;
1941 }
1942
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001943 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001944 {
1945 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1946 // not generate an error.
1947 return false;
1948 }
1949
1950 if (!ValidDebugSeverity(severity))
1951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001953 return false;
1954 }
1955
1956 if (!ValidDebugType(type))
1957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001958 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001959 return false;
1960 }
1961
1962 if (!ValidDebugSource(source, true))
1963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001964 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001965 return false;
1966 }
1967
1968 size_t messageLength = (length < 0) ? strlen(buf) : length;
1969 if (messageLength > context->getExtensions().maxDebugMessageLength)
1970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001971 context->handleError(InvalidValue()
1972 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001973 return false;
1974 }
1975
Geoff Lange102fee2015-12-10 11:23:30 -05001976 return true;
1977}
1978
1979bool ValidateDebugMessageCallbackKHR(Context *context,
1980 GLDEBUGPROCKHR callback,
1981 const void *userParam)
1982{
1983 if (!context->getExtensions().debug)
1984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001986 return false;
1987 }
1988
Geoff Lange102fee2015-12-10 11:23:30 -05001989 return true;
1990}
1991
1992bool ValidateGetDebugMessageLogKHR(Context *context,
1993 GLuint count,
1994 GLsizei bufSize,
1995 GLenum *sources,
1996 GLenum *types,
1997 GLuint *ids,
1998 GLenum *severities,
1999 GLsizei *lengths,
2000 GLchar *messageLog)
2001{
2002 if (!context->getExtensions().debug)
2003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002005 return false;
2006 }
2007
Geoff Lang70d0f492015-12-10 17:45:46 -05002008 if (bufSize < 0 && messageLog != nullptr)
2009 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002010 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002011 return false;
2012 }
2013
Geoff Lange102fee2015-12-10 11:23:30 -05002014 return true;
2015}
2016
2017bool ValidatePushDebugGroupKHR(Context *context,
2018 GLenum source,
2019 GLuint id,
2020 GLsizei length,
2021 const GLchar *message)
2022{
2023 if (!context->getExtensions().debug)
2024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002026 return false;
2027 }
2028
Geoff Lang70d0f492015-12-10 17:45:46 -05002029 if (!ValidDebugSource(source, true))
2030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002031 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002032 return false;
2033 }
2034
2035 size_t messageLength = (length < 0) ? strlen(message) : length;
2036 if (messageLength > context->getExtensions().maxDebugMessageLength)
2037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002038 context->handleError(InvalidValue()
2039 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002040 return false;
2041 }
2042
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002043 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002044 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002046 context
2047 ->handleError(StackOverflow()
2048 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002049 return false;
2050 }
2051
Geoff Lange102fee2015-12-10 11:23:30 -05002052 return true;
2053}
2054
2055bool ValidatePopDebugGroupKHR(Context *context)
2056{
2057 if (!context->getExtensions().debug)
2058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002060 return false;
2061 }
2062
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002063 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002064 if (currentStackSize <= 1)
2065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002066 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002067 return false;
2068 }
2069
2070 return true;
2071}
2072
2073static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2074{
2075 switch (identifier)
2076 {
2077 case GL_BUFFER:
2078 if (context->getBuffer(name) == nullptr)
2079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002080 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002081 return false;
2082 }
2083 return true;
2084
2085 case GL_SHADER:
2086 if (context->getShader(name) == nullptr)
2087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002088 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002089 return false;
2090 }
2091 return true;
2092
2093 case GL_PROGRAM:
2094 if (context->getProgram(name) == nullptr)
2095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002096 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002097 return false;
2098 }
2099 return true;
2100
2101 case GL_VERTEX_ARRAY:
2102 if (context->getVertexArray(name) == nullptr)
2103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002104 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002105 return false;
2106 }
2107 return true;
2108
2109 case GL_QUERY:
2110 if (context->getQuery(name) == nullptr)
2111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002113 return false;
2114 }
2115 return true;
2116
2117 case GL_TRANSFORM_FEEDBACK:
2118 if (context->getTransformFeedback(name) == nullptr)
2119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002120 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002121 return false;
2122 }
2123 return true;
2124
2125 case GL_SAMPLER:
2126 if (context->getSampler(name) == nullptr)
2127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002128 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002129 return false;
2130 }
2131 return true;
2132
2133 case GL_TEXTURE:
2134 if (context->getTexture(name) == nullptr)
2135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002136 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002137 return false;
2138 }
2139 return true;
2140
2141 case GL_RENDERBUFFER:
2142 if (context->getRenderbuffer(name) == nullptr)
2143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002144 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002145 return false;
2146 }
2147 return true;
2148
2149 case GL_FRAMEBUFFER:
2150 if (context->getFramebuffer(name) == nullptr)
2151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002152 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002153 return false;
2154 }
2155 return true;
2156
2157 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002158 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002159 return false;
2160 }
Geoff Lange102fee2015-12-10 11:23:30 -05002161}
2162
Martin Radev9d901792016-07-15 15:58:58 +03002163static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2164{
2165 size_t labelLength = 0;
2166
2167 if (length < 0)
2168 {
2169 if (label != nullptr)
2170 {
2171 labelLength = strlen(label);
2172 }
2173 }
2174 else
2175 {
2176 labelLength = static_cast<size_t>(length);
2177 }
2178
2179 if (labelLength > context->getExtensions().maxLabelLength)
2180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002181 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002182 return false;
2183 }
2184
2185 return true;
2186}
2187
Geoff Lange102fee2015-12-10 11:23:30 -05002188bool ValidateObjectLabelKHR(Context *context,
2189 GLenum identifier,
2190 GLuint name,
2191 GLsizei length,
2192 const GLchar *label)
2193{
2194 if (!context->getExtensions().debug)
2195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002197 return false;
2198 }
2199
Geoff Lang70d0f492015-12-10 17:45:46 -05002200 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2201 {
2202 return false;
2203 }
2204
Martin Radev9d901792016-07-15 15:58:58 +03002205 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002206 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002207 return false;
2208 }
2209
Geoff Lange102fee2015-12-10 11:23:30 -05002210 return true;
2211}
2212
2213bool ValidateGetObjectLabelKHR(Context *context,
2214 GLenum identifier,
2215 GLuint name,
2216 GLsizei bufSize,
2217 GLsizei *length,
2218 GLchar *label)
2219{
2220 if (!context->getExtensions().debug)
2221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002223 return false;
2224 }
2225
Geoff Lang70d0f492015-12-10 17:45:46 -05002226 if (bufSize < 0)
2227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002228 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002229 return false;
2230 }
2231
2232 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2233 {
2234 return false;
2235 }
2236
Martin Radev9d901792016-07-15 15:58:58 +03002237 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002238}
2239
2240static bool ValidateObjectPtrName(Context *context, const void *ptr)
2241{
2242 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002245 return false;
2246 }
2247
Geoff Lange102fee2015-12-10 11:23:30 -05002248 return true;
2249}
2250
2251bool ValidateObjectPtrLabelKHR(Context *context,
2252 const void *ptr,
2253 GLsizei length,
2254 const GLchar *label)
2255{
2256 if (!context->getExtensions().debug)
2257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002259 return false;
2260 }
2261
Geoff Lang70d0f492015-12-10 17:45:46 -05002262 if (!ValidateObjectPtrName(context, ptr))
2263 {
2264 return false;
2265 }
2266
Martin Radev9d901792016-07-15 15:58:58 +03002267 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002268 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002269 return false;
2270 }
2271
Geoff Lange102fee2015-12-10 11:23:30 -05002272 return true;
2273}
2274
2275bool ValidateGetObjectPtrLabelKHR(Context *context,
2276 const void *ptr,
2277 GLsizei bufSize,
2278 GLsizei *length,
2279 GLchar *label)
2280{
2281 if (!context->getExtensions().debug)
2282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002284 return false;
2285 }
2286
Geoff Lang70d0f492015-12-10 17:45:46 -05002287 if (bufSize < 0)
2288 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002289 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002290 return false;
2291 }
2292
2293 if (!ValidateObjectPtrName(context, ptr))
2294 {
2295 return false;
2296 }
2297
Martin Radev9d901792016-07-15 15:58:58 +03002298 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002299}
2300
2301bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2302{
2303 if (!context->getExtensions().debug)
2304 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002306 return false;
2307 }
2308
Geoff Lang70d0f492015-12-10 17:45:46 -05002309 // TODO: represent this in Context::getQueryParameterInfo.
2310 switch (pname)
2311 {
2312 case GL_DEBUG_CALLBACK_FUNCTION:
2313 case GL_DEBUG_CALLBACK_USER_PARAM:
2314 break;
2315
2316 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002317 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002318 return false;
2319 }
2320
Geoff Lange102fee2015-12-10 11:23:30 -05002321 return true;
2322}
Jamie Madillc29968b2016-01-20 11:17:23 -05002323
2324bool ValidateBlitFramebufferANGLE(Context *context,
2325 GLint srcX0,
2326 GLint srcY0,
2327 GLint srcX1,
2328 GLint srcY1,
2329 GLint dstX0,
2330 GLint dstY0,
2331 GLint dstX1,
2332 GLint dstY1,
2333 GLbitfield mask,
2334 GLenum filter)
2335{
2336 if (!context->getExtensions().framebufferBlit)
2337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002338 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002339 return false;
2340 }
2341
2342 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2343 {
2344 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 context->handleError(InvalidOperation() << "Scaling and flipping in "
2346 "BlitFramebufferANGLE not supported by this "
2347 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002348 return false;
2349 }
2350
2351 if (filter == GL_LINEAR)
2352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002353 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002354 return false;
2355 }
2356
Jamie Madill51f40ec2016-06-15 14:06:00 -04002357 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2358 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002359
2360 if (mask & GL_COLOR_BUFFER_BIT)
2361 {
2362 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2363 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2364
2365 if (readColorAttachment && drawColorAttachment)
2366 {
2367 if (!(readColorAttachment->type() == GL_TEXTURE &&
2368 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2369 readColorAttachment->type() != GL_RENDERBUFFER &&
2370 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002372 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002373 return false;
2374 }
2375
Geoff Langa15472a2015-08-11 11:48:03 -04002376 for (size_t drawbufferIdx = 0;
2377 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002378 {
Geoff Langa15472a2015-08-11 11:48:03 -04002379 const FramebufferAttachment *attachment =
2380 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2381 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002382 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002383 if (!(attachment->type() == GL_TEXTURE &&
2384 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2385 attachment->type() != GL_RENDERBUFFER &&
2386 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002388 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002389 return false;
2390 }
2391
2392 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002393 if (!Format::EquivalentForBlit(attachment->getFormat(),
2394 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002397 return false;
2398 }
2399 }
2400 }
2401
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002402 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002403 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2404 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002407 return false;
2408 }
2409 }
2410 }
2411
2412 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2413 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2414 for (size_t i = 0; i < 2; i++)
2415 {
2416 if (mask & masks[i])
2417 {
2418 const FramebufferAttachment *readBuffer =
2419 readFramebuffer->getAttachment(attachments[i]);
2420 const FramebufferAttachment *drawBuffer =
2421 drawFramebuffer->getAttachment(attachments[i]);
2422
2423 if (readBuffer && drawBuffer)
2424 {
2425 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2426 dstX0, dstY0, dstX1, dstY1))
2427 {
2428 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002429 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2430 "stencil blits are supported by "
2431 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002432 return false;
2433 }
2434
2435 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002437 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002438 return false;
2439 }
2440 }
2441 }
2442 }
2443
2444 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2445 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002446}
Jamie Madillc29968b2016-01-20 11:17:23 -05002447
2448bool ValidateClear(ValidationContext *context, GLbitfield mask)
2449{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002450 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002451 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002453 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002454 return false;
2455 }
2456
2457 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2458 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002459 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002460 return false;
2461 }
2462
Geoff Lang76e65652017-03-27 14:58:02 -04002463 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2464 {
2465 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2466 GL_SIGNED_NORMALIZED};
2467
Corentin Wallez59c41592017-07-11 13:19:54 -04002468 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002469 drawBufferIdx++)
2470 {
2471 if (!ValidateWebGLFramebufferAttachmentClearType(
2472 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2473 {
2474 return false;
2475 }
2476 }
2477 }
2478
Jamie Madillc29968b2016-01-20 11:17:23 -05002479 return true;
2480}
2481
2482bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2483{
2484 if (!context->getExtensions().drawBuffers)
2485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002486 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002487 return false;
2488 }
2489
2490 return ValidateDrawBuffersBase(context, n, bufs);
2491}
2492
Jamie Madill73a84962016-02-12 09:27:23 -05002493bool ValidateTexImage2D(Context *context,
2494 GLenum target,
2495 GLint level,
2496 GLint internalformat,
2497 GLsizei width,
2498 GLsizei height,
2499 GLint border,
2500 GLenum format,
2501 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002502 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002503{
Martin Radev1be913c2016-07-11 17:59:16 +03002504 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002505 {
2506 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002507 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002508 }
2509
Martin Radev1be913c2016-07-11 17:59:16 +03002510 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002511 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002512 0, 0, width, height, 1, border, format, type, -1,
2513 pixels);
2514}
2515
2516bool ValidateTexImage2DRobust(Context *context,
2517 GLenum target,
2518 GLint level,
2519 GLint internalformat,
2520 GLsizei width,
2521 GLsizei height,
2522 GLint border,
2523 GLenum format,
2524 GLenum type,
2525 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002526 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002527{
2528 if (!ValidateRobustEntryPoint(context, bufSize))
2529 {
2530 return false;
2531 }
2532
2533 if (context->getClientMajorVersion() < 3)
2534 {
2535 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2536 0, 0, width, height, border, format, type, bufSize,
2537 pixels);
2538 }
2539
2540 ASSERT(context->getClientMajorVersion() >= 3);
2541 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2542 0, 0, width, height, 1, border, format, type, bufSize,
2543 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002544}
2545
2546bool ValidateTexSubImage2D(Context *context,
2547 GLenum target,
2548 GLint level,
2549 GLint xoffset,
2550 GLint yoffset,
2551 GLsizei width,
2552 GLsizei height,
2553 GLenum format,
2554 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002555 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002556{
2557
Martin Radev1be913c2016-07-11 17:59:16 +03002558 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002559 {
2560 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002561 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002562 }
2563
Martin Radev1be913c2016-07-11 17:59:16 +03002564 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002565 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002566 yoffset, 0, width, height, 1, 0, format, type, -1,
2567 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002568}
2569
Geoff Langc52f6f12016-10-14 10:18:00 -04002570bool ValidateTexSubImage2DRobustANGLE(Context *context,
2571 GLenum target,
2572 GLint level,
2573 GLint xoffset,
2574 GLint yoffset,
2575 GLsizei width,
2576 GLsizei height,
2577 GLenum format,
2578 GLenum type,
2579 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002580 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002581{
2582 if (!ValidateRobustEntryPoint(context, bufSize))
2583 {
2584 return false;
2585 }
2586
2587 if (context->getClientMajorVersion() < 3)
2588 {
2589 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2590 yoffset, width, height, 0, format, type, bufSize,
2591 pixels);
2592 }
2593
2594 ASSERT(context->getClientMajorVersion() >= 3);
2595 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2596 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2597 pixels);
2598}
2599
Jamie Madill73a84962016-02-12 09:27:23 -05002600bool ValidateCompressedTexImage2D(Context *context,
2601 GLenum target,
2602 GLint level,
2603 GLenum internalformat,
2604 GLsizei width,
2605 GLsizei height,
2606 GLint border,
2607 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002608 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002609{
Martin Radev1be913c2016-07-11 17:59:16 +03002610 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002611 {
2612 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002613 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002614 {
2615 return false;
2616 }
2617 }
2618 else
2619 {
Martin Radev1be913c2016-07-11 17:59:16 +03002620 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002621 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002622 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002623 data))
2624 {
2625 return false;
2626 }
2627 }
2628
Geoff Langca271392017-04-05 12:30:00 -04002629 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002630 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002631 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002632 if (blockSizeOrErr.isError())
2633 {
2634 context->handleError(blockSizeOrErr.getError());
2635 return false;
2636 }
2637
2638 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002640 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002641 return false;
2642 }
2643
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002644 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2645 {
2646 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2647 return false;
2648 }
2649
Jamie Madill73a84962016-02-12 09:27:23 -05002650 return true;
2651}
2652
Corentin Wallezb2931602017-04-11 15:58:57 -04002653bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2654 GLenum target,
2655 GLint level,
2656 GLenum internalformat,
2657 GLsizei width,
2658 GLsizei height,
2659 GLint border,
2660 GLsizei imageSize,
2661 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002662 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002663{
2664 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2665 {
2666 return false;
2667 }
2668
2669 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2670 border, imageSize, data);
2671}
2672bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2673 GLenum target,
2674 GLint level,
2675 GLint xoffset,
2676 GLint yoffset,
2677 GLsizei width,
2678 GLsizei height,
2679 GLenum format,
2680 GLsizei imageSize,
2681 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002682 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002683{
2684 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2685 {
2686 return false;
2687 }
2688
2689 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2690 format, imageSize, data);
2691}
2692
Jamie Madill73a84962016-02-12 09:27:23 -05002693bool ValidateCompressedTexSubImage2D(Context *context,
2694 GLenum target,
2695 GLint level,
2696 GLint xoffset,
2697 GLint yoffset,
2698 GLsizei width,
2699 GLsizei height,
2700 GLenum format,
2701 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002702 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002703{
Martin Radev1be913c2016-07-11 17:59:16 +03002704 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002705 {
2706 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002707 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002708 {
2709 return false;
2710 }
2711 }
2712 else
2713 {
Martin Radev1be913c2016-07-11 17:59:16 +03002714 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002715 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002716 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002717 data))
2718 {
2719 return false;
2720 }
2721 }
2722
Geoff Langca271392017-04-05 12:30:00 -04002723 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002724 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002725 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002726 if (blockSizeOrErr.isError())
2727 {
2728 context->handleError(blockSizeOrErr.getError());
2729 return false;
2730 }
2731
2732 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002734 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002735 return false;
2736 }
2737
2738 return true;
2739}
2740
Olli Etuaho4f667482016-03-30 15:56:35 +03002741bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2742{
Geoff Lang496c02d2016-10-20 11:38:11 -07002743 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002744}
2745
2746bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2747{
2748 if (!context->getExtensions().mapBuffer)
2749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002750 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002751 return false;
2752 }
2753
2754 if (!ValidBufferTarget(context, target))
2755 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002757 return false;
2758 }
2759
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002760 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002761
2762 if (buffer == nullptr)
2763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002764 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002765 return false;
2766 }
2767
2768 if (access != GL_WRITE_ONLY_OES)
2769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002770 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002771 return false;
2772 }
2773
2774 if (buffer->isMapped())
2775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002776 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002777 return false;
2778 }
2779
Geoff Lang79f71042017-08-14 16:43:43 -04002780 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002781}
2782
2783bool ValidateUnmapBufferOES(Context *context, GLenum target)
2784{
2785 if (!context->getExtensions().mapBuffer)
2786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002787 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002788 return false;
2789 }
2790
2791 return ValidateUnmapBufferBase(context, target);
2792}
2793
2794bool ValidateMapBufferRangeEXT(Context *context,
2795 GLenum target,
2796 GLintptr offset,
2797 GLsizeiptr length,
2798 GLbitfield access)
2799{
2800 if (!context->getExtensions().mapBufferRange)
2801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002802 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002803 return false;
2804 }
2805
2806 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2807}
2808
Geoff Lang79f71042017-08-14 16:43:43 -04002809bool ValidateMapBufferBase(Context *context, GLenum target)
2810{
2811 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2812 ASSERT(buffer != nullptr);
2813
2814 // Check if this buffer is currently being used as a transform feedback output buffer
2815 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2816 if (transformFeedback != nullptr && transformFeedback->isActive())
2817 {
2818 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2819 {
2820 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2821 if (transformFeedbackBuffer.get() == buffer)
2822 {
2823 context->handleError(InvalidOperation()
2824 << "Buffer is currently bound for transform feedback.");
2825 return false;
2826 }
2827 }
2828 }
2829
2830 return true;
2831}
2832
Olli Etuaho4f667482016-03-30 15:56:35 +03002833bool ValidateFlushMappedBufferRangeEXT(Context *context,
2834 GLenum target,
2835 GLintptr offset,
2836 GLsizeiptr length)
2837{
2838 if (!context->getExtensions().mapBufferRange)
2839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002840 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002841 return false;
2842 }
2843
2844 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2845}
2846
Ian Ewell54f87462016-03-10 13:47:21 -05002847bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2848{
2849 Texture *textureObject = context->getTexture(texture);
2850 if (textureObject && textureObject->getTarget() != target && texture != 0)
2851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Ian Ewell54f87462016-03-10 13:47:21 -05002853 return false;
2854 }
2855
Geoff Langf41a7152016-09-19 15:11:17 -04002856 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2857 !context->isTextureGenerated(texture))
2858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002859 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002860 return false;
2861 }
2862
Ian Ewell54f87462016-03-10 13:47:21 -05002863 switch (target)
2864 {
2865 case GL_TEXTURE_2D:
2866 case GL_TEXTURE_CUBE_MAP:
2867 break;
2868
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002869 case GL_TEXTURE_RECTANGLE_ANGLE:
2870 if (!context->getExtensions().textureRectangle)
2871 {
2872 context->handleError(InvalidEnum()
2873 << "Context does not support GL_ANGLE_texture_rectangle");
2874 return false;
2875 }
2876 break;
2877
Ian Ewell54f87462016-03-10 13:47:21 -05002878 case GL_TEXTURE_3D:
2879 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002880 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002882 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002883 return false;
2884 }
2885 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002886
2887 case GL_TEXTURE_2D_MULTISAMPLE:
2888 if (context->getClientVersion() < Version(3, 1))
2889 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002890 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002891 return false;
2892 }
Geoff Lang3b573612016-10-31 14:08:10 -04002893 break;
2894
Ian Ewell54f87462016-03-10 13:47:21 -05002895 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002896 if (!context->getExtensions().eglImageExternal &&
2897 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002899 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002900 return false;
2901 }
2902 break;
2903 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002905 return false;
2906 }
2907
2908 return true;
2909}
2910
Geoff Langd8605522016-04-13 10:19:12 -04002911bool ValidateBindUniformLocationCHROMIUM(Context *context,
2912 GLuint program,
2913 GLint location,
2914 const GLchar *name)
2915{
2916 if (!context->getExtensions().bindUniformLocation)
2917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002918 context->handleError(InvalidOperation()
2919 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002920 return false;
2921 }
2922
2923 Program *programObject = GetValidProgram(context, program);
2924 if (!programObject)
2925 {
2926 return false;
2927 }
2928
2929 if (location < 0)
2930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002931 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002932 return false;
2933 }
2934
2935 const Caps &caps = context->getCaps();
2936 if (static_cast<size_t>(location) >=
2937 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002939 context->handleError(InvalidValue() << "Location must be less than "
2940 "(MAX_VERTEX_UNIFORM_VECTORS + "
2941 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002942 return false;
2943 }
2944
Geoff Langfc32e8b2017-05-31 14:16:59 -04002945 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2946 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04002947 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002948 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002949 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04002950 return false;
2951 }
2952
Geoff Langd8605522016-04-13 10:19:12 -04002953 if (strncmp(name, "gl_", 3) == 0)
2954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002955 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04002956 return false;
2957 }
2958
2959 return true;
2960}
2961
Jamie Madille2e406c2016-06-02 13:04:10 -04002962bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002963{
2964 if (!context->getExtensions().framebufferMixedSamples)
2965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002966 context->handleError(InvalidOperation()
2967 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002968 return false;
2969 }
2970 switch (components)
2971 {
2972 case GL_RGB:
2973 case GL_RGBA:
2974 case GL_ALPHA:
2975 case GL_NONE:
2976 break;
2977 default:
2978 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002979 InvalidEnum()
2980 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002981 return false;
2982 }
2983
2984 return true;
2985}
2986
Sami Väisänene45e53b2016-05-25 10:36:04 +03002987// CHROMIUM_path_rendering
2988
2989bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2990{
2991 if (!context->getExtensions().pathRendering)
2992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002993 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002994 return false;
2995 }
2996 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002998 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002999 return false;
3000 }
3001 if (matrix == nullptr)
3002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003003 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003004 return false;
3005 }
3006 return true;
3007}
3008
3009bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3010{
3011 if (!context->getExtensions().pathRendering)
3012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003013 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003014 return false;
3015 }
3016 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003019 return false;
3020 }
3021 return true;
3022}
3023
3024bool ValidateGenPaths(Context *context, GLsizei range)
3025{
3026 if (!context->getExtensions().pathRendering)
3027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003028 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003029 return false;
3030 }
3031
3032 // range = 0 is undefined in NV_path_rendering.
3033 // we add stricter semantic check here and require a non zero positive range.
3034 if (range <= 0)
3035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003036 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003037 return false;
3038 }
3039
3040 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3041 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003042 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003043 return false;
3044 }
3045
3046 return true;
3047}
3048
3049bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3050{
3051 if (!context->getExtensions().pathRendering)
3052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003053 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003054 return false;
3055 }
3056
3057 // range = 0 is undefined in NV_path_rendering.
3058 // we add stricter semantic check here and require a non zero positive range.
3059 if (range <= 0)
3060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003061 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003062 return false;
3063 }
3064
3065 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3066 checkedRange += range;
3067
3068 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003071 return false;
3072 }
3073 return true;
3074}
3075
3076bool ValidatePathCommands(Context *context,
3077 GLuint path,
3078 GLsizei numCommands,
3079 const GLubyte *commands,
3080 GLsizei numCoords,
3081 GLenum coordType,
3082 const void *coords)
3083{
3084 if (!context->getExtensions().pathRendering)
3085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003086 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003087 return false;
3088 }
3089 if (!context->hasPath(path))
3090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003091 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003092 return false;
3093 }
3094
3095 if (numCommands < 0)
3096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003097 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003098 return false;
3099 }
3100 else if (numCommands > 0)
3101 {
3102 if (!commands)
3103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003104 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003105 return false;
3106 }
3107 }
3108
3109 if (numCoords < 0)
3110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003111 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003112 return false;
3113 }
3114 else if (numCoords > 0)
3115 {
3116 if (!coords)
3117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003118 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003119 return false;
3120 }
3121 }
3122
3123 std::uint32_t coordTypeSize = 0;
3124 switch (coordType)
3125 {
3126 case GL_BYTE:
3127 coordTypeSize = sizeof(GLbyte);
3128 break;
3129
3130 case GL_UNSIGNED_BYTE:
3131 coordTypeSize = sizeof(GLubyte);
3132 break;
3133
3134 case GL_SHORT:
3135 coordTypeSize = sizeof(GLshort);
3136 break;
3137
3138 case GL_UNSIGNED_SHORT:
3139 coordTypeSize = sizeof(GLushort);
3140 break;
3141
3142 case GL_FLOAT:
3143 coordTypeSize = sizeof(GLfloat);
3144 break;
3145
3146 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003147 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003148 return false;
3149 }
3150
3151 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3152 checkedSize += (coordTypeSize * numCoords);
3153 if (!checkedSize.IsValid())
3154 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003156 return false;
3157 }
3158
3159 // early return skips command data validation when it doesn't exist.
3160 if (!commands)
3161 return true;
3162
3163 GLsizei expectedNumCoords = 0;
3164 for (GLsizei i = 0; i < numCommands; ++i)
3165 {
3166 switch (commands[i])
3167 {
3168 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3169 break;
3170 case GL_MOVE_TO_CHROMIUM:
3171 case GL_LINE_TO_CHROMIUM:
3172 expectedNumCoords += 2;
3173 break;
3174 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3175 expectedNumCoords += 4;
3176 break;
3177 case GL_CUBIC_CURVE_TO_CHROMIUM:
3178 expectedNumCoords += 6;
3179 break;
3180 case GL_CONIC_CURVE_TO_CHROMIUM:
3181 expectedNumCoords += 5;
3182 break;
3183 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003184 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003185 return false;
3186 }
3187 }
3188 if (expectedNumCoords != numCoords)
3189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003190 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003191 return false;
3192 }
3193
3194 return true;
3195}
3196
3197bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3198{
3199 if (!context->getExtensions().pathRendering)
3200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003201 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003202 return false;
3203 }
3204 if (!context->hasPath(path))
3205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003206 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003207 return false;
3208 }
3209
3210 switch (pname)
3211 {
3212 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3213 if (value < 0.0f)
3214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003215 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003216 return false;
3217 }
3218 break;
3219 case GL_PATH_END_CAPS_CHROMIUM:
3220 switch (static_cast<GLenum>(value))
3221 {
3222 case GL_FLAT_CHROMIUM:
3223 case GL_SQUARE_CHROMIUM:
3224 case GL_ROUND_CHROMIUM:
3225 break;
3226 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003227 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003228 return false;
3229 }
3230 break;
3231 case GL_PATH_JOIN_STYLE_CHROMIUM:
3232 switch (static_cast<GLenum>(value))
3233 {
3234 case GL_MITER_REVERT_CHROMIUM:
3235 case GL_BEVEL_CHROMIUM:
3236 case GL_ROUND_CHROMIUM:
3237 break;
3238 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003239 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003240 return false;
3241 }
3242 case GL_PATH_MITER_LIMIT_CHROMIUM:
3243 if (value < 0.0f)
3244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003246 return false;
3247 }
3248 break;
3249
3250 case GL_PATH_STROKE_BOUND_CHROMIUM:
3251 // no errors, only clamping.
3252 break;
3253
3254 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003255 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003256 return false;
3257 }
3258 return true;
3259}
3260
3261bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3262{
3263 if (!context->getExtensions().pathRendering)
3264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003265 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003266 return false;
3267 }
3268
3269 if (!context->hasPath(path))
3270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003271 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003272 return false;
3273 }
3274 if (!value)
3275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003277 return false;
3278 }
3279
3280 switch (pname)
3281 {
3282 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3283 case GL_PATH_END_CAPS_CHROMIUM:
3284 case GL_PATH_JOIN_STYLE_CHROMIUM:
3285 case GL_PATH_MITER_LIMIT_CHROMIUM:
3286 case GL_PATH_STROKE_BOUND_CHROMIUM:
3287 break;
3288
3289 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003291 return false;
3292 }
3293
3294 return true;
3295}
3296
3297bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3298{
3299 if (!context->getExtensions().pathRendering)
3300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003301 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003302 return false;
3303 }
3304
3305 switch (func)
3306 {
3307 case GL_NEVER:
3308 case GL_ALWAYS:
3309 case GL_LESS:
3310 case GL_LEQUAL:
3311 case GL_EQUAL:
3312 case GL_GEQUAL:
3313 case GL_GREATER:
3314 case GL_NOTEQUAL:
3315 break;
3316 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003317 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003318 return false;
3319 }
3320
3321 return true;
3322}
3323
3324// Note that the spec specifies that for the path drawing commands
3325// if the path object is not an existing path object the command
3326// does nothing and no error is generated.
3327// However if the path object exists but has not been specified any
3328// commands then an error is generated.
3329
3330bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3331{
3332 if (!context->getExtensions().pathRendering)
3333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003334 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003335 return false;
3336 }
3337 if (context->hasPath(path) && !context->hasPathData(path))
3338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003339 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003340 return false;
3341 }
3342
3343 switch (fillMode)
3344 {
3345 case GL_COUNT_UP_CHROMIUM:
3346 case GL_COUNT_DOWN_CHROMIUM:
3347 break;
3348 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003349 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003350 return false;
3351 }
3352
3353 if (!isPow2(mask + 1))
3354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003355 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003356 return false;
3357 }
3358
3359 return true;
3360}
3361
3362bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3363{
3364 if (!context->getExtensions().pathRendering)
3365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003367 return false;
3368 }
3369 if (context->hasPath(path) && !context->hasPathData(path))
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003372 return false;
3373 }
3374
3375 return true;
3376}
3377
3378bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3379{
3380 if (!context->getExtensions().pathRendering)
3381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003382 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003383 return false;
3384 }
3385 if (context->hasPath(path) && !context->hasPathData(path))
3386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003387 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003388 return false;
3389 }
3390
3391 switch (coverMode)
3392 {
3393 case GL_CONVEX_HULL_CHROMIUM:
3394 case GL_BOUNDING_BOX_CHROMIUM:
3395 break;
3396 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003398 return false;
3399 }
3400 return true;
3401}
3402
3403bool ValidateStencilThenCoverFillPath(Context *context,
3404 GLuint path,
3405 GLenum fillMode,
3406 GLuint mask,
3407 GLenum coverMode)
3408{
3409 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3410 ValidateCoverPath(context, path, coverMode);
3411}
3412
3413bool ValidateStencilThenCoverStrokePath(Context *context,
3414 GLuint path,
3415 GLint reference,
3416 GLuint mask,
3417 GLenum coverMode)
3418{
3419 return ValidateStencilStrokePath(context, path, reference, mask) &&
3420 ValidateCoverPath(context, path, coverMode);
3421}
3422
3423bool ValidateIsPath(Context *context)
3424{
3425 if (!context->getExtensions().pathRendering)
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003428 return false;
3429 }
3430 return true;
3431}
3432
Sami Väisänend59ca052016-06-21 16:10:00 +03003433bool ValidateCoverFillPathInstanced(Context *context,
3434 GLsizei numPaths,
3435 GLenum pathNameType,
3436 const void *paths,
3437 GLuint pathBase,
3438 GLenum coverMode,
3439 GLenum transformType,
3440 const GLfloat *transformValues)
3441{
3442 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3443 transformType, transformValues))
3444 return false;
3445
3446 switch (coverMode)
3447 {
3448 case GL_CONVEX_HULL_CHROMIUM:
3449 case GL_BOUNDING_BOX_CHROMIUM:
3450 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3451 break;
3452 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003453 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003454 return false;
3455 }
3456
3457 return true;
3458}
3459
3460bool ValidateCoverStrokePathInstanced(Context *context,
3461 GLsizei numPaths,
3462 GLenum pathNameType,
3463 const void *paths,
3464 GLuint pathBase,
3465 GLenum coverMode,
3466 GLenum transformType,
3467 const GLfloat *transformValues)
3468{
3469 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3470 transformType, transformValues))
3471 return false;
3472
3473 switch (coverMode)
3474 {
3475 case GL_CONVEX_HULL_CHROMIUM:
3476 case GL_BOUNDING_BOX_CHROMIUM:
3477 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3478 break;
3479 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003480 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003481 return false;
3482 }
3483
3484 return true;
3485}
3486
3487bool ValidateStencilFillPathInstanced(Context *context,
3488 GLsizei numPaths,
3489 GLenum pathNameType,
3490 const void *paths,
3491 GLuint pathBase,
3492 GLenum fillMode,
3493 GLuint mask,
3494 GLenum transformType,
3495 const GLfloat *transformValues)
3496{
3497
3498 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3499 transformType, transformValues))
3500 return false;
3501
3502 switch (fillMode)
3503 {
3504 case GL_COUNT_UP_CHROMIUM:
3505 case GL_COUNT_DOWN_CHROMIUM:
3506 break;
3507 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003508 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003509 return false;
3510 }
3511 if (!isPow2(mask + 1))
3512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003513 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003514 return false;
3515 }
3516 return true;
3517}
3518
3519bool ValidateStencilStrokePathInstanced(Context *context,
3520 GLsizei numPaths,
3521 GLenum pathNameType,
3522 const void *paths,
3523 GLuint pathBase,
3524 GLint reference,
3525 GLuint mask,
3526 GLenum transformType,
3527 const GLfloat *transformValues)
3528{
3529 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3530 transformType, transformValues))
3531 return false;
3532
3533 // no more validation here.
3534
3535 return true;
3536}
3537
3538bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3539 GLsizei numPaths,
3540 GLenum pathNameType,
3541 const void *paths,
3542 GLuint pathBase,
3543 GLenum fillMode,
3544 GLuint mask,
3545 GLenum coverMode,
3546 GLenum transformType,
3547 const GLfloat *transformValues)
3548{
3549 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3550 transformType, transformValues))
3551 return false;
3552
3553 switch (coverMode)
3554 {
3555 case GL_CONVEX_HULL_CHROMIUM:
3556 case GL_BOUNDING_BOX_CHROMIUM:
3557 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3558 break;
3559 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003560 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003561 return false;
3562 }
3563
3564 switch (fillMode)
3565 {
3566 case GL_COUNT_UP_CHROMIUM:
3567 case GL_COUNT_DOWN_CHROMIUM:
3568 break;
3569 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003570 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003571 return false;
3572 }
3573 if (!isPow2(mask + 1))
3574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003575 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003576 return false;
3577 }
3578
3579 return true;
3580}
3581
3582bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3583 GLsizei numPaths,
3584 GLenum pathNameType,
3585 const void *paths,
3586 GLuint pathBase,
3587 GLint reference,
3588 GLuint mask,
3589 GLenum coverMode,
3590 GLenum transformType,
3591 const GLfloat *transformValues)
3592{
3593 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3594 transformType, transformValues))
3595 return false;
3596
3597 switch (coverMode)
3598 {
3599 case GL_CONVEX_HULL_CHROMIUM:
3600 case GL_BOUNDING_BOX_CHROMIUM:
3601 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3602 break;
3603 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003604 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003605 return false;
3606 }
3607
3608 return true;
3609}
3610
Sami Väisänen46eaa942016-06-29 10:26:37 +03003611bool ValidateBindFragmentInputLocation(Context *context,
3612 GLuint program,
3613 GLint location,
3614 const GLchar *name)
3615{
3616 if (!context->getExtensions().pathRendering)
3617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003619 return false;
3620 }
3621
3622 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3623 if (location >= MaxLocation)
3624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003626 return false;
3627 }
3628
3629 const auto *programObject = context->getProgram(program);
3630 if (!programObject)
3631 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003633 return false;
3634 }
3635
3636 if (!name)
3637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003638 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003639 return false;
3640 }
3641
3642 if (angle::BeginsWith(name, "gl_"))
3643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003644 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003645 return false;
3646 }
3647
3648 return true;
3649}
3650
3651bool ValidateProgramPathFragmentInputGen(Context *context,
3652 GLuint program,
3653 GLint location,
3654 GLenum genMode,
3655 GLint components,
3656 const GLfloat *coeffs)
3657{
3658 if (!context->getExtensions().pathRendering)
3659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003660 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003661 return false;
3662 }
3663
3664 const auto *programObject = context->getProgram(program);
3665 if (!programObject || programObject->isFlaggedForDeletion())
3666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003668 return false;
3669 }
3670
3671 if (!programObject->isLinked())
3672 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003674 return false;
3675 }
3676
3677 switch (genMode)
3678 {
3679 case GL_NONE:
3680 if (components != 0)
3681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003682 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003683 return false;
3684 }
3685 break;
3686
3687 case GL_OBJECT_LINEAR_CHROMIUM:
3688 case GL_EYE_LINEAR_CHROMIUM:
3689 case GL_CONSTANT_CHROMIUM:
3690 if (components < 1 || components > 4)
3691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003693 return false;
3694 }
3695 if (!coeffs)
3696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003698 return false;
3699 }
3700 break;
3701
3702 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003703 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003704 return false;
3705 }
3706
3707 // If the location is -1 then the command is silently ignored
3708 // and no further validation is needed.
3709 if (location == -1)
3710 return true;
3711
Jamie Madillbd044ed2017-06-05 12:59:21 -04003712 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003713
3714 if (!binding.valid)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003717 return false;
3718 }
3719
3720 if (binding.type != GL_NONE)
3721 {
3722 GLint expectedComponents = 0;
3723 switch (binding.type)
3724 {
3725 case GL_FLOAT:
3726 expectedComponents = 1;
3727 break;
3728 case GL_FLOAT_VEC2:
3729 expectedComponents = 2;
3730 break;
3731 case GL_FLOAT_VEC3:
3732 expectedComponents = 3;
3733 break;
3734 case GL_FLOAT_VEC4:
3735 expectedComponents = 4;
3736 break;
3737 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003738 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 InvalidOperation()
3740 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003741 return false;
3742 }
3743 if (expectedComponents != components && genMode != GL_NONE)
3744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003746 return false;
3747 }
3748 }
3749 return true;
3750}
3751
Geoff Lang97073d12016-04-20 10:42:34 -07003752bool ValidateCopyTextureCHROMIUM(Context *context,
3753 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003754 GLint sourceLevel,
3755 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003756 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003757 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003758 GLint internalFormat,
3759 GLenum destType,
3760 GLboolean unpackFlipY,
3761 GLboolean unpackPremultiplyAlpha,
3762 GLboolean unpackUnmultiplyAlpha)
3763{
3764 if (!context->getExtensions().copyTexture)
3765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003766 context->handleError(InvalidOperation()
3767 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003768 return false;
3769 }
3770
Geoff Lang4f0e0032017-05-01 16:04:35 -04003771 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003772 if (source == nullptr)
3773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003774 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003775 return false;
3776 }
3777
3778 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003780 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003781 return false;
3782 }
3783
3784 GLenum sourceTarget = source->getTarget();
3785 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003786
3787 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003790 return false;
3791 }
3792
Geoff Lang4f0e0032017-05-01 16:04:35 -04003793 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3794 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3795 if (sourceWidth == 0 || sourceHeight == 0)
3796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003798 return false;
3799 }
3800
3801 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3802 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003804 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003805 return false;
3806 }
3807
Geoff Lang4f0e0032017-05-01 16:04:35 -04003808 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003809 if (dest == nullptr)
3810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003811 context->handleError(InvalidValue()
3812 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003813 return false;
3814 }
3815
Geoff Lang4f0e0032017-05-01 16:04:35 -04003816 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003819 return false;
3820 }
3821
Geoff Lang4f0e0032017-05-01 16:04:35 -04003822 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3823 sourceHeight))
3824 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003825 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003826 return false;
3827 }
3828
Geoff Lang97073d12016-04-20 10:42:34 -07003829 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003831 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003832 return false;
3833 }
3834
Geoff Lang4f0e0032017-05-01 16:04:35 -04003835 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(
3838 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003839 return false;
3840 }
3841
Geoff Lang97073d12016-04-20 10:42:34 -07003842 if (dest->getImmutableFormat())
3843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003844 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003845 return false;
3846 }
3847
3848 return true;
3849}
3850
3851bool ValidateCopySubTextureCHROMIUM(Context *context,
3852 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003853 GLint sourceLevel,
3854 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003855 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003856 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003857 GLint xoffset,
3858 GLint yoffset,
3859 GLint x,
3860 GLint y,
3861 GLsizei width,
3862 GLsizei height,
3863 GLboolean unpackFlipY,
3864 GLboolean unpackPremultiplyAlpha,
3865 GLboolean unpackUnmultiplyAlpha)
3866{
3867 if (!context->getExtensions().copyTexture)
3868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidOperation()
3870 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003871 return false;
3872 }
3873
Geoff Lang4f0e0032017-05-01 16:04:35 -04003874 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003875 if (source == nullptr)
3876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003878 return false;
3879 }
3880
3881 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003884 return false;
3885 }
3886
3887 GLenum sourceTarget = source->getTarget();
3888 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003889
3890 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003892 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003893 return false;
3894 }
3895
3896 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3897 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidValue()
3900 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003901 return false;
3902 }
3903
3904 if (x < 0 || y < 0)
3905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003906 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003907 return false;
3908 }
3909
3910 if (width < 0 || height < 0)
3911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003912 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003913 return false;
3914 }
3915
Geoff Lang4f0e0032017-05-01 16:04:35 -04003916 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3917 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003919 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003920 return false;
3921 }
3922
Geoff Lang4f0e0032017-05-01 16:04:35 -04003923 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3924 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003927 return false;
3928 }
3929
Geoff Lang4f0e0032017-05-01 16:04:35 -04003930 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003931 if (dest == nullptr)
3932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidValue()
3934 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003935 return false;
3936 }
3937
Geoff Lang4f0e0032017-05-01 16:04:35 -04003938 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003940 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003941 return false;
3942 }
3943
Geoff Lang4f0e0032017-05-01 16:04:35 -04003944 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003946 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003947 return false;
3948 }
3949
Geoff Lang4f0e0032017-05-01 16:04:35 -04003950 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3951 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003952 context
3953 ->handleError(InvalidOperation()
3954 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003955 return false;
3956 }
3957
3958 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3959 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003961 context->handleError(InvalidOperation()
3962 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003963 return false;
3964 }
3965
3966 if (xoffset < 0 || yoffset < 0)
3967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003968 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07003969 return false;
3970 }
3971
Geoff Lang4f0e0032017-05-01 16:04:35 -04003972 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3973 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003975 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003976 return false;
3977 }
3978
3979 return true;
3980}
3981
Geoff Lang47110bf2016-04-20 11:13:22 -07003982bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3983{
3984 if (!context->getExtensions().copyCompressedTexture)
3985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(InvalidOperation()
3987 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003988 return false;
3989 }
3990
3991 const gl::Texture *source = context->getTexture(sourceId);
3992 if (source == nullptr)
3993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003994 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003995 return false;
3996 }
3997
3998 if (source->getTarget() != GL_TEXTURE_2D)
3999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004000 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004001 return false;
4002 }
4003
4004 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004006 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004007 return false;
4008 }
4009
4010 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4011 if (!sourceFormat.info->compressed)
4012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004013 context->handleError(InvalidOperation()
4014 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004015 return false;
4016 }
4017
4018 const gl::Texture *dest = context->getTexture(destId);
4019 if (dest == nullptr)
4020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004021 context->handleError(InvalidValue()
4022 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004023 return false;
4024 }
4025
4026 if (dest->getTarget() != GL_TEXTURE_2D)
4027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004028 context->handleError(InvalidValue()
4029 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004030 return false;
4031 }
4032
4033 if (dest->getImmutableFormat())
4034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004035 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004036 return false;
4037 }
4038
4039 return true;
4040}
4041
Martin Radev4c4c8e72016-08-04 12:25:34 +03004042bool ValidateCreateShader(Context *context, GLenum type)
4043{
4044 switch (type)
4045 {
4046 case GL_VERTEX_SHADER:
4047 case GL_FRAGMENT_SHADER:
4048 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004049
Martin Radev4c4c8e72016-08-04 12:25:34 +03004050 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004051 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004053 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04004054 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004055 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004056 break;
4057
Martin Radev4c4c8e72016-08-04 12:25:34 +03004058 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004059 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004060 return false;
4061 }
Jamie Madill29639852016-09-02 15:00:09 -04004062
4063 return true;
4064}
4065
4066bool ValidateBufferData(ValidationContext *context,
4067 GLenum target,
4068 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004069 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04004070 GLenum usage)
4071{
4072 if (size < 0)
4073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004074 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004075 return false;
4076 }
4077
4078 switch (usage)
4079 {
4080 case GL_STREAM_DRAW:
4081 case GL_STATIC_DRAW:
4082 case GL_DYNAMIC_DRAW:
4083 break;
4084
4085 case GL_STREAM_READ:
4086 case GL_STREAM_COPY:
4087 case GL_STATIC_READ:
4088 case GL_STATIC_COPY:
4089 case GL_DYNAMIC_READ:
4090 case GL_DYNAMIC_COPY:
4091 if (context->getClientMajorVersion() < 3)
4092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004094 return false;
4095 }
4096 break;
4097
4098 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004100 return false;
4101 }
4102
4103 if (!ValidBufferTarget(context, target))
4104 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004106 return false;
4107 }
4108
4109 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4110
4111 if (!buffer)
4112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004114 return false;
4115 }
4116
4117 return true;
4118}
4119
4120bool ValidateBufferSubData(ValidationContext *context,
4121 GLenum target,
4122 GLintptr offset,
4123 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004124 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004125{
Brandon Jones6cad5662017-06-14 13:25:13 -07004126 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004128 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4129 return false;
4130 }
4131
4132 if (offset < 0)
4133 {
4134 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004135 return false;
4136 }
4137
4138 if (!ValidBufferTarget(context, target))
4139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004141 return false;
4142 }
4143
4144 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4145
4146 if (!buffer)
4147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004149 return false;
4150 }
4151
4152 if (buffer->isMapped())
4153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004154 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004155 return false;
4156 }
4157
4158 // Check for possible overflow of size + offset
4159 angle::CheckedNumeric<size_t> checkedSize(size);
4160 checkedSize += offset;
4161 if (!checkedSize.IsValid())
4162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004163 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004164 return false;
4165 }
4166
4167 if (size + offset > buffer->getSize())
4168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004169 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004170 return false;
4171 }
4172
Martin Radev4c4c8e72016-08-04 12:25:34 +03004173 return true;
4174}
4175
Geoff Langc339c4e2016-11-29 10:37:36 -05004176bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004177{
Geoff Langc339c4e2016-11-29 10:37:36 -05004178 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004180 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004181 return false;
4182 }
4183
4184 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
4185 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05004186 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04004187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004188 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004189 return false;
4190 }
4191
4192 return true;
4193}
4194
Jamie Madillef300b12016-10-07 15:12:09 -04004195bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4196{
4197 if (texture < GL_TEXTURE0 ||
4198 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004200 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004201 return false;
4202 }
4203
4204 return true;
4205}
4206
4207bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4208{
4209 Program *programObject = GetValidProgram(context, program);
4210 if (!programObject)
4211 {
4212 return false;
4213 }
4214
4215 Shader *shaderObject = GetValidShader(context, shader);
4216 if (!shaderObject)
4217 {
4218 return false;
4219 }
4220
4221 switch (shaderObject->getType())
4222 {
4223 case GL_VERTEX_SHADER:
4224 {
4225 if (programObject->getAttachedVertexShader())
4226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004228 return false;
4229 }
4230 break;
4231 }
4232 case GL_FRAGMENT_SHADER:
4233 {
4234 if (programObject->getAttachedFragmentShader())
4235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004237 return false;
4238 }
4239 break;
4240 }
4241 case GL_COMPUTE_SHADER:
4242 {
4243 if (programObject->getAttachedComputeShader())
4244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004246 return false;
4247 }
4248 break;
4249 }
4250 default:
4251 UNREACHABLE();
4252 break;
4253 }
4254
4255 return true;
4256}
4257
Jamie Madill01a80ee2016-11-07 12:06:18 -05004258bool ValidateBindAttribLocation(ValidationContext *context,
4259 GLuint program,
4260 GLuint index,
4261 const GLchar *name)
4262{
4263 if (index >= MAX_VERTEX_ATTRIBS)
4264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004265 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004266 return false;
4267 }
4268
4269 if (strncmp(name, "gl_", 3) == 0)
4270 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004271 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004272 return false;
4273 }
4274
Geoff Langfc32e8b2017-05-31 14:16:59 -04004275 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4276 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04004277 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004278 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004279 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004280 return false;
4281 }
4282
Jamie Madill01a80ee2016-11-07 12:06:18 -05004283 return GetValidProgram(context, program) != nullptr;
4284}
4285
4286bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4287{
4288 if (!ValidBufferTarget(context, target))
4289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004290 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004291 return false;
4292 }
4293
4294 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4295 !context->isBufferGenerated(buffer))
4296 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004298 return false;
4299 }
4300
4301 return true;
4302}
4303
4304bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4305{
4306 if (!ValidFramebufferTarget(target))
4307 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004308 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004309 return false;
4310 }
4311
4312 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4313 !context->isFramebufferGenerated(framebuffer))
4314 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004315 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004316 return false;
4317 }
4318
4319 return true;
4320}
4321
4322bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4323{
4324 if (target != GL_RENDERBUFFER)
4325 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004326 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004327 return false;
4328 }
4329
4330 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4331 !context->isRenderbufferGenerated(renderbuffer))
4332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004334 return false;
4335 }
4336
4337 return true;
4338}
4339
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004340static bool ValidBlendEquationMode(GLenum mode)
4341{
4342 switch (mode)
4343 {
4344 case GL_FUNC_ADD:
4345 case GL_FUNC_SUBTRACT:
4346 case GL_FUNC_REVERSE_SUBTRACT:
4347 case GL_MIN:
4348 case GL_MAX:
4349 return true;
4350
4351 default:
4352 return false;
4353 }
4354}
4355
Jamie Madillc1d770e2017-04-13 17:31:24 -04004356bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004357 GLfloat red,
4358 GLfloat green,
4359 GLfloat blue,
4360 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004361{
4362 return true;
4363}
4364
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004365bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4366{
4367 if (!ValidBlendEquationMode(mode))
4368 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004369 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004370 return false;
4371 }
4372
4373 return true;
4374}
4375
4376bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4377{
4378 if (!ValidBlendEquationMode(modeRGB))
4379 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004381 return false;
4382 }
4383
4384 if (!ValidBlendEquationMode(modeAlpha))
4385 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004387 return false;
4388 }
4389
4390 return true;
4391}
4392
4393bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4394{
4395 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4396}
4397
4398static bool ValidSrcBlendFunc(GLenum srcBlend)
4399{
4400 switch (srcBlend)
4401 {
4402 case GL_ZERO:
4403 case GL_ONE:
4404 case GL_SRC_COLOR:
4405 case GL_ONE_MINUS_SRC_COLOR:
4406 case GL_DST_COLOR:
4407 case GL_ONE_MINUS_DST_COLOR:
4408 case GL_SRC_ALPHA:
4409 case GL_ONE_MINUS_SRC_ALPHA:
4410 case GL_DST_ALPHA:
4411 case GL_ONE_MINUS_DST_ALPHA:
4412 case GL_CONSTANT_COLOR:
4413 case GL_ONE_MINUS_CONSTANT_COLOR:
4414 case GL_CONSTANT_ALPHA:
4415 case GL_ONE_MINUS_CONSTANT_ALPHA:
4416 case GL_SRC_ALPHA_SATURATE:
4417 return true;
4418
4419 default:
4420 return false;
4421 }
4422}
4423
4424static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4425{
4426 switch (dstBlend)
4427 {
4428 case GL_ZERO:
4429 case GL_ONE:
4430 case GL_SRC_COLOR:
4431 case GL_ONE_MINUS_SRC_COLOR:
4432 case GL_DST_COLOR:
4433 case GL_ONE_MINUS_DST_COLOR:
4434 case GL_SRC_ALPHA:
4435 case GL_ONE_MINUS_SRC_ALPHA:
4436 case GL_DST_ALPHA:
4437 case GL_ONE_MINUS_DST_ALPHA:
4438 case GL_CONSTANT_COLOR:
4439 case GL_ONE_MINUS_CONSTANT_COLOR:
4440 case GL_CONSTANT_ALPHA:
4441 case GL_ONE_MINUS_CONSTANT_ALPHA:
4442 return true;
4443
4444 case GL_SRC_ALPHA_SATURATE:
4445 return (contextMajorVersion >= 3);
4446
4447 default:
4448 return false;
4449 }
4450}
4451
4452bool ValidateBlendFuncSeparate(ValidationContext *context,
4453 GLenum srcRGB,
4454 GLenum dstRGB,
4455 GLenum srcAlpha,
4456 GLenum dstAlpha)
4457{
4458 if (!ValidSrcBlendFunc(srcRGB))
4459 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004460 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004461 return false;
4462 }
4463
4464 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4465 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004466 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004467 return false;
4468 }
4469
4470 if (!ValidSrcBlendFunc(srcAlpha))
4471 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004473 return false;
4474 }
4475
4476 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4477 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004479 return false;
4480 }
4481
Frank Henigman146e8a12017-03-02 23:22:37 -05004482 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4483 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004484 {
4485 bool constantColorUsed =
4486 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4487 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4488
4489 bool constantAlphaUsed =
4490 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4491 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4492
4493 if (constantColorUsed && constantAlphaUsed)
4494 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004495 const char *msg;
4496 if (context->getExtensions().webglCompatibility)
4497 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004498 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004499 }
4500 else
4501 {
4502 msg =
4503 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4504 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4505 "implementation.";
4506 ERR() << msg;
4507 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004508 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004509 return false;
4510 }
4511 }
4512
4513 return true;
4514}
4515
Geoff Langc339c4e2016-11-29 10:37:36 -05004516bool ValidateGetString(Context *context, GLenum name)
4517{
4518 switch (name)
4519 {
4520 case GL_VENDOR:
4521 case GL_RENDERER:
4522 case GL_VERSION:
4523 case GL_SHADING_LANGUAGE_VERSION:
4524 case GL_EXTENSIONS:
4525 break;
4526
4527 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4528 if (!context->getExtensions().requestExtension)
4529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004530 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004531 return false;
4532 }
4533 break;
4534
4535 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004536 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004537 return false;
4538 }
4539
4540 return true;
4541}
4542
Geoff Lang47c48082016-12-07 15:38:13 -05004543bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4544{
4545 if (width <= 0.0f || isNaN(width))
4546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004547 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004548 return false;
4549 }
4550
4551 return true;
4552}
4553
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004554bool ValidateVertexAttribPointer(ValidationContext *context,
4555 GLuint index,
4556 GLint size,
4557 GLenum type,
4558 GLboolean normalized,
4559 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004560 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004561{
Shao80957d92017-02-20 21:25:59 +08004562 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004563 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004564 return false;
4565 }
4566
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004567 if (stride < 0)
4568 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004569 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004570 return false;
4571 }
4572
Shao80957d92017-02-20 21:25:59 +08004573 const Caps &caps = context->getCaps();
4574 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004575 {
Shao80957d92017-02-20 21:25:59 +08004576 if (stride > caps.maxVertexAttribStride)
4577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004578 context->handleError(InvalidValue()
4579 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004580 return false;
4581 }
4582
4583 if (index >= caps.maxVertexAttribBindings)
4584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004585 context->handleError(InvalidValue()
4586 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004587 return false;
4588 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004589 }
4590
4591 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4592 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4593 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4594 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004595 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4596 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004597 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004599 context
4600 ->handleError(InvalidOperation()
4601 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004602 return false;
4603 }
4604
4605 if (context->getExtensions().webglCompatibility)
4606 {
4607 // WebGL 1.0 [Section 6.14] Fixed point support
4608 // The WebGL API does not support the GL_FIXED data type.
4609 if (type == GL_FIXED)
4610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004611 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004612 return false;
4613 }
4614
Geoff Lang2d62ab72017-03-23 16:54:40 -04004615 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004616 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004617 return false;
4618 }
4619 }
4620
4621 return true;
4622}
4623
Jamie Madill876429b2017-04-20 15:46:24 -04004624bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004625{
4626 if (context->getExtensions().webglCompatibility && zNear > zFar)
4627 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004629 return false;
4630 }
4631
4632 return true;
4633}
4634
Jamie Madille8fb6402017-02-14 17:56:40 -05004635bool ValidateRenderbufferStorage(ValidationContext *context,
4636 GLenum target,
4637 GLenum internalformat,
4638 GLsizei width,
4639 GLsizei height)
4640{
4641 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4642 height);
4643}
4644
4645bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4646 GLenum target,
4647 GLsizei samples,
4648 GLenum internalformat,
4649 GLsizei width,
4650 GLsizei height)
4651{
4652 if (!context->getExtensions().framebufferMultisample)
4653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004654 context->handleError(InvalidOperation()
4655 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004656 return false;
4657 }
4658
4659 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4660 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4661 // generated.
4662 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004664 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004665 return false;
4666 }
4667
4668 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4669 // the specified storage. This is different than ES 3.0 in which a sample number higher
4670 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4671 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4672 if (context->getClientMajorVersion() >= 3)
4673 {
4674 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4675 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004677 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004678 return false;
4679 }
4680 }
4681
4682 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4683 width, height);
4684}
4685
Jamie Madillc1d770e2017-04-13 17:31:24 -04004686bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4687{
4688 if (!ValidFramebufferTarget(target))
4689 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004690 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004691 return false;
4692 }
4693
4694 return true;
4695}
4696
4697bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004698 GLfloat red,
4699 GLfloat green,
4700 GLfloat blue,
4701 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004702{
4703 return true;
4704}
4705
Jamie Madill876429b2017-04-20 15:46:24 -04004706bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004707{
4708 return true;
4709}
4710
4711bool ValidateClearStencil(ValidationContext *context, GLint s)
4712{
4713 return true;
4714}
4715
4716bool ValidateColorMask(ValidationContext *context,
4717 GLboolean red,
4718 GLboolean green,
4719 GLboolean blue,
4720 GLboolean alpha)
4721{
4722 return true;
4723}
4724
4725bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4726{
4727 return true;
4728}
4729
4730bool ValidateCreateProgram(ValidationContext *context)
4731{
4732 return true;
4733}
4734
4735bool ValidateCullFace(ValidationContext *context, GLenum mode)
4736{
4737 switch (mode)
4738 {
4739 case GL_FRONT:
4740 case GL_BACK:
4741 case GL_FRONT_AND_BACK:
4742 break;
4743
4744 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004745 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004746 return false;
4747 }
4748
4749 return true;
4750}
4751
4752bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4753{
4754 if (program == 0)
4755 {
4756 return false;
4757 }
4758
4759 if (!context->getProgram(program))
4760 {
4761 if (context->getShader(program))
4762 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004763 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004764 return false;
4765 }
4766 else
4767 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004768 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004769 return false;
4770 }
4771 }
4772
4773 return true;
4774}
4775
4776bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4777{
4778 if (shader == 0)
4779 {
4780 return false;
4781 }
4782
4783 if (!context->getShader(shader))
4784 {
4785 if (context->getProgram(shader))
4786 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004788 return false;
4789 }
4790 else
4791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004792 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004793 return false;
4794 }
4795 }
4796
4797 return true;
4798}
4799
4800bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4801{
4802 switch (func)
4803 {
4804 case GL_NEVER:
4805 case GL_ALWAYS:
4806 case GL_LESS:
4807 case GL_LEQUAL:
4808 case GL_EQUAL:
4809 case GL_GREATER:
4810 case GL_GEQUAL:
4811 case GL_NOTEQUAL:
4812 break;
4813
4814 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004816 return false;
4817 }
4818
4819 return true;
4820}
4821
4822bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4823{
4824 return true;
4825}
4826
4827bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4828{
4829 Program *programObject = GetValidProgram(context, program);
4830 if (!programObject)
4831 {
4832 return false;
4833 }
4834
4835 Shader *shaderObject = GetValidShader(context, shader);
4836 if (!shaderObject)
4837 {
4838 return false;
4839 }
4840
4841 const Shader *attachedShader = nullptr;
4842
4843 switch (shaderObject->getType())
4844 {
4845 case GL_VERTEX_SHADER:
4846 {
4847 attachedShader = programObject->getAttachedVertexShader();
4848 break;
4849 }
4850 case GL_FRAGMENT_SHADER:
4851 {
4852 attachedShader = programObject->getAttachedFragmentShader();
4853 break;
4854 }
4855 case GL_COMPUTE_SHADER:
4856 {
4857 attachedShader = programObject->getAttachedComputeShader();
4858 break;
4859 }
4860 default:
4861 UNREACHABLE();
4862 return false;
4863 }
4864
4865 if (attachedShader != shaderObject)
4866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004868 return false;
4869 }
4870
4871 return true;
4872}
4873
4874bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4875{
4876 if (index >= MAX_VERTEX_ATTRIBS)
4877 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004878 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004879 return false;
4880 }
4881
4882 return true;
4883}
4884
4885bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4886{
4887 if (index >= MAX_VERTEX_ATTRIBS)
4888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004889 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004890 return false;
4891 }
4892
4893 return true;
4894}
4895
4896bool ValidateFinish(ValidationContext *context)
4897{
4898 return true;
4899}
4900
4901bool ValidateFlush(ValidationContext *context)
4902{
4903 return true;
4904}
4905
4906bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4907{
4908 switch (mode)
4909 {
4910 case GL_CW:
4911 case GL_CCW:
4912 break;
4913 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004915 return false;
4916 }
4917
4918 return true;
4919}
4920
4921bool ValidateGetActiveAttrib(ValidationContext *context,
4922 GLuint program,
4923 GLuint index,
4924 GLsizei bufsize,
4925 GLsizei *length,
4926 GLint *size,
4927 GLenum *type,
4928 GLchar *name)
4929{
4930 if (bufsize < 0)
4931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004933 return false;
4934 }
4935
4936 Program *programObject = GetValidProgram(context, program);
4937
4938 if (!programObject)
4939 {
4940 return false;
4941 }
4942
4943 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004945 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004946 return false;
4947 }
4948
4949 return true;
4950}
4951
4952bool ValidateGetActiveUniform(ValidationContext *context,
4953 GLuint program,
4954 GLuint index,
4955 GLsizei bufsize,
4956 GLsizei *length,
4957 GLint *size,
4958 GLenum *type,
4959 GLchar *name)
4960{
4961 if (bufsize < 0)
4962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004964 return false;
4965 }
4966
4967 Program *programObject = GetValidProgram(context, program);
4968
4969 if (!programObject)
4970 {
4971 return false;
4972 }
4973
4974 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004976 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004977 return false;
4978 }
4979
4980 return true;
4981}
4982
4983bool ValidateGetAttachedShaders(ValidationContext *context,
4984 GLuint program,
4985 GLsizei maxcount,
4986 GLsizei *count,
4987 GLuint *shaders)
4988{
4989 if (maxcount < 0)
4990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004991 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004992 return false;
4993 }
4994
4995 Program *programObject = GetValidProgram(context, program);
4996
4997 if (!programObject)
4998 {
4999 return false;
5000 }
5001
5002 return true;
5003}
5004
5005bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5006{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005007 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5008 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005009 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005011 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005012 return false;
5013 }
5014
Jamie Madillc1d770e2017-04-13 17:31:24 -04005015 Program *programObject = GetValidProgram(context, program);
5016
5017 if (!programObject)
5018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005020 return false;
5021 }
5022
5023 if (!programObject->isLinked())
5024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005026 return false;
5027 }
5028
5029 return true;
5030}
5031
5032bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5033{
5034 GLenum nativeType;
5035 unsigned int numParams = 0;
5036 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5037}
5038
5039bool ValidateGetError(ValidationContext *context)
5040{
5041 return true;
5042}
5043
5044bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5045{
5046 GLenum nativeType;
5047 unsigned int numParams = 0;
5048 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5049}
5050
5051bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5052{
5053 GLenum nativeType;
5054 unsigned int numParams = 0;
5055 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5056}
5057
5058bool ValidateGetProgramInfoLog(ValidationContext *context,
5059 GLuint program,
5060 GLsizei bufsize,
5061 GLsizei *length,
5062 GLchar *infolog)
5063{
5064 if (bufsize < 0)
5065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005066 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005067 return false;
5068 }
5069
5070 Program *programObject = GetValidProgram(context, program);
5071 if (!programObject)
5072 {
5073 return false;
5074 }
5075
5076 return true;
5077}
5078
5079bool ValidateGetShaderInfoLog(ValidationContext *context,
5080 GLuint shader,
5081 GLsizei bufsize,
5082 GLsizei *length,
5083 GLchar *infolog)
5084{
5085 if (bufsize < 0)
5086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005087 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005088 return false;
5089 }
5090
5091 Shader *shaderObject = GetValidShader(context, shader);
5092 if (!shaderObject)
5093 {
5094 return false;
5095 }
5096
5097 return true;
5098}
5099
5100bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5101 GLenum shadertype,
5102 GLenum precisiontype,
5103 GLint *range,
5104 GLint *precision)
5105{
5106 switch (shadertype)
5107 {
5108 case GL_VERTEX_SHADER:
5109 case GL_FRAGMENT_SHADER:
5110 break;
5111 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005112 context->handleError(InvalidOperation()
5113 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005114 return false;
5115 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005117 return false;
5118 }
5119
5120 switch (precisiontype)
5121 {
5122 case GL_LOW_FLOAT:
5123 case GL_MEDIUM_FLOAT:
5124 case GL_HIGH_FLOAT:
5125 case GL_LOW_INT:
5126 case GL_MEDIUM_INT:
5127 case GL_HIGH_INT:
5128 break;
5129
5130 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005132 return false;
5133 }
5134
5135 return true;
5136}
5137
5138bool ValidateGetShaderSource(ValidationContext *context,
5139 GLuint shader,
5140 GLsizei bufsize,
5141 GLsizei *length,
5142 GLchar *source)
5143{
5144 if (bufsize < 0)
5145 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005146 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005147 return false;
5148 }
5149
5150 Shader *shaderObject = GetValidShader(context, shader);
5151 if (!shaderObject)
5152 {
5153 return false;
5154 }
5155
5156 return true;
5157}
5158
5159bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5160{
5161 if (strstr(name, "gl_") == name)
5162 {
5163 return false;
5164 }
5165
Geoff Langfc32e8b2017-05-31 14:16:59 -04005166 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5167 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005168 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005170 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005171 return false;
5172 }
5173
Jamie Madillc1d770e2017-04-13 17:31:24 -04005174 Program *programObject = GetValidProgram(context, program);
5175
5176 if (!programObject)
5177 {
5178 return false;
5179 }
5180
5181 if (!programObject->isLinked())
5182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005184 return false;
5185 }
5186
5187 return true;
5188}
5189
5190bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5191{
5192 switch (mode)
5193 {
5194 case GL_FASTEST:
5195 case GL_NICEST:
5196 case GL_DONT_CARE:
5197 break;
5198
5199 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005200 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005201 return false;
5202 }
5203
5204 switch (target)
5205 {
5206 case GL_GENERATE_MIPMAP_HINT:
5207 break;
5208
Geoff Lange7bd2182017-06-16 16:13:13 -04005209 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5210 if (context->getClientVersion() < ES_3_0 &&
5211 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005213 context->handleError(InvalidOperation()
5214 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005215 return false;
5216 }
5217 break;
5218
5219 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005221 return false;
5222 }
5223
5224 return true;
5225}
5226
5227bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5228{
5229 return true;
5230}
5231
5232bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5233{
5234 return true;
5235}
5236
5237bool ValidateIsProgram(ValidationContext *context, GLuint program)
5238{
5239 return true;
5240}
5241
5242bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5243{
5244 return true;
5245}
5246
5247bool ValidateIsShader(ValidationContext *context, GLuint shader)
5248{
5249 return true;
5250}
5251
5252bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5253{
5254 return true;
5255}
5256
5257bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5258{
5259 if (context->getClientMajorVersion() < 3)
5260 {
5261 switch (pname)
5262 {
5263 case GL_UNPACK_IMAGE_HEIGHT:
5264 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005265 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005266 return false;
5267
5268 case GL_UNPACK_ROW_LENGTH:
5269 case GL_UNPACK_SKIP_ROWS:
5270 case GL_UNPACK_SKIP_PIXELS:
5271 if (!context->getExtensions().unpackSubimage)
5272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005273 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005274 return false;
5275 }
5276 break;
5277
5278 case GL_PACK_ROW_LENGTH:
5279 case GL_PACK_SKIP_ROWS:
5280 case GL_PACK_SKIP_PIXELS:
5281 if (!context->getExtensions().packSubimage)
5282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005283 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005284 return false;
5285 }
5286 break;
5287 }
5288 }
5289
5290 if (param < 0)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005293 return false;
5294 }
5295
5296 switch (pname)
5297 {
5298 case GL_UNPACK_ALIGNMENT:
5299 if (param != 1 && param != 2 && param != 4 && param != 8)
5300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005301 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005302 return false;
5303 }
5304 break;
5305
5306 case GL_PACK_ALIGNMENT:
5307 if (param != 1 && param != 2 && param != 4 && param != 8)
5308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005309 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005310 return false;
5311 }
5312 break;
5313
5314 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5315 case GL_UNPACK_ROW_LENGTH:
5316 case GL_UNPACK_IMAGE_HEIGHT:
5317 case GL_UNPACK_SKIP_IMAGES:
5318 case GL_UNPACK_SKIP_ROWS:
5319 case GL_UNPACK_SKIP_PIXELS:
5320 case GL_PACK_ROW_LENGTH:
5321 case GL_PACK_SKIP_ROWS:
5322 case GL_PACK_SKIP_PIXELS:
5323 break;
5324
5325 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005326 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005327 return false;
5328 }
5329
5330 return true;
5331}
5332
5333bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5334{
5335 return true;
5336}
5337
5338bool ValidateReleaseShaderCompiler(ValidationContext *context)
5339{
5340 return true;
5341}
5342
Jamie Madill876429b2017-04-20 15:46:24 -04005343bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005344{
5345 return true;
5346}
5347
5348bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5349{
5350 if (width < 0 || height < 0)
5351 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005352 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005353 return false;
5354 }
5355
5356 return true;
5357}
5358
5359bool ValidateShaderBinary(ValidationContext *context,
5360 GLsizei n,
5361 const GLuint *shaders,
5362 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005363 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005364 GLsizei length)
5365{
5366 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5367 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5368 shaderBinaryFormats.end())
5369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005370 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005371 return false;
5372 }
5373
5374 return true;
5375}
5376
5377bool ValidateShaderSource(ValidationContext *context,
5378 GLuint shader,
5379 GLsizei count,
5380 const GLchar *const *string,
5381 const GLint *length)
5382{
5383 if (count < 0)
5384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005386 return false;
5387 }
5388
Geoff Langfc32e8b2017-05-31 14:16:59 -04005389 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5390 // shader-related entry points
5391 if (context->getExtensions().webglCompatibility)
5392 {
5393 for (GLsizei i = 0; i < count; i++)
5394 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005395 size_t len =
5396 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005397
5398 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005399 if (!IsValidESSLShaderSourceString(string[i], len,
5400 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005401 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005402 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005403 return false;
5404 }
5405 }
5406 }
5407
Jamie Madillc1d770e2017-04-13 17:31:24 -04005408 Shader *shaderObject = GetValidShader(context, shader);
5409 if (!shaderObject)
5410 {
5411 return false;
5412 }
5413
5414 return true;
5415}
5416
5417bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5418{
5419 if (!IsValidStencilFunc(func))
5420 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005422 return false;
5423 }
5424
5425 return true;
5426}
5427
5428bool ValidateStencilFuncSeparate(ValidationContext *context,
5429 GLenum face,
5430 GLenum func,
5431 GLint ref,
5432 GLuint mask)
5433{
5434 if (!IsValidStencilFace(face))
5435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005437 return false;
5438 }
5439
5440 if (!IsValidStencilFunc(func))
5441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005443 return false;
5444 }
5445
5446 return true;
5447}
5448
5449bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5450{
5451 return true;
5452}
5453
5454bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5455{
5456 if (!IsValidStencilFace(face))
5457 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005459 return false;
5460 }
5461
5462 return true;
5463}
5464
5465bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5466{
5467 if (!IsValidStencilOp(fail))
5468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005470 return false;
5471 }
5472
5473 if (!IsValidStencilOp(zfail))
5474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005475 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005476 return false;
5477 }
5478
5479 if (!IsValidStencilOp(zpass))
5480 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005482 return false;
5483 }
5484
5485 return true;
5486}
5487
5488bool ValidateStencilOpSeparate(ValidationContext *context,
5489 GLenum face,
5490 GLenum fail,
5491 GLenum zfail,
5492 GLenum zpass)
5493{
5494 if (!IsValidStencilFace(face))
5495 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005496 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005497 return false;
5498 }
5499
5500 return ValidateStencilOp(context, fail, zfail, zpass);
5501}
5502
5503bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5504{
5505 return ValidateUniform(context, GL_FLOAT, location, 1);
5506}
5507
5508bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5509{
5510 return ValidateUniform(context, GL_FLOAT, location, count);
5511}
5512
Jamie Madillbe849e42017-05-02 15:49:00 -04005513bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5514{
5515 return ValidateUniform1iv(context, location, 1, &x);
5516}
5517
Jamie Madillc1d770e2017-04-13 17:31:24 -04005518bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5519{
5520 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5521}
5522
5523bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5524{
5525 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5526}
5527
5528bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5529{
5530 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5531}
5532
5533bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5534{
5535 return ValidateUniform(context, GL_INT_VEC2, location, count);
5536}
5537
5538bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5539{
5540 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5541}
5542
5543bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5544{
5545 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5546}
5547
5548bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5549{
5550 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5551}
5552
5553bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5554{
5555 return ValidateUniform(context, GL_INT_VEC3, location, count);
5556}
5557
5558bool ValidateUniform4f(ValidationContext *context,
5559 GLint location,
5560 GLfloat x,
5561 GLfloat y,
5562 GLfloat z,
5563 GLfloat w)
5564{
5565 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5566}
5567
5568bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5569{
5570 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5571}
5572
5573bool ValidateUniform4i(ValidationContext *context,
5574 GLint location,
5575 GLint x,
5576 GLint y,
5577 GLint z,
5578 GLint w)
5579{
5580 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5581}
5582
5583bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5584{
5585 return ValidateUniform(context, GL_INT_VEC4, location, count);
5586}
5587
5588bool ValidateUniformMatrix2fv(ValidationContext *context,
5589 GLint location,
5590 GLsizei count,
5591 GLboolean transpose,
5592 const GLfloat *value)
5593{
5594 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5595}
5596
5597bool ValidateUniformMatrix3fv(ValidationContext *context,
5598 GLint location,
5599 GLsizei count,
5600 GLboolean transpose,
5601 const GLfloat *value)
5602{
5603 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5604}
5605
5606bool ValidateUniformMatrix4fv(ValidationContext *context,
5607 GLint location,
5608 GLsizei count,
5609 GLboolean transpose,
5610 const GLfloat *value)
5611{
5612 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5613}
5614
5615bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5616{
5617 Program *programObject = GetValidProgram(context, program);
5618
5619 if (!programObject)
5620 {
5621 return false;
5622 }
5623
5624 return true;
5625}
5626
5627bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5628{
5629 if (index >= MAX_VERTEX_ATTRIBS)
5630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005631 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005632 return false;
5633 }
5634
5635 return true;
5636}
5637
5638bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5639{
5640 return ValidateVertexAttribIndex(context, index);
5641}
5642
5643bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5644{
5645 return ValidateVertexAttribIndex(context, index);
5646}
5647
5648bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5649{
5650 return ValidateVertexAttribIndex(context, index);
5651}
5652
5653bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5654{
5655 return ValidateVertexAttribIndex(context, index);
5656}
5657
5658bool ValidateVertexAttrib3f(ValidationContext *context,
5659 GLuint index,
5660 GLfloat x,
5661 GLfloat y,
5662 GLfloat z)
5663{
5664 return ValidateVertexAttribIndex(context, index);
5665}
5666
5667bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5668{
5669 return ValidateVertexAttribIndex(context, index);
5670}
5671
5672bool ValidateVertexAttrib4f(ValidationContext *context,
5673 GLuint index,
5674 GLfloat x,
5675 GLfloat y,
5676 GLfloat z,
5677 GLfloat w)
5678{
5679 return ValidateVertexAttribIndex(context, index);
5680}
5681
5682bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5683{
5684 return ValidateVertexAttribIndex(context, index);
5685}
5686
5687bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5688{
5689 if (width < 0 || height < 0)
5690 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005691 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005692 return false;
5693 }
5694
5695 return true;
5696}
5697
5698bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5699{
5700 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5701}
5702
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005703bool ValidateDrawElements(ValidationContext *context,
5704 GLenum mode,
5705 GLsizei count,
5706 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005707 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005708{
5709 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5710}
5711
Jamie Madillbe849e42017-05-02 15:49:00 -04005712bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5713 GLenum target,
5714 GLenum attachment,
5715 GLenum pname,
5716 GLint *params)
5717{
5718 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5719 nullptr);
5720}
5721
5722bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5723{
5724 return ValidateGetProgramivBase(context, program, pname, nullptr);
5725}
5726
5727bool ValidateCopyTexImage2D(ValidationContext *context,
5728 GLenum target,
5729 GLint level,
5730 GLenum internalformat,
5731 GLint x,
5732 GLint y,
5733 GLsizei width,
5734 GLsizei height,
5735 GLint border)
5736{
5737 if (context->getClientMajorVersion() < 3)
5738 {
5739 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5740 0, x, y, width, height, border);
5741 }
5742
5743 ASSERT(context->getClientMajorVersion() == 3);
5744 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5745 0, x, y, width, height, border);
5746}
5747
5748bool ValidateCopyTexSubImage2D(Context *context,
5749 GLenum target,
5750 GLint level,
5751 GLint xoffset,
5752 GLint yoffset,
5753 GLint x,
5754 GLint y,
5755 GLsizei width,
5756 GLsizei height)
5757{
5758 if (context->getClientMajorVersion() < 3)
5759 {
5760 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5761 yoffset, x, y, width, height, 0);
5762 }
5763
5764 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5765 yoffset, 0, x, y, width, height, 0);
5766}
5767
5768bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5769{
5770 return ValidateGenOrDelete(context, n);
5771}
5772
5773bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5774{
5775 return ValidateGenOrDelete(context, n);
5776}
5777
5778bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5779{
5780 return ValidateGenOrDelete(context, n);
5781}
5782
5783bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5784{
5785 return ValidateGenOrDelete(context, n);
5786}
5787
5788bool ValidateDisable(Context *context, GLenum cap)
5789{
5790 if (!ValidCap(context, cap, false))
5791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005792 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 return false;
5794 }
5795
5796 return true;
5797}
5798
5799bool ValidateEnable(Context *context, GLenum cap)
5800{
5801 if (!ValidCap(context, cap, false))
5802 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806
5807 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5808 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5809 {
5810 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005811 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005812
5813 // We also output an error message to the debugger window if tracing is active, so that
5814 // developers can see the error message.
5815 ERR() << errorMessage;
5816 return false;
5817 }
5818
5819 return true;
5820}
5821
5822bool ValidateFramebufferRenderbuffer(Context *context,
5823 GLenum target,
5824 GLenum attachment,
5825 GLenum renderbuffertarget,
5826 GLuint renderbuffer)
5827{
Brandon Jones6cad5662017-06-14 13:25:13 -07005828 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005830 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5831 return false;
5832 }
5833
5834 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5835 {
5836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005837 return false;
5838 }
5839
5840 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5841 renderbuffertarget, renderbuffer);
5842}
5843
5844bool ValidateFramebufferTexture2D(Context *context,
5845 GLenum target,
5846 GLenum attachment,
5847 GLenum textarget,
5848 GLuint texture,
5849 GLint level)
5850{
5851 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5852 // extension
5853 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5854 level != 0)
5855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005856 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005857 return false;
5858 }
5859
5860 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5861 {
5862 return false;
5863 }
5864
5865 if (texture != 0)
5866 {
5867 gl::Texture *tex = context->getTexture(texture);
5868 ASSERT(tex);
5869
5870 const gl::Caps &caps = context->getCaps();
5871
5872 switch (textarget)
5873 {
5874 case GL_TEXTURE_2D:
5875 {
5876 if (level > gl::log2(caps.max2DTextureSize))
5877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005878 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005879 return false;
5880 }
5881 if (tex->getTarget() != GL_TEXTURE_2D)
5882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005883 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005884 return false;
5885 }
5886 }
5887 break;
5888
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005889 case GL_TEXTURE_RECTANGLE_ANGLE:
5890 {
5891 if (level != 0)
5892 {
5893 context->handleError(InvalidValue());
5894 return false;
5895 }
5896 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5897 {
5898 context->handleError(InvalidOperation()
5899 << "Textarget must match the texture target type.");
5900 return false;
5901 }
5902 }
5903 break;
5904
Jamie Madillbe849e42017-05-02 15:49:00 -04005905 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5907 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5908 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5909 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5910 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5911 {
5912 if (level > gl::log2(caps.maxCubeMapTextureSize))
5913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005914 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005915 return false;
5916 }
5917 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005919 context->handleError(InvalidOperation()
5920 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005921 return false;
5922 }
5923 }
5924 break;
5925
5926 case GL_TEXTURE_2D_MULTISAMPLE:
5927 {
5928 if (context->getClientVersion() < ES_3_1)
5929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005930 context->handleError(InvalidOperation()
5931 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 return false;
5933 }
5934
5935 if (level != 0)
5936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005937 context->handleError(InvalidValue()
5938 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 return false;
5940 }
5941 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005943 context->handleError(InvalidOperation()
5944 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005945 return false;
5946 }
5947 }
5948 break;
5949
5950 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 return false;
5953 }
5954
5955 const Format &format = tex->getFormat(textarget, level);
5956 if (format.info->compressed)
5957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005958 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005959 return false;
5960 }
5961 }
5962
5963 return true;
5964}
5965
5966bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5967{
5968 return ValidateGenOrDelete(context, n);
5969}
5970
5971bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5972{
5973 return ValidateGenOrDelete(context, n);
5974}
5975
5976bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5977{
5978 return ValidateGenOrDelete(context, n);
5979}
5980
5981bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5982{
5983 return ValidateGenOrDelete(context, n);
5984}
5985
5986bool ValidateGenerateMipmap(Context *context, GLenum target)
5987{
5988 if (!ValidTextureTarget(context, target))
5989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005990 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 return false;
5992 }
5993
5994 Texture *texture = context->getTargetTexture(target);
5995
5996 if (texture == nullptr)
5997 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005999 return false;
6000 }
6001
6002 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6003
6004 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6005 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6006 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006008 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006009 return false;
6010 }
6011
6012 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
6013 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
6014 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
6015
Brandon Jones6cad5662017-06-14 13:25:13 -07006016 if (format.info->compressed)
6017 {
6018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6019 return false;
6020 }
6021
Jamie Madillbe849e42017-05-02 15:49:00 -04006022 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
Brandon Jones6cad5662017-06-14 13:25:13 -07006023 // unsized formats or that are color renderable and filterable. Since we do not track if
Jamie Madillbe849e42017-05-02 15:49:00 -04006024 // the texture was created with sized or unsized format (only sized formats are stored),
6025 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
6026 // be able to) because they aren't color renderable. Simply do a special case for LUMA
6027 // textures since they're the only texture format that can be created with unsized formats
6028 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
6029 // was the last version to use add them.
6030 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
Brandon Jones6cad5662017-06-14 13:25:13 -07006031 (!formatCaps.renderable && !format.info->isLUMA()))
Jamie Madillbe849e42017-05-02 15:49:00 -04006032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006033 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006034 return false;
6035 }
6036
Geoff Lang65ac5b92017-05-01 13:16:30 -04006037 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
6038 bool supportsSRGBMipmapGeneration =
6039 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
6040 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006042 context->handleError(InvalidOperation()
6043 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006044 return false;
6045 }
6046
6047 // Non-power of 2 ES2 check
6048 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6049 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6050 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6051 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006052 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6053 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006055 return false;
6056 }
6057
6058 // Cube completeness check
6059 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006062 return false;
6063 }
6064
6065 return true;
6066}
6067
6068bool ValidateGetBufferParameteriv(ValidationContext *context,
6069 GLenum target,
6070 GLenum pname,
6071 GLint *params)
6072{
6073 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6074}
6075
6076bool ValidateGetRenderbufferParameteriv(Context *context,
6077 GLenum target,
6078 GLenum pname,
6079 GLint *params)
6080{
6081 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6082}
6083
6084bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6085{
6086 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6087}
6088
6089bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6090{
6091 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6092}
6093
6094bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6095{
6096 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6097}
6098
6099bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6100{
6101 return ValidateGetUniformBase(context, program, location);
6102}
6103
6104bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6105{
6106 return ValidateGetUniformBase(context, program, location);
6107}
6108
6109bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6110{
6111 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6112}
6113
6114bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6115{
6116 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6117}
6118
6119bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6120{
6121 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6122}
6123
6124bool ValidateIsEnabled(Context *context, GLenum cap)
6125{
6126 if (!ValidCap(context, cap, true))
6127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006129 return false;
6130 }
6131
6132 return true;
6133}
6134
6135bool ValidateLinkProgram(Context *context, GLuint program)
6136{
6137 if (context->hasActiveTransformFeedback(program))
6138 {
6139 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006140 context->handleError(InvalidOperation() << "Cannot link program while program is "
6141 "associated with an active transform "
6142 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006143 return false;
6144 }
6145
6146 Program *programObject = GetValidProgram(context, program);
6147 if (!programObject)
6148 {
6149 return false;
6150 }
6151
6152 return true;
6153}
6154
Jamie Madill4928b7c2017-06-20 12:57:39 -04006155bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006156 GLint x,
6157 GLint y,
6158 GLsizei width,
6159 GLsizei height,
6160 GLenum format,
6161 GLenum type,
6162 void *pixels)
6163{
6164 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6165 nullptr, pixels);
6166}
6167
6168bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6169{
6170 return ValidateTexParameterBase(context, target, pname, -1, &param);
6171}
6172
6173bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6174{
6175 return ValidateTexParameterBase(context, target, pname, -1, params);
6176}
6177
6178bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6179{
6180 return ValidateTexParameterBase(context, target, pname, -1, &param);
6181}
6182
6183bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6184{
6185 return ValidateTexParameterBase(context, target, pname, -1, params);
6186}
6187
6188bool ValidateUseProgram(Context *context, GLuint program)
6189{
6190 if (program != 0)
6191 {
6192 Program *programObject = context->getProgram(program);
6193 if (!programObject)
6194 {
6195 // ES 3.1.0 section 7.3 page 72
6196 if (context->getShader(program))
6197 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006198 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006199 return false;
6200 }
6201 else
6202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006203 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006204 return false;
6205 }
6206 }
6207 if (!programObject->isLinked())
6208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006209 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006210 return false;
6211 }
6212 }
6213 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6214 {
6215 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006216 context
6217 ->handleError(InvalidOperation()
6218 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006219 return false;
6220 }
6221
6222 return true;
6223}
6224
Jamie Madillc29968b2016-01-20 11:17:23 -05006225} // namespace gl