blob: af7d7ecb42725c0e56447bb2e4af57d245dde421 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070017#include "libANGLE/ErrorStrings.h"
Jamie Madillef300b12016-10-07 15:12:09 -040018#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/Texture.h"
Jamie Madillef300b12016-10-07 15:12:09 -040023#include "libANGLE/Uniform.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/VertexArray.h"
Jamie Madillef300b12016-10-07 15:12:09 -040025#include "libANGLE/formatutils.h"
26#include "libANGLE/validationES.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29namespace gl
30{
31
Jamie Madillc29968b2016-01-20 11:17:23 -050032namespace
33{
34
35bool IsPartialBlit(gl::Context *context,
36 const FramebufferAttachment *readBuffer,
37 const FramebufferAttachment *writeBuffer,
38 GLint srcX0,
39 GLint srcY0,
40 GLint srcX1,
41 GLint srcY1,
42 GLint dstX0,
43 GLint dstY0,
44 GLint dstX1,
45 GLint dstY1)
46{
47 const Extents &writeSize = writeBuffer->getSize();
48 const Extents &readSize = readBuffer->getSize();
49
50 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
51 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
52 {
53 return true;
54 }
55
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050057 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070058 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050059 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
60 scissor.height < writeSize.height;
61 }
62
63 return false;
64}
65
Sami Väisänend59ca052016-06-21 16:10:00 +030066template <typename T>
67bool ValidatePathInstances(gl::Context *context,
68 GLsizei numPaths,
69 const void *paths,
70 GLuint pathBase)
71{
72 const auto *array = static_cast<const T *>(paths);
73
74 for (GLsizei i = 0; i < numPaths; ++i)
75 {
76 const GLuint pathName = array[i] + pathBase;
77 if (context->hasPath(pathName) && !context->hasPathData(pathName))
78 {
Brandon Jonesafa75152017-07-21 13:11:29 -070079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänend59ca052016-06-21 16:10:00 +030080 return false;
81 }
82 }
83 return true;
84}
85
86bool ValidateInstancedPathParameters(gl::Context *context,
87 GLsizei numPaths,
88 GLenum pathNameType,
89 const void *paths,
90 GLuint pathBase,
91 GLenum transformType,
92 const GLfloat *transformValues)
93{
94 if (!context->getExtensions().pathRendering)
95 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050096 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänend59ca052016-06-21 16:10:00 +030097 return false;
98 }
99
100 if (paths == nullptr)
101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500102 context->handleError(InvalidValue() << "No path name array.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300103 return false;
104 }
105
106 if (numPaths < 0)
107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500108 context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500160 context->handleError(InvalidEnum() << "Invalid path name type.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500188 context->handleError(InvalidEnum() << "Invalid transformation.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidValue() << "No transform array given.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang4f0e0032017-05-01 16:04:35 -0400209bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700210{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400211 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400212 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700213 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400214 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700215 case GL_ALPHA:
216 case GL_LUMINANCE:
217 case GL_LUMINANCE_ALPHA:
218 case GL_RGB:
219 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400220 case GL_RGB8:
221 case GL_RGBA8:
222 case GL_BGRA_EXT:
223 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700224 return true;
225
Geoff Lang4f0e0032017-05-01 16:04:35 -0400226 default:
227 return false;
228 }
229}
Geoff Lang97073d12016-04-20 10:42:34 -0700230
Geoff Lang4f0e0032017-05-01 16:04:35 -0400231bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
232{
233 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
234}
235
Geoff Lang4f0e0032017-05-01 16:04:35 -0400236bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
237{
238 // Table 1.0 from the CHROMIUM_copy_texture spec
239 switch (internalFormat)
240 {
241 case GL_RGB:
242 case GL_RGBA:
243 case GL_RGB8:
244 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700245 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400246 case GL_BGRA8_EXT:
247 case GL_SRGB_EXT:
248 case GL_SRGB_ALPHA_EXT:
249 case GL_R8:
250 case GL_R8UI:
251 case GL_RG8:
252 case GL_RG8UI:
253 case GL_SRGB8:
254 case GL_RGB565:
255 case GL_RGB8UI:
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400256 case GL_RGB10_A2:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400257 case GL_SRGB8_ALPHA8:
258 case GL_RGB5_A1:
259 case GL_RGBA4:
260 case GL_RGBA8UI:
261 case GL_RGB9_E5:
262 case GL_R16F:
263 case GL_R32F:
264 case GL_RG16F:
265 case GL_RG32F:
266 case GL_RGB16F:
267 case GL_RGB32F:
268 case GL_RGBA16F:
269 case GL_RGBA32F:
270 case GL_R11F_G11F_B10F:
Brandon Jones340b7b82017-06-26 13:02:31 -0700271 case GL_LUMINANCE:
272 case GL_LUMINANCE_ALPHA:
273 case GL_ALPHA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400274 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700275
276 default:
277 return false;
278 }
279}
280
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400281bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
282{
283 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
284}
285
Geoff Lang97073d12016-04-20 10:42:34 -0700286bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
287{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400288 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700289 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400290 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700291 }
292
Geoff Langc0094ec2017-08-16 14:16:24 -0400293 if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
294 {
295 context->handleError(InvalidOperation()
296 << "Invalid combination of type and internalFormat.");
297 return false;
298 }
299
Geoff Lang4f0e0032017-05-01 16:04:35 -0400300 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
301 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700302 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400303 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700304 }
305
306 return true;
307}
308
Geoff Lang4f0e0032017-05-01 16:04:35 -0400309bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700310{
311 switch (target)
312 {
313 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400314 return textureType == GL_TEXTURE_2D;
315
316 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
317 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
318 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
319 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
320 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
321 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
322 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700323
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400324 case GL_TEXTURE_RECTANGLE_ANGLE:
325 return textureType == GL_TEXTURE_RECTANGLE_ANGLE &&
326 context->getExtensions().textureRectangle;
Geoff Lang97073d12016-04-20 10:42:34 -0700327
328 default:
329 return false;
330 }
331}
332
333bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
334{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400335 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700336 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400337 case GL_TEXTURE_2D:
338 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400339 case GL_TEXTURE_RECTANGLE_ANGLE:
340 return context->getExtensions().textureRectangle;
Geoff Lang4f0e0032017-05-01 16:04:35 -0400341
342 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
343 // supported
344
345 default:
346 return false;
347 }
348}
349
350bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
351{
Geoff Lang3847f942017-07-12 11:17:28 -0400352 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400353 {
354 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700355 }
356
Geoff Lang4f0e0032017-05-01 16:04:35 -0400357 if (level > 0 && context->getClientVersion() < ES_3_0)
358 {
359 return false;
360 }
Geoff Lang97073d12016-04-20 10:42:34 -0700361
Geoff Lang4f0e0032017-05-01 16:04:35 -0400362 return true;
363}
364
365bool IsValidCopyTextureDestinationLevel(Context *context,
366 GLenum target,
367 GLint level,
368 GLsizei width,
369 GLsizei height)
370{
Geoff Lang3847f942017-07-12 11:17:28 -0400371 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400372 {
373 return false;
374 }
375
Geoff Lang4f0e0032017-05-01 16:04:35 -0400376 const Caps &caps = context->getCaps();
377 if (target == GL_TEXTURE_2D)
378 {
379 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
380 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
381 {
382 return false;
383 }
384 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400385 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
386 {
387 ASSERT(level == 0);
388 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
389 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
390 {
391 return false;
392 }
393 }
Geoff Lang4f0e0032017-05-01 16:04:35 -0400394 else if (IsCubeMapTextureTarget(target))
395 {
396 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
397 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
398 {
399 return false;
400 }
401 }
402
403 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700404}
405
Jamie Madillc1d770e2017-04-13 17:31:24 -0400406bool IsValidStencilFunc(GLenum func)
407{
408 switch (func)
409 {
410 case GL_NEVER:
411 case GL_ALWAYS:
412 case GL_LESS:
413 case GL_LEQUAL:
414 case GL_EQUAL:
415 case GL_GEQUAL:
416 case GL_GREATER:
417 case GL_NOTEQUAL:
418 return true;
419
420 default:
421 return false;
422 }
423}
424
425bool IsValidStencilFace(GLenum face)
426{
427 switch (face)
428 {
429 case GL_FRONT:
430 case GL_BACK:
431 case GL_FRONT_AND_BACK:
432 return true;
433
434 default:
435 return false;
436 }
437}
438
439bool IsValidStencilOp(GLenum op)
440{
441 switch (op)
442 {
443 case GL_ZERO:
444 case GL_KEEP:
445 case GL_REPLACE:
446 case GL_INCR:
447 case GL_DECR:
448 case GL_INVERT:
449 case GL_INCR_WRAP:
450 case GL_DECR_WRAP:
451 return true;
452
453 default:
454 return false;
455 }
456}
457
Jamie Madillbe849e42017-05-02 15:49:00 -0400458bool ValidateES2CopyTexImageParameters(ValidationContext *context,
459 GLenum target,
460 GLint level,
461 GLenum internalformat,
462 bool isSubImage,
463 GLint xoffset,
464 GLint yoffset,
465 GLint x,
466 GLint y,
467 GLsizei width,
468 GLsizei height,
469 GLint border)
470{
471 if (!ValidTexture2DDestinationTarget(context, target))
472 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400474 return false;
475 }
476
477 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500479 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400480 return false;
481 }
482
483 Format textureFormat = Format::Invalid();
484 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
485 xoffset, yoffset, 0, x, y, width, height, border,
486 &textureFormat))
487 {
488 return false;
489 }
490
491 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
492 GLenum colorbufferFormat =
493 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
494 const auto &formatInfo = *textureFormat.info;
495
496 // [OpenGL ES 2.0.24] table 3.9
497 if (isSubImage)
498 {
499 switch (formatInfo.format)
500 {
501 case GL_ALPHA:
502 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400503 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
504 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400505 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700506 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400507 return false;
508 }
509 break;
510 case GL_LUMINANCE:
511 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
512 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
513 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400514 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
515 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400516 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400518 return false;
519 }
520 break;
521 case GL_RED_EXT:
522 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
523 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
524 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
525 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
526 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400527 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
528 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400529 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400531 return false;
532 }
533 break;
534 case GL_RG_EXT:
535 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
536 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
537 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
538 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400539 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
540 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400541 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700542 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400543 return false;
544 }
545 break;
546 case GL_RGB:
547 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
548 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
549 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400550 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
551 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400552 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700553 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400554 return false;
555 }
556 break;
557 case GL_LUMINANCE_ALPHA:
558 case GL_RGBA:
559 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400560 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
561 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700563 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400564 return false;
565 }
566 break;
567 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
568 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
569 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
570 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
571 case GL_ETC1_RGB8_OES:
572 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
573 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
574 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
575 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
576 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400578 return false;
579 case GL_DEPTH_COMPONENT:
580 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400582 return false;
583 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700584 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400585 return false;
586 }
587
588 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
589 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400591 return false;
592 }
593 }
594 else
595 {
596 switch (internalformat)
597 {
598 case GL_ALPHA:
599 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
600 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
601 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
602 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700603 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400604 return false;
605 }
606 break;
607 case GL_LUMINANCE:
608 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
609 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
610 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
611 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
612 colorbufferFormat != GL_BGR5_A1_ANGLEX)
613 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700614 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400615 return false;
616 }
617 break;
618 case GL_RED_EXT:
619 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
620 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
621 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
622 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
623 colorbufferFormat != GL_BGR5_A1_ANGLEX)
624 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 return false;
627 }
628 break;
629 case GL_RG_EXT:
630 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
631 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
632 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
633 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
634 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400636 return false;
637 }
638 break;
639 case GL_RGB:
640 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
641 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
642 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
643 colorbufferFormat != GL_BGR5_A1_ANGLEX)
644 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700645 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400646 return false;
647 }
648 break;
649 case GL_LUMINANCE_ALPHA:
650 case GL_RGBA:
651 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
652 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
653 colorbufferFormat != GL_BGR5_A1_ANGLEX)
654 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400656 return false;
657 }
658 break;
659 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
660 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
661 if (context->getExtensions().textureCompressionDXT1)
662 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 return false;
665 }
666 else
667 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400669 return false;
670 }
671 break;
672 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
673 if (context->getExtensions().textureCompressionDXT3)
674 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400676 return false;
677 }
678 else
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400681 return false;
682 }
683 break;
684 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
685 if (context->getExtensions().textureCompressionDXT5)
686 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400688 return false;
689 }
690 else
691 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700692 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400693 return false;
694 }
695 break;
696 case GL_ETC1_RGB8_OES:
697 if (context->getExtensions().compressedETC1RGB8Texture)
698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400700 return false;
701 }
702 else
703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500704 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400705 return false;
706 }
707 break;
708 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
709 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
710 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
711 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
712 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
713 if (context->getExtensions().lossyETCDecode)
714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500715 context->handleError(InvalidOperation()
716 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400717 return false;
718 }
719 else
720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500721 context->handleError(InvalidEnum()
722 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 break;
726 case GL_DEPTH_COMPONENT:
727 case GL_DEPTH_COMPONENT16:
728 case GL_DEPTH_COMPONENT32_OES:
729 case GL_DEPTH_STENCIL_OES:
730 case GL_DEPTH24_STENCIL8_OES:
731 if (context->getExtensions().depthTextures)
732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500733 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400734 return false;
735 }
736 else
737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500738 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400739 return false;
740 }
741 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500742 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400743 return false;
744 }
745 }
746
747 // If width or height is zero, it is a no-op. Return false without setting an error.
748 return (width > 0 && height > 0);
749}
750
751bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
752{
753 switch (cap)
754 {
755 // EXT_multisample_compatibility
756 case GL_MULTISAMPLE_EXT:
757 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
758 return context->getExtensions().multisampleCompatibility;
759
760 case GL_CULL_FACE:
761 case GL_POLYGON_OFFSET_FILL:
762 case GL_SAMPLE_ALPHA_TO_COVERAGE:
763 case GL_SAMPLE_COVERAGE:
764 case GL_SCISSOR_TEST:
765 case GL_STENCIL_TEST:
766 case GL_DEPTH_TEST:
767 case GL_BLEND:
768 case GL_DITHER:
769 return true;
770
771 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
772 case GL_RASTERIZER_DISCARD:
773 return (context->getClientMajorVersion() >= 3);
774
775 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
776 case GL_DEBUG_OUTPUT:
777 return context->getExtensions().debug;
778
779 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
780 return queryOnly && context->getExtensions().bindGeneratesResource;
781
782 case GL_CLIENT_ARRAYS_ANGLE:
783 return queryOnly && context->getExtensions().clientArrays;
784
785 case GL_FRAMEBUFFER_SRGB_EXT:
786 return context->getExtensions().sRGBWriteControl;
787
788 case GL_SAMPLE_MASK:
789 return context->getClientVersion() >= Version(3, 1);
790
Geoff Langb433e872017-10-05 14:01:47 -0400791 case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
Jamie Madillbe849e42017-05-02 15:49:00 -0400792 return queryOnly && context->getExtensions().robustResourceInitialization;
793
794 default:
795 return false;
796 }
797}
798
Geoff Langfc32e8b2017-05-31 14:16:59 -0400799// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
800// 3.1.
Geoff Langcab92ee2017-07-19 17:32:07 -0400801bool IsValidESSLCharacter(unsigned char c)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400802{
803 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langcab92ee2017-07-19 17:32:07 -0400804 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
805 c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400806 {
807 return true;
808 }
809
810 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
811 if (c >= 9 && c <= 13)
812 {
813 return true;
814 }
815
816 return false;
817}
818
Geoff Langcab92ee2017-07-19 17:32:07 -0400819bool IsValidESSLString(const char *str, size_t len)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400820{
Geoff Langa71a98e2017-06-19 15:15:00 -0400821 for (size_t i = 0; i < len; i++)
822 {
Geoff Langcab92ee2017-07-19 17:32:07 -0400823 if (!IsValidESSLCharacter(str[i]))
Geoff Langa71a98e2017-06-19 15:15:00 -0400824 {
825 return false;
826 }
827 }
828
829 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400830}
831
Geoff Langcab92ee2017-07-19 17:32:07 -0400832bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
833{
834 enum class ParseState
835 {
836 // Have not seen an ASCII non-whitespace character yet on
837 // this line. Possible that we might see a preprocessor
838 // directive.
839 BEGINING_OF_LINE,
840
841 // Have seen at least one ASCII non-whitespace character
842 // on this line.
843 MIDDLE_OF_LINE,
844
845 // Handling a preprocessor directive. Passes through all
846 // characters up to the end of the line. Disables comment
847 // processing.
848 IN_PREPROCESSOR_DIRECTIVE,
849
850 // Handling a single-line comment. The comment text is
851 // replaced with a single space.
852 IN_SINGLE_LINE_COMMENT,
853
854 // Handling a multi-line comment. Newlines are passed
855 // through to preserve line numbers.
856 IN_MULTI_LINE_COMMENT
857 };
858
859 ParseState state = ParseState::BEGINING_OF_LINE;
860 size_t pos = 0;
861
862 while (pos < len)
863 {
864 char c = str[pos];
865 char next = pos + 1 < len ? str[pos + 1] : 0;
866
867 // Check for newlines
868 if (c == '\n' || c == '\r')
869 {
870 if (state != ParseState::IN_MULTI_LINE_COMMENT)
871 {
872 state = ParseState::BEGINING_OF_LINE;
873 }
874
875 pos++;
876 continue;
877 }
878
879 switch (state)
880 {
881 case ParseState::BEGINING_OF_LINE:
882 if (c == ' ')
883 {
884 // Maintain the BEGINING_OF_LINE state until a non-space is seen
885 pos++;
886 }
887 else if (c == '#')
888 {
889 state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
890 pos++;
891 }
892 else
893 {
894 // Don't advance, re-process this character with the MIDDLE_OF_LINE state
895 state = ParseState::MIDDLE_OF_LINE;
896 }
897 break;
898
899 case ParseState::MIDDLE_OF_LINE:
900 if (c == '/' && next == '/')
901 {
902 state = ParseState::IN_SINGLE_LINE_COMMENT;
903 pos++;
904 }
905 else if (c == '/' && next == '*')
906 {
907 state = ParseState::IN_MULTI_LINE_COMMENT;
908 pos++;
909 }
910 else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
911 {
912 // Skip line continuation characters
913 }
914 else if (!IsValidESSLCharacter(c))
915 {
916 return false;
917 }
918 pos++;
919 break;
920
921 case ParseState::IN_PREPROCESSOR_DIRECTIVE:
Bryan Bernhart (Intel Americas Inc)335d8bf2017-10-23 15:41:43 -0700922 // Line-continuation characters may not be permitted.
923 // Otherwise, just pass it through. Do not parse comments in this state.
924 if (!lineContinuationAllowed && c == '\\')
925 {
926 return false;
927 }
Geoff Langcab92ee2017-07-19 17:32:07 -0400928 pos++;
929 break;
930
931 case ParseState::IN_SINGLE_LINE_COMMENT:
932 // Line-continuation characters are processed before comment processing.
933 // Advance string if a new line character is immediately behind
934 // line-continuation character.
935 if (c == '\\' && (next == '\n' || next == '\r'))
936 {
937 pos++;
938 }
939 pos++;
940 break;
941
942 case ParseState::IN_MULTI_LINE_COMMENT:
943 if (c == '*' && next == '/')
944 {
945 state = ParseState::MIDDLE_OF_LINE;
946 pos++;
947 }
948 pos++;
949 break;
950 }
951 }
952
953 return true;
954}
955
Brandon Jonesed5b46f2017-07-21 08:39:17 -0700956bool ValidateWebGLNamePrefix(ValidationContext *context, const GLchar *name)
957{
958 ASSERT(context->isWebGL());
959
960 // WebGL 1.0 [Section 6.16] GLSL Constructs
961 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
962 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
963 {
964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), WebglBindAttribLocationReservedPrefix);
965 return false;
966 }
967
968 return true;
969}
970
971bool ValidateWebGLNameLength(ValidationContext *context, size_t length)
972{
973 ASSERT(context->isWebGL());
974
975 if (context->isWebGL1() && length > 256)
976 {
977 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
978 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
979 // locations.
980 ANGLE_VALIDATION_ERR(context, InvalidValue(), WebglNameLengthLimitExceeded);
981
982 return false;
983 }
984 else if (length > 1024)
985 {
986 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
987 // uniform and attribute locations.
988 ANGLE_VALIDATION_ERR(context, InvalidValue(), Webgl2NameLengthLimitExceeded);
989 return false;
990 }
991
992 return true;
993}
994
Jamie Madillc29968b2016-01-20 11:17:23 -0500995} // anonymous namespace
996
Geoff Langff5b2d52016-09-07 11:32:23 -0400997bool ValidateES2TexImageParameters(Context *context,
998 GLenum target,
999 GLint level,
1000 GLenum internalformat,
1001 bool isCompressed,
1002 bool isSubImage,
1003 GLint xoffset,
1004 GLint yoffset,
1005 GLsizei width,
1006 GLsizei height,
1007 GLint border,
1008 GLenum format,
1009 GLenum type,
1010 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001011 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012{
Jamie Madill6f38f822014-06-06 17:12:20 -04001013 if (!ValidTexture2DDestinationTarget(context, target))
1014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001017 }
1018
Austin Kinross08528e12015-10-07 16:24:40 -07001019 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001021 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 }
1024
Brandon Jones6cad5662017-06-14 13:25:13 -07001025 if (!ValidMipLevel(context, target, level))
1026 {
1027 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
1028 return false;
1029 }
1030
1031 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 std::numeric_limits<GLsizei>::max() - yoffset < height)
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
1037
Geoff Lang6e898aa2017-06-02 11:17:26 -04001038 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1039 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1040 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1041 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1042 // case.
1043 bool nonEqualFormatsAllowed =
1044 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
1045 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
1046
1047 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001049 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001051 }
1052
Geoff Langaae65a42014-05-26 12:43:44 -04001053 const gl::Caps &caps = context->getCaps();
1054
Geoff Langa9be0dc2014-12-17 12:34:40 -05001055 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001057 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
1058 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001060 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001061 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001063 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001064 else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
1065 {
1066 ASSERT(level == 0);
1067 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1068 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
1069 {
1070 context->handleError(InvalidValue());
1071 return false;
1072 }
1073 if (isCompressed)
1074 {
1075 context->handleError(InvalidEnum()
1076 << "Rectangle texture cannot have a compressed format.");
1077 return false;
1078 }
1079 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001080 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001081 {
1082 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001084 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001085 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087
Geoff Langa9be0dc2014-12-17 12:34:40 -05001088 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1089 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001091 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001092 return false;
1093 }
1094 }
1095 else
1096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001097 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001098 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 }
1100
He Yunchaoced53ae2016-11-29 15:00:51 +08001101 gl::Texture *texture =
1102 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 if (!texture)
1104 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
Geoff Langa9be0dc2014-12-17 12:34:40 -05001109 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 {
Geoff Langca271392017-04-05 12:30:00 -04001111 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1112 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001114 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001115 return false;
1116 }
1117
Geoff Langa9be0dc2014-12-17 12:34:40 -05001118 if (format != GL_NONE)
1119 {
Geoff Langca271392017-04-05 12:30:00 -04001120 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1121 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001124 return false;
1125 }
1126 }
1127
1128 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1129 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001131 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001132 return false;
1133 }
1134 }
1135 else
1136 {
Geoff Lang69cce582015-09-17 13:20:36 -04001137 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001139 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001140 return false;
1141 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 }
1143
1144 // Verify zero border
1145 if (border != 0)
1146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001147 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 if (isCompressed)
1152 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001153 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001154 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1155 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 switch (actualInternalFormat)
1157 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001158 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1160 if (!context->getExtensions().textureCompressionDXT1)
1161 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001162 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 return false;
1164 }
1165 break;
1166 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1167 if (!context->getExtensions().textureCompressionDXT1)
1168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001169 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001170 return false;
1171 }
1172 break;
1173 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1174 if (!context->getExtensions().textureCompressionDXT5)
1175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001177 return false;
1178 }
1179 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001180 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1181 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1182 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1183 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1184 if (!context->getExtensions().textureCompressionS3TCsRGB)
1185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001187 return false;
1188 }
1189 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 case GL_ETC1_RGB8_OES:
1191 if (!context->getExtensions().compressedETC1RGB8Texture)
1192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 return false;
1195 }
1196 break;
1197 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001198 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1199 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1200 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1201 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 if (!context->getExtensions().lossyETCDecode)
1203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001204 context->handleError(InvalidEnum()
1205 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
1207 }
1208 break;
1209 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001211 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001212 }
Geoff Lang966c9402017-04-18 12:38:27 -04001213
1214 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001215 {
Geoff Lang966c9402017-04-18 12:38:27 -04001216 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1217 height, texture->getWidth(target, level),
1218 texture->getHeight(target, level)))
1219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001221 return false;
1222 }
1223
1224 if (format != actualInternalFormat)
1225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001227 return false;
1228 }
1229 }
1230 else
1231 {
1232 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001235 return false;
1236 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237 }
1238 }
1239 else
1240 {
1241 // validate <type> by itself (used as secondary key below)
1242 switch (type)
1243 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001244 case GL_UNSIGNED_BYTE:
1245 case GL_UNSIGNED_SHORT_5_6_5:
1246 case GL_UNSIGNED_SHORT_4_4_4_4:
1247 case GL_UNSIGNED_SHORT_5_5_5_1:
1248 case GL_UNSIGNED_SHORT:
1249 case GL_UNSIGNED_INT:
1250 case GL_UNSIGNED_INT_24_8_OES:
1251 case GL_HALF_FLOAT_OES:
1252 case GL_FLOAT:
1253 break;
1254 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
1259 // validate <format> + <type> combinations
1260 // - invalid <format> -> sets INVALID_ENUM
1261 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1262 switch (format)
1263 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001264 case GL_ALPHA:
1265 case GL_LUMINANCE:
1266 case GL_LUMINANCE_ALPHA:
1267 switch (type)
1268 {
1269 case GL_UNSIGNED_BYTE:
1270 case GL_FLOAT:
1271 case GL_HALF_FLOAT_OES:
1272 break;
1273 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001274 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001275 return false;
1276 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001278 case GL_RED:
1279 case GL_RG:
1280 if (!context->getExtensions().textureRG)
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001283 return false;
1284 }
1285 switch (type)
1286 {
1287 case GL_UNSIGNED_BYTE:
1288 case GL_FLOAT:
1289 case GL_HALF_FLOAT_OES:
1290 break;
1291 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001293 return false;
1294 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001296 case GL_RGB:
1297 switch (type)
1298 {
1299 case GL_UNSIGNED_BYTE:
1300 case GL_UNSIGNED_SHORT_5_6_5:
1301 case GL_FLOAT:
1302 case GL_HALF_FLOAT_OES:
1303 break;
1304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001306 return false;
1307 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001309 case GL_RGBA:
1310 switch (type)
1311 {
1312 case GL_UNSIGNED_BYTE:
1313 case GL_UNSIGNED_SHORT_4_4_4_4:
1314 case GL_UNSIGNED_SHORT_5_5_5_1:
1315 case GL_FLOAT:
1316 case GL_HALF_FLOAT_OES:
1317 break;
1318 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001320 return false;
1321 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 case GL_BGRA_EXT:
1324 switch (type)
1325 {
1326 case GL_UNSIGNED_BYTE:
1327 break;
1328 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001330 return false;
1331 }
1332 break;
1333 case GL_SRGB_EXT:
1334 case GL_SRGB_ALPHA_EXT:
1335 if (!context->getExtensions().sRGB)
1336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001338 return false;
1339 }
1340 switch (type)
1341 {
1342 case GL_UNSIGNED_BYTE:
1343 break;
1344 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001345 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001346 return false;
1347 }
1348 break;
1349 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1350 // handled below
1351 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1352 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1353 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1354 break;
1355 case GL_DEPTH_COMPONENT:
1356 switch (type)
1357 {
1358 case GL_UNSIGNED_SHORT:
1359 case GL_UNSIGNED_INT:
1360 break;
1361 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001362 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001363 return false;
1364 }
1365 break;
1366 case GL_DEPTH_STENCIL_OES:
1367 switch (type)
1368 {
1369 case GL_UNSIGNED_INT_24_8_OES:
1370 break;
1371 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001372 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001373 return false;
1374 }
1375 break;
1376 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
1380
1381 switch (format)
1382 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001383 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1384 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1385 if (context->getExtensions().textureCompressionDXT1)
1386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001388 return false;
1389 }
1390 else
1391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001392 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001393 return false;
1394 }
1395 break;
1396 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1397 if (context->getExtensions().textureCompressionDXT3)
1398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 return false;
1401 }
1402 else
1403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001404 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001405 return false;
1406 }
1407 break;
1408 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1409 if (context->getExtensions().textureCompressionDXT5)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 return false;
1413 }
1414 else
1415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 return false;
1418 }
1419 break;
1420 case GL_ETC1_RGB8_OES:
1421 if (context->getExtensions().compressedETC1RGB8Texture)
1422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001424 return false;
1425 }
1426 else
1427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 return false;
1430 }
1431 break;
1432 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001433 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1434 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1435 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1436 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001437 if (context->getExtensions().lossyETCDecode)
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(InvalidOperation()
1440 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001441 return false;
1442 }
1443 else
1444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidEnum()
1446 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001447 return false;
1448 }
1449 break;
1450 case GL_DEPTH_COMPONENT:
1451 case GL_DEPTH_STENCIL_OES:
1452 if (!context->getExtensions().depthTextures)
1453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001454 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001455 return false;
1456 }
1457 if (target != GL_TEXTURE_2D)
1458 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 return false;
1461 }
1462 // OES_depth_texture supports loading depth data and multiple levels,
1463 // but ANGLE_depth_texture does not
Brandon Jonesafa75152017-07-21 13:11:29 -07001464 if (pixels != nullptr)
He Yunchaoced53ae2016-11-29 15:00:51 +08001465 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
1467 return false;
1468 }
1469 if (level != 0)
1470 {
1471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 break;
1475 default:
1476 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 }
1478
Geoff Lang6e898aa2017-06-02 11:17:26 -04001479 if (!isSubImage)
1480 {
1481 switch (internalformat)
1482 {
1483 case GL_RGBA32F:
1484 if (!context->getExtensions().colorBufferFloatRGBA)
1485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001486 context->handleError(InvalidValue()
1487 << "Sized GL_RGBA32F internal format requires "
1488 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001489 return false;
1490 }
1491 if (type != GL_FLOAT)
1492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001493 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001494 return false;
1495 }
1496 if (format != GL_RGBA)
1497 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001498 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001499 return false;
1500 }
1501 break;
1502
1503 case GL_RGB32F:
1504 if (!context->getExtensions().colorBufferFloatRGB)
1505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidValue()
1507 << "Sized GL_RGB32F internal format requires "
1508 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001509 return false;
1510 }
1511 if (type != GL_FLOAT)
1512 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001513 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001514 return false;
1515 }
1516 if (format != GL_RGB)
1517 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001519 return false;
1520 }
1521 break;
1522
1523 default:
1524 break;
1525 }
1526 }
1527
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 if (type == GL_FLOAT)
1529 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001530 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001532 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001533 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 }
1535 }
1536 else if (type == GL_HALF_FLOAT_OES)
1537 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001538 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001541 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 }
1543 }
1544 }
1545
Geoff Langdbcced82017-06-06 15:55:54 -04001546 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1547 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001548 imageSize))
1549 {
1550 return false;
1551 }
1552
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001553 return true;
1554}
1555
He Yunchaoced53ae2016-11-29 15:00:51 +08001556bool ValidateES2TexStorageParameters(Context *context,
1557 GLenum target,
1558 GLsizei levels,
1559 GLenum internalformat,
1560 GLsizei width,
1561 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001562{
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001563 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
1564 target != GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001566 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001567 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001568 }
1569
1570 if (width < 1 || height < 1 || levels < 1)
1571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001572 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001574 }
1575
1576 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001578 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001579 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001580 }
1581
1582 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001584 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001585 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586 }
1587
Geoff Langca271392017-04-05 12:30:00 -04001588 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001589 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001591 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001593 }
1594
Geoff Langaae65a42014-05-26 12:43:44 -04001595 const gl::Caps &caps = context->getCaps();
1596
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001597 switch (target)
1598 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 case GL_TEXTURE_2D:
1600 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1601 static_cast<GLuint>(height) > caps.max2DTextureSize)
1602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001603 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001604 return false;
1605 }
1606 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001607 case GL_TEXTURE_RECTANGLE_ANGLE:
1608 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1609 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1610 {
1611 context->handleError(InvalidValue());
1612 return false;
1613 }
1614 if (formatInfo.compressed)
1615 {
1616 context->handleError(InvalidEnum()
1617 << "Rectangle texture cannot have a compressed format.");
1618 return false;
1619 }
1620 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001621 case GL_TEXTURE_CUBE_MAP:
1622 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1623 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001626 return false;
1627 }
1628 break;
1629 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001630 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001631 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001632 }
1633
Geoff Langc0b9ef42014-07-02 10:02:37 -04001634 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001635 {
1636 if (!gl::isPow2(width) || !gl::isPow2(height))
1637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001639 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001640 }
1641 }
1642
1643 switch (internalformat)
1644 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001645 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1646 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1647 if (!context->getExtensions().textureCompressionDXT1)
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_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1654 if (!context->getExtensions().textureCompressionDXT3)
1655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001657 return false;
1658 }
1659 break;
1660 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1661 if (!context->getExtensions().textureCompressionDXT5)
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001664 return false;
1665 }
1666 break;
1667 case GL_ETC1_RGB8_OES:
1668 if (!context->getExtensions().compressedETC1RGB8Texture)
1669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001671 return false;
1672 }
1673 break;
1674 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001675 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1676 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1677 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1678 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001679 if (!context->getExtensions().lossyETCDecode)
1680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001681 context->handleError(InvalidEnum()
1682 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001683 return false;
1684 }
1685 break;
1686 case GL_RGBA32F_EXT:
1687 case GL_RGB32F_EXT:
1688 case GL_ALPHA32F_EXT:
1689 case GL_LUMINANCE32F_EXT:
1690 case GL_LUMINANCE_ALPHA32F_EXT:
1691 if (!context->getExtensions().textureFloat)
1692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001693 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001694 return false;
1695 }
1696 break;
1697 case GL_RGBA16F_EXT:
1698 case GL_RGB16F_EXT:
1699 case GL_ALPHA16F_EXT:
1700 case GL_LUMINANCE16F_EXT:
1701 case GL_LUMINANCE_ALPHA16F_EXT:
1702 if (!context->getExtensions().textureHalfFloat)
1703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001704 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001705 return false;
1706 }
1707 break;
1708 case GL_R8_EXT:
1709 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001710 if (!context->getExtensions().textureRG)
1711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001712 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001713 return false;
1714 }
1715 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001716 case GL_R16F_EXT:
1717 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001718 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001720 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001721 return false;
1722 }
1723 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001724 case GL_R32F_EXT:
1725 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001726 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001729 return false;
1730 }
1731 break;
1732 case GL_DEPTH_COMPONENT16:
1733 case GL_DEPTH_COMPONENT32_OES:
1734 case GL_DEPTH24_STENCIL8_OES:
1735 if (!context->getExtensions().depthTextures)
1736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001737 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001738 return false;
1739 }
1740 if (target != GL_TEXTURE_2D)
1741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001742 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001743 return false;
1744 }
1745 // ANGLE_depth_texture only supports 1-level textures
1746 if (levels != 1)
1747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001749 return false;
1750 }
1751 break;
1752 default:
1753 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 }
1755
Geoff Lang691e58c2014-12-19 17:03:25 -05001756 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 if (!texture || texture->id() == 0)
1758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001759 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001760 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001761 }
1762
Geoff Lang69cce582015-09-17 13:20:36 -04001763 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001767 }
1768
1769 return true;
1770}
1771
He Yunchaoced53ae2016-11-29 15:00:51 +08001772bool ValidateDiscardFramebufferEXT(Context *context,
1773 GLenum target,
1774 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001775 const GLenum *attachments)
1776{
Jamie Madillc29968b2016-01-20 11:17:23 -05001777 if (!context->getExtensions().discardFramebuffer)
1778 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001780 return false;
1781 }
1782
Austin Kinross08332632015-05-05 13:35:47 -07001783 bool defaultFramebuffer = false;
1784
1785 switch (target)
1786 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001787 case GL_FRAMEBUFFER:
1788 defaultFramebuffer =
1789 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1790 break;
1791 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001792 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001793 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001794 }
1795
He Yunchaoced53ae2016-11-29 15:00:51 +08001796 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1797 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001798}
1799
Austin Kinrossbc781f32015-10-26 09:27:38 -07001800bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1801{
1802 if (!context->getExtensions().vertexArrayObject)
1803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001805 return false;
1806 }
1807
1808 return ValidateBindVertexArrayBase(context, array);
1809}
1810
Jamie Madilld7576732017-08-26 18:49:50 -04001811bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001812{
1813 if (!context->getExtensions().vertexArrayObject)
1814 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001815 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001816 return false;
1817 }
1818
Olli Etuaho41997e72016-03-10 13:38:39 +02001819 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001820}
1821
Jamie Madilld7576732017-08-26 18:49:50 -04001822bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001823{
1824 if (!context->getExtensions().vertexArrayObject)
1825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001827 return false;
1828 }
1829
Olli Etuaho41997e72016-03-10 13:38:39 +02001830 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001831}
1832
Jamie Madilld7576732017-08-26 18:49:50 -04001833bool ValidateIsVertexArrayOES(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001834{
1835 if (!context->getExtensions().vertexArrayObject)
1836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001838 return false;
1839 }
1840
1841 return true;
1842}
Geoff Langc5629752015-12-07 16:29:04 -05001843
1844bool ValidateProgramBinaryOES(Context *context,
1845 GLuint program,
1846 GLenum binaryFormat,
1847 const void *binary,
1848 GLint length)
1849{
1850 if (!context->getExtensions().getProgramBinary)
1851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001853 return false;
1854 }
1855
1856 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1857}
1858
1859bool ValidateGetProgramBinaryOES(Context *context,
1860 GLuint program,
1861 GLsizei bufSize,
1862 GLsizei *length,
1863 GLenum *binaryFormat,
1864 void *binary)
1865{
1866 if (!context->getExtensions().getProgramBinary)
1867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001869 return false;
1870 }
1871
1872 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1873}
Geoff Lange102fee2015-12-10 11:23:30 -05001874
Geoff Lang70d0f492015-12-10 17:45:46 -05001875static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1876{
1877 switch (source)
1878 {
1879 case GL_DEBUG_SOURCE_API:
1880 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1881 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1882 case GL_DEBUG_SOURCE_OTHER:
1883 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1884 return !mustBeThirdPartyOrApplication;
1885
1886 case GL_DEBUG_SOURCE_THIRD_PARTY:
1887 case GL_DEBUG_SOURCE_APPLICATION:
1888 return true;
1889
1890 default:
1891 return false;
1892 }
1893}
1894
1895static bool ValidDebugType(GLenum type)
1896{
1897 switch (type)
1898 {
1899 case GL_DEBUG_TYPE_ERROR:
1900 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1901 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1902 case GL_DEBUG_TYPE_PERFORMANCE:
1903 case GL_DEBUG_TYPE_PORTABILITY:
1904 case GL_DEBUG_TYPE_OTHER:
1905 case GL_DEBUG_TYPE_MARKER:
1906 case GL_DEBUG_TYPE_PUSH_GROUP:
1907 case GL_DEBUG_TYPE_POP_GROUP:
1908 return true;
1909
1910 default:
1911 return false;
1912 }
1913}
1914
1915static bool ValidDebugSeverity(GLenum severity)
1916{
1917 switch (severity)
1918 {
1919 case GL_DEBUG_SEVERITY_HIGH:
1920 case GL_DEBUG_SEVERITY_MEDIUM:
1921 case GL_DEBUG_SEVERITY_LOW:
1922 case GL_DEBUG_SEVERITY_NOTIFICATION:
1923 return true;
1924
1925 default:
1926 return false;
1927 }
1928}
1929
Geoff Lange102fee2015-12-10 11:23:30 -05001930bool ValidateDebugMessageControlKHR(Context *context,
1931 GLenum source,
1932 GLenum type,
1933 GLenum severity,
1934 GLsizei count,
1935 const GLuint *ids,
1936 GLboolean enabled)
1937{
1938 if (!context->getExtensions().debug)
1939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001941 return false;
1942 }
1943
Geoff Lang70d0f492015-12-10 17:45:46 -05001944 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1945 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001946 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05001947 return false;
1948 }
1949
1950 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1951 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05001953 return false;
1954 }
1955
1956 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1957 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
Geoff Lang70d0f492015-12-10 17:45:46 -05001959 return false;
1960 }
1961
1962 if (count > 0)
1963 {
1964 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001966 context->handleError(
1967 InvalidOperation()
1968 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001969 return false;
1970 }
1971
1972 if (severity != GL_DONT_CARE)
1973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 InvalidOperation()
1976 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001977 return false;
1978 }
1979 }
1980
Geoff Lange102fee2015-12-10 11:23:30 -05001981 return true;
1982}
1983
1984bool ValidateDebugMessageInsertKHR(Context *context,
1985 GLenum source,
1986 GLenum type,
1987 GLuint id,
1988 GLenum severity,
1989 GLsizei length,
1990 const GLchar *buf)
1991{
1992 if (!context->getExtensions().debug)
1993 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001995 return false;
1996 }
1997
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001998 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001999 {
2000 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2001 // not generate an error.
2002 return false;
2003 }
2004
2005 if (!ValidDebugSeverity(severity))
2006 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002008 return false;
2009 }
2010
2011 if (!ValidDebugType(type))
2012 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002013 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
Geoff Lang70d0f492015-12-10 17:45:46 -05002014 return false;
2015 }
2016
2017 if (!ValidDebugSource(source, true))
2018 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002019 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002020 return false;
2021 }
2022
2023 size_t messageLength = (length < 0) ? strlen(buf) : length;
2024 if (messageLength > context->getExtensions().maxDebugMessageLength)
2025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002026 context->handleError(InvalidValue()
2027 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002028 return false;
2029 }
2030
Geoff Lange102fee2015-12-10 11:23:30 -05002031 return true;
2032}
2033
2034bool ValidateDebugMessageCallbackKHR(Context *context,
2035 GLDEBUGPROCKHR callback,
2036 const void *userParam)
2037{
2038 if (!context->getExtensions().debug)
2039 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002041 return false;
2042 }
2043
Geoff Lange102fee2015-12-10 11:23:30 -05002044 return true;
2045}
2046
2047bool ValidateGetDebugMessageLogKHR(Context *context,
2048 GLuint count,
2049 GLsizei bufSize,
2050 GLenum *sources,
2051 GLenum *types,
2052 GLuint *ids,
2053 GLenum *severities,
2054 GLsizei *lengths,
2055 GLchar *messageLog)
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
Geoff Lang70d0f492015-12-10 17:45:46 -05002063 if (bufSize < 0 && messageLog != nullptr)
2064 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002065 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002066 return false;
2067 }
2068
Geoff Lange102fee2015-12-10 11:23:30 -05002069 return true;
2070}
2071
2072bool ValidatePushDebugGroupKHR(Context *context,
2073 GLenum source,
2074 GLuint id,
2075 GLsizei length,
2076 const GLchar *message)
2077{
2078 if (!context->getExtensions().debug)
2079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002081 return false;
2082 }
2083
Geoff Lang70d0f492015-12-10 17:45:46 -05002084 if (!ValidDebugSource(source, true))
2085 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
Geoff Lang70d0f492015-12-10 17:45:46 -05002087 return false;
2088 }
2089
2090 size_t messageLength = (length < 0) ? strlen(message) : length;
2091 if (messageLength > context->getExtensions().maxDebugMessageLength)
2092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002093 context->handleError(InvalidValue()
2094 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002095 return false;
2096 }
2097
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002098 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002099 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002101 context
2102 ->handleError(StackOverflow()
2103 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002104 return false;
2105 }
2106
Geoff Lange102fee2015-12-10 11:23:30 -05002107 return true;
2108}
2109
2110bool ValidatePopDebugGroupKHR(Context *context)
2111{
2112 if (!context->getExtensions().debug)
2113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002115 return false;
2116 }
2117
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002118 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002119 if (currentStackSize <= 1)
2120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002121 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002122 return false;
2123 }
2124
2125 return true;
2126}
2127
2128static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2129{
2130 switch (identifier)
2131 {
2132 case GL_BUFFER:
2133 if (context->getBuffer(name) == nullptr)
2134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002135 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002136 return false;
2137 }
2138 return true;
2139
2140 case GL_SHADER:
2141 if (context->getShader(name) == nullptr)
2142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002144 return false;
2145 }
2146 return true;
2147
2148 case GL_PROGRAM:
2149 if (context->getProgram(name) == nullptr)
2150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002151 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002152 return false;
2153 }
2154 return true;
2155
2156 case GL_VERTEX_ARRAY:
2157 if (context->getVertexArray(name) == nullptr)
2158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002159 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002160 return false;
2161 }
2162 return true;
2163
2164 case GL_QUERY:
2165 if (context->getQuery(name) == nullptr)
2166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002167 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002168 return false;
2169 }
2170 return true;
2171
2172 case GL_TRANSFORM_FEEDBACK:
2173 if (context->getTransformFeedback(name) == nullptr)
2174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002175 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002176 return false;
2177 }
2178 return true;
2179
2180 case GL_SAMPLER:
2181 if (context->getSampler(name) == nullptr)
2182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002183 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002184 return false;
2185 }
2186 return true;
2187
2188 case GL_TEXTURE:
2189 if (context->getTexture(name) == nullptr)
2190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002191 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002192 return false;
2193 }
2194 return true;
2195
2196 case GL_RENDERBUFFER:
2197 if (context->getRenderbuffer(name) == nullptr)
2198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002199 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002200 return false;
2201 }
2202 return true;
2203
2204 case GL_FRAMEBUFFER:
2205 if (context->getFramebuffer(name) == nullptr)
2206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002208 return false;
2209 }
2210 return true;
2211
2212 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002213 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002214 return false;
2215 }
Geoff Lange102fee2015-12-10 11:23:30 -05002216}
2217
Martin Radev9d901792016-07-15 15:58:58 +03002218static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2219{
2220 size_t labelLength = 0;
2221
2222 if (length < 0)
2223 {
2224 if (label != nullptr)
2225 {
2226 labelLength = strlen(label);
2227 }
2228 }
2229 else
2230 {
2231 labelLength = static_cast<size_t>(length);
2232 }
2233
2234 if (labelLength > context->getExtensions().maxLabelLength)
2235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002237 return false;
2238 }
2239
2240 return true;
2241}
2242
Geoff Lange102fee2015-12-10 11:23:30 -05002243bool ValidateObjectLabelKHR(Context *context,
2244 GLenum identifier,
2245 GLuint name,
2246 GLsizei length,
2247 const GLchar *label)
2248{
2249 if (!context->getExtensions().debug)
2250 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002252 return false;
2253 }
2254
Geoff Lang70d0f492015-12-10 17:45:46 -05002255 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2256 {
2257 return false;
2258 }
2259
Martin Radev9d901792016-07-15 15:58:58 +03002260 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002261 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002262 return false;
2263 }
2264
Geoff Lange102fee2015-12-10 11:23:30 -05002265 return true;
2266}
2267
2268bool ValidateGetObjectLabelKHR(Context *context,
2269 GLenum identifier,
2270 GLuint name,
2271 GLsizei bufSize,
2272 GLsizei *length,
2273 GLchar *label)
2274{
2275 if (!context->getExtensions().debug)
2276 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002277 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002278 return false;
2279 }
2280
Geoff Lang70d0f492015-12-10 17:45:46 -05002281 if (bufSize < 0)
2282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002283 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002284 return false;
2285 }
2286
2287 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2288 {
2289 return false;
2290 }
2291
Martin Radev9d901792016-07-15 15:58:58 +03002292 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002293}
2294
2295static bool ValidateObjectPtrName(Context *context, const void *ptr)
2296{
Jamie Madill70b5bb02017-08-28 13:32:37 -04002297 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
Geoff Lang70d0f492015-12-10 17:45:46 -05002298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002299 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002300 return false;
2301 }
2302
Geoff Lange102fee2015-12-10 11:23:30 -05002303 return true;
2304}
2305
2306bool ValidateObjectPtrLabelKHR(Context *context,
2307 const void *ptr,
2308 GLsizei length,
2309 const GLchar *label)
2310{
2311 if (!context->getExtensions().debug)
2312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002314 return false;
2315 }
2316
Geoff Lang70d0f492015-12-10 17:45:46 -05002317 if (!ValidateObjectPtrName(context, ptr))
2318 {
2319 return false;
2320 }
2321
Martin Radev9d901792016-07-15 15:58:58 +03002322 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002323 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002324 return false;
2325 }
2326
Geoff Lange102fee2015-12-10 11:23:30 -05002327 return true;
2328}
2329
2330bool ValidateGetObjectPtrLabelKHR(Context *context,
2331 const void *ptr,
2332 GLsizei bufSize,
2333 GLsizei *length,
2334 GLchar *label)
2335{
2336 if (!context->getExtensions().debug)
2337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002339 return false;
2340 }
2341
Geoff Lang70d0f492015-12-10 17:45:46 -05002342 if (bufSize < 0)
2343 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002344 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002345 return false;
2346 }
2347
2348 if (!ValidateObjectPtrName(context, ptr))
2349 {
2350 return false;
2351 }
2352
Martin Radev9d901792016-07-15 15:58:58 +03002353 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002354}
2355
2356bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2357{
2358 if (!context->getExtensions().debug)
2359 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002360 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002361 return false;
2362 }
2363
Geoff Lang70d0f492015-12-10 17:45:46 -05002364 // TODO: represent this in Context::getQueryParameterInfo.
2365 switch (pname)
2366 {
2367 case GL_DEBUG_CALLBACK_FUNCTION:
2368 case GL_DEBUG_CALLBACK_USER_PARAM:
2369 break;
2370
2371 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002373 return false;
2374 }
2375
Geoff Lange102fee2015-12-10 11:23:30 -05002376 return true;
2377}
Jamie Madillc29968b2016-01-20 11:17:23 -05002378
2379bool ValidateBlitFramebufferANGLE(Context *context,
2380 GLint srcX0,
2381 GLint srcY0,
2382 GLint srcX1,
2383 GLint srcY1,
2384 GLint dstX0,
2385 GLint dstY0,
2386 GLint dstX1,
2387 GLint dstY1,
2388 GLbitfield mask,
2389 GLenum filter)
2390{
2391 if (!context->getExtensions().framebufferBlit)
2392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002393 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002394 return false;
2395 }
2396
2397 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2398 {
2399 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002400 context->handleError(InvalidOperation() << "Scaling and flipping in "
2401 "BlitFramebufferANGLE not supported by this "
2402 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002403 return false;
2404 }
2405
2406 if (filter == GL_LINEAR)
2407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002408 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002409 return false;
2410 }
2411
Jamie Madill51f40ec2016-06-15 14:06:00 -04002412 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2413 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002414
2415 if (mask & GL_COLOR_BUFFER_BIT)
2416 {
2417 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2418 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2419
2420 if (readColorAttachment && drawColorAttachment)
2421 {
2422 if (!(readColorAttachment->type() == GL_TEXTURE &&
2423 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2424 readColorAttachment->type() != GL_RENDERBUFFER &&
2425 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002427 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002428 return false;
2429 }
2430
Geoff Langa15472a2015-08-11 11:48:03 -04002431 for (size_t drawbufferIdx = 0;
2432 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002433 {
Geoff Langa15472a2015-08-11 11:48:03 -04002434 const FramebufferAttachment *attachment =
2435 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2436 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002437 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002438 if (!(attachment->type() == GL_TEXTURE &&
2439 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2440 attachment->type() != GL_RENDERBUFFER &&
2441 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002443 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002444 return false;
2445 }
2446
2447 // Return an error if the destination formats do not match
Kenneth Russell69382852017-07-21 16:38:44 -04002448 if (!Format::EquivalentForBlit(attachment->getFormat(),
2449 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002451 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002452 return false;
2453 }
2454 }
2455 }
2456
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002457 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002458 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2459 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002461 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002462 return false;
2463 }
2464 }
2465 }
2466
2467 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2468 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2469 for (size_t i = 0; i < 2; i++)
2470 {
2471 if (mask & masks[i])
2472 {
2473 const FramebufferAttachment *readBuffer =
2474 readFramebuffer->getAttachment(attachments[i]);
2475 const FramebufferAttachment *drawBuffer =
2476 drawFramebuffer->getAttachment(attachments[i]);
2477
2478 if (readBuffer && drawBuffer)
2479 {
2480 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2481 dstX0, dstY0, dstX1, dstY1))
2482 {
2483 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002484 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2485 "stencil blits are supported by "
2486 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002487 return false;
2488 }
2489
2490 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002492 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002493 return false;
2494 }
2495 }
2496 }
2497 }
2498
2499 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2500 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002501}
Jamie Madillc29968b2016-01-20 11:17:23 -05002502
2503bool ValidateClear(ValidationContext *context, GLbitfield mask)
2504{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002505 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002506 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002509 return false;
2510 }
2511
2512 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002514 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002515 return false;
2516 }
2517
Geoff Lang76e65652017-03-27 14:58:02 -04002518 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2519 {
2520 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2521 GL_SIGNED_NORMALIZED};
2522
Corentin Wallez59c41592017-07-11 13:19:54 -04002523 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002524 drawBufferIdx++)
2525 {
2526 if (!ValidateWebGLFramebufferAttachmentClearType(
2527 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2528 {
2529 return false;
2530 }
2531 }
2532 }
2533
Jamie Madillc29968b2016-01-20 11:17:23 -05002534 return true;
2535}
2536
2537bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2538{
2539 if (!context->getExtensions().drawBuffers)
2540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002541 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002542 return false;
2543 }
2544
2545 return ValidateDrawBuffersBase(context, n, bufs);
2546}
2547
Jamie Madill73a84962016-02-12 09:27:23 -05002548bool ValidateTexImage2D(Context *context,
2549 GLenum target,
2550 GLint level,
2551 GLint internalformat,
2552 GLsizei width,
2553 GLsizei height,
2554 GLint border,
2555 GLenum format,
2556 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002557 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002558{
Martin Radev1be913c2016-07-11 17:59:16 +03002559 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002560 {
2561 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002562 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002563 }
2564
Martin Radev1be913c2016-07-11 17:59:16 +03002565 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002566 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002567 0, 0, width, height, 1, border, format, type, -1,
2568 pixels);
2569}
2570
2571bool ValidateTexImage2DRobust(Context *context,
2572 GLenum target,
2573 GLint level,
2574 GLint internalformat,
2575 GLsizei width,
2576 GLsizei height,
2577 GLint border,
2578 GLenum format,
2579 GLenum type,
2580 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002581 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002582{
2583 if (!ValidateRobustEntryPoint(context, bufSize))
2584 {
2585 return false;
2586 }
2587
2588 if (context->getClientMajorVersion() < 3)
2589 {
2590 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2591 0, 0, width, height, border, format, type, bufSize,
2592 pixels);
2593 }
2594
2595 ASSERT(context->getClientMajorVersion() >= 3);
2596 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2597 0, 0, width, height, 1, border, format, type, bufSize,
2598 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002599}
2600
2601bool ValidateTexSubImage2D(Context *context,
2602 GLenum target,
2603 GLint level,
2604 GLint xoffset,
2605 GLint yoffset,
2606 GLsizei width,
2607 GLsizei height,
2608 GLenum format,
2609 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002610 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002611{
2612
Martin Radev1be913c2016-07-11 17:59:16 +03002613 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002614 {
2615 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002616 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002617 }
2618
Martin Radev1be913c2016-07-11 17:59:16 +03002619 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002620 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002621 yoffset, 0, width, height, 1, 0, format, type, -1,
2622 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002623}
2624
Geoff Langc52f6f12016-10-14 10:18:00 -04002625bool ValidateTexSubImage2DRobustANGLE(Context *context,
2626 GLenum target,
2627 GLint level,
2628 GLint xoffset,
2629 GLint yoffset,
2630 GLsizei width,
2631 GLsizei height,
2632 GLenum format,
2633 GLenum type,
2634 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002635 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002636{
2637 if (!ValidateRobustEntryPoint(context, bufSize))
2638 {
2639 return false;
2640 }
2641
2642 if (context->getClientMajorVersion() < 3)
2643 {
2644 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2645 yoffset, width, height, 0, format, type, bufSize,
2646 pixels);
2647 }
2648
2649 ASSERT(context->getClientMajorVersion() >= 3);
2650 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2651 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2652 pixels);
2653}
2654
Jamie Madill73a84962016-02-12 09:27:23 -05002655bool ValidateCompressedTexImage2D(Context *context,
2656 GLenum target,
2657 GLint level,
2658 GLenum internalformat,
2659 GLsizei width,
2660 GLsizei height,
2661 GLint border,
2662 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002663 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002664{
Martin Radev1be913c2016-07-11 17:59:16 +03002665 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002666 {
2667 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002668 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002669 {
2670 return false;
2671 }
2672 }
2673 else
2674 {
Martin Radev1be913c2016-07-11 17:59:16 +03002675 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002676 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002677 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002678 data))
2679 {
2680 return false;
2681 }
2682 }
2683
Geoff Langca271392017-04-05 12:30:00 -04002684 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002685 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002686 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002687 if (blockSizeOrErr.isError())
2688 {
2689 context->handleError(blockSizeOrErr.getError());
2690 return false;
2691 }
2692
2693 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002694 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002695 ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
Jamie Madill73a84962016-02-12 09:27:23 -05002696 return false;
2697 }
2698
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002699 if (target == GL_TEXTURE_RECTANGLE_ANGLE)
2700 {
2701 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
2702 return false;
2703 }
2704
Jamie Madill73a84962016-02-12 09:27:23 -05002705 return true;
2706}
2707
Corentin Wallezb2931602017-04-11 15:58:57 -04002708bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2709 GLenum target,
2710 GLint level,
2711 GLenum internalformat,
2712 GLsizei width,
2713 GLsizei height,
2714 GLint border,
2715 GLsizei imageSize,
2716 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002717 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002718{
2719 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2720 {
2721 return false;
2722 }
2723
2724 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2725 border, imageSize, data);
2726}
2727bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2728 GLenum target,
2729 GLint level,
2730 GLint xoffset,
2731 GLint yoffset,
2732 GLsizei width,
2733 GLsizei height,
2734 GLenum format,
2735 GLsizei imageSize,
2736 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002737 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002738{
2739 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2740 {
2741 return false;
2742 }
2743
2744 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2745 format, imageSize, data);
2746}
2747
Jamie Madill73a84962016-02-12 09:27:23 -05002748bool ValidateCompressedTexSubImage2D(Context *context,
2749 GLenum target,
2750 GLint level,
2751 GLint xoffset,
2752 GLint yoffset,
2753 GLsizei width,
2754 GLsizei height,
2755 GLenum format,
2756 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002757 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002758{
Martin Radev1be913c2016-07-11 17:59:16 +03002759 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002760 {
2761 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002762 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002763 {
2764 return false;
2765 }
2766 }
2767 else
2768 {
Martin Radev1be913c2016-07-11 17:59:16 +03002769 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002770 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002771 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002772 data))
2773 {
2774 return false;
2775 }
2776 }
2777
Geoff Langca271392017-04-05 12:30:00 -04002778 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002779 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002780 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002781 if (blockSizeOrErr.isError())
2782 {
2783 context->handleError(blockSizeOrErr.getError());
2784 return false;
2785 }
2786
2787 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002789 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002790 return false;
2791 }
2792
2793 return true;
2794}
2795
Olli Etuaho4f667482016-03-30 15:56:35 +03002796bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2797{
Geoff Lang496c02d2016-10-20 11:38:11 -07002798 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002799}
2800
2801bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2802{
2803 if (!context->getExtensions().mapBuffer)
2804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002805 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002806 return false;
2807 }
2808
2809 if (!ValidBufferTarget(context, target))
2810 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002811 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002812 return false;
2813 }
2814
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002815 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002816
2817 if (buffer == nullptr)
2818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002819 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002820 return false;
2821 }
2822
2823 if (access != GL_WRITE_ONLY_OES)
2824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002825 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002826 return false;
2827 }
2828
2829 if (buffer->isMapped())
2830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002831 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002832 return false;
2833 }
2834
Geoff Lang79f71042017-08-14 16:43:43 -04002835 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002836}
2837
2838bool ValidateUnmapBufferOES(Context *context, GLenum target)
2839{
2840 if (!context->getExtensions().mapBuffer)
2841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002842 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002843 return false;
2844 }
2845
2846 return ValidateUnmapBufferBase(context, target);
2847}
2848
2849bool ValidateMapBufferRangeEXT(Context *context,
2850 GLenum target,
2851 GLintptr offset,
2852 GLsizeiptr length,
2853 GLbitfield access)
2854{
2855 if (!context->getExtensions().mapBufferRange)
2856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002857 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002858 return false;
2859 }
2860
2861 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2862}
2863
Geoff Lang79f71042017-08-14 16:43:43 -04002864bool ValidateMapBufferBase(Context *context, GLenum target)
2865{
2866 Buffer *buffer = context->getGLState().getTargetBuffer(target);
2867 ASSERT(buffer != nullptr);
2868
2869 // Check if this buffer is currently being used as a transform feedback output buffer
2870 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2871 if (transformFeedback != nullptr && transformFeedback->isActive())
2872 {
2873 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2874 {
2875 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
2876 if (transformFeedbackBuffer.get() == buffer)
2877 {
2878 context->handleError(InvalidOperation()
2879 << "Buffer is currently bound for transform feedback.");
2880 return false;
2881 }
2882 }
2883 }
2884
2885 return true;
2886}
2887
Olli Etuaho4f667482016-03-30 15:56:35 +03002888bool ValidateFlushMappedBufferRangeEXT(Context *context,
2889 GLenum target,
2890 GLintptr offset,
2891 GLsizeiptr length)
2892{
2893 if (!context->getExtensions().mapBufferRange)
2894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002895 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002896 return false;
2897 }
2898
2899 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2900}
2901
Ian Ewell54f87462016-03-10 13:47:21 -05002902bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2903{
2904 Texture *textureObject = context->getTexture(texture);
2905 if (textureObject && textureObject->getTarget() != target && texture != 0)
2906 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
Ian Ewell54f87462016-03-10 13:47:21 -05002908 return false;
2909 }
2910
Geoff Langf41a7152016-09-19 15:11:17 -04002911 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2912 !context->isTextureGenerated(texture))
2913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002914 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002915 return false;
2916 }
2917
Ian Ewell54f87462016-03-10 13:47:21 -05002918 switch (target)
2919 {
2920 case GL_TEXTURE_2D:
2921 case GL_TEXTURE_CUBE_MAP:
2922 break;
2923
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002924 case GL_TEXTURE_RECTANGLE_ANGLE:
2925 if (!context->getExtensions().textureRectangle)
2926 {
2927 context->handleError(InvalidEnum()
2928 << "Context does not support GL_ANGLE_texture_rectangle");
2929 return false;
2930 }
2931 break;
2932
Ian Ewell54f87462016-03-10 13:47:21 -05002933 case GL_TEXTURE_3D:
2934 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002935 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002936 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002937 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Ian Ewell54f87462016-03-10 13:47:21 -05002938 return false;
2939 }
2940 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002941
2942 case GL_TEXTURE_2D_MULTISAMPLE:
2943 if (context->getClientVersion() < Version(3, 1))
2944 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002945 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Lang3b573612016-10-31 14:08:10 -04002946 return false;
2947 }
Geoff Lang3b573612016-10-31 14:08:10 -04002948 break;
2949
Ian Ewell54f87462016-03-10 13:47:21 -05002950 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002951 if (!context->getExtensions().eglImageExternal &&
2952 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002954 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002955 return false;
2956 }
2957 break;
2958 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002959 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002960 return false;
2961 }
2962
2963 return true;
2964}
2965
Geoff Langd8605522016-04-13 10:19:12 -04002966bool ValidateBindUniformLocationCHROMIUM(Context *context,
2967 GLuint program,
2968 GLint location,
2969 const GLchar *name)
2970{
2971 if (!context->getExtensions().bindUniformLocation)
2972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002973 context->handleError(InvalidOperation()
2974 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002975 return false;
2976 }
2977
2978 Program *programObject = GetValidProgram(context, program);
2979 if (!programObject)
2980 {
2981 return false;
2982 }
2983
2984 if (location < 0)
2985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002986 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002987 return false;
2988 }
2989
2990 const Caps &caps = context->getCaps();
2991 if (static_cast<size_t>(location) >=
2992 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002994 context->handleError(InvalidValue() << "Location must be less than "
2995 "(MAX_VERTEX_UNIFORM_VECTORS + "
2996 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002997 return false;
2998 }
2999
Geoff Langfc32e8b2017-05-31 14:16:59 -04003000 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3001 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04003002 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04003003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003004 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04003005 return false;
3006 }
3007
Geoff Langd8605522016-04-13 10:19:12 -04003008 if (strncmp(name, "gl_", 3) == 0)
3009 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003010 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04003011 return false;
3012 }
3013
3014 return true;
3015}
3016
Jamie Madille2e406c2016-06-02 13:04:10 -04003017bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03003018{
3019 if (!context->getExtensions().framebufferMixedSamples)
3020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003021 context->handleError(InvalidOperation()
3022 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03003023 return false;
3024 }
3025 switch (components)
3026 {
3027 case GL_RGB:
3028 case GL_RGBA:
3029 case GL_ALPHA:
3030 case GL_NONE:
3031 break;
3032 default:
3033 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003034 InvalidEnum()
3035 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03003036 return false;
3037 }
3038
3039 return true;
3040}
3041
Sami Väisänene45e53b2016-05-25 10:36:04 +03003042// CHROMIUM_path_rendering
3043
3044bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
3045{
3046 if (!context->getExtensions().pathRendering)
3047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003048 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003049 return false;
3050 }
3051 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3052 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003054 return false;
3055 }
3056 if (matrix == nullptr)
3057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003058 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003059 return false;
3060 }
3061 return true;
3062}
3063
3064bool ValidateMatrixMode(Context *context, GLenum matrixMode)
3065{
3066 if (!context->getExtensions().pathRendering)
3067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003068 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003069 return false;
3070 }
3071 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
3072 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003074 return false;
3075 }
3076 return true;
3077}
3078
3079bool ValidateGenPaths(Context *context, GLsizei range)
3080{
3081 if (!context->getExtensions().pathRendering)
3082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003083 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003084 return false;
3085 }
3086
3087 // range = 0 is undefined in NV_path_rendering.
3088 // we add stricter semantic check here and require a non zero positive range.
3089 if (range <= 0)
3090 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003091 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003092 return false;
3093 }
3094
3095 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
3096 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003098 return false;
3099 }
3100
3101 return true;
3102}
3103
3104bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
3105{
3106 if (!context->getExtensions().pathRendering)
3107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003108 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003109 return false;
3110 }
3111
3112 // range = 0 is undefined in NV_path_rendering.
3113 // we add stricter semantic check here and require a non zero positive range.
3114 if (range <= 0)
3115 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003116 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003117 return false;
3118 }
3119
3120 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
3121 checkedRange += range;
3122
3123 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
3124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003126 return false;
3127 }
3128 return true;
3129}
3130
3131bool ValidatePathCommands(Context *context,
3132 GLuint path,
3133 GLsizei numCommands,
3134 const GLubyte *commands,
3135 GLsizei numCoords,
3136 GLenum coordType,
3137 const void *coords)
3138{
3139 if (!context->getExtensions().pathRendering)
3140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003141 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003142 return false;
3143 }
3144 if (!context->hasPath(path))
3145 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003147 return false;
3148 }
3149
3150 if (numCommands < 0)
3151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003152 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003153 return false;
3154 }
3155 else if (numCommands > 0)
3156 {
3157 if (!commands)
3158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003159 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003160 return false;
3161 }
3162 }
3163
3164 if (numCoords < 0)
3165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003166 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003167 return false;
3168 }
3169 else if (numCoords > 0)
3170 {
3171 if (!coords)
3172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003173 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003174 return false;
3175 }
3176 }
3177
3178 std::uint32_t coordTypeSize = 0;
3179 switch (coordType)
3180 {
3181 case GL_BYTE:
3182 coordTypeSize = sizeof(GLbyte);
3183 break;
3184
3185 case GL_UNSIGNED_BYTE:
3186 coordTypeSize = sizeof(GLubyte);
3187 break;
3188
3189 case GL_SHORT:
3190 coordTypeSize = sizeof(GLshort);
3191 break;
3192
3193 case GL_UNSIGNED_SHORT:
3194 coordTypeSize = sizeof(GLushort);
3195 break;
3196
3197 case GL_FLOAT:
3198 coordTypeSize = sizeof(GLfloat);
3199 break;
3200
3201 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003202 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003203 return false;
3204 }
3205
3206 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3207 checkedSize += (coordTypeSize * numCoords);
3208 if (!checkedSize.IsValid())
3209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003211 return false;
3212 }
3213
3214 // early return skips command data validation when it doesn't exist.
3215 if (!commands)
3216 return true;
3217
3218 GLsizei expectedNumCoords = 0;
3219 for (GLsizei i = 0; i < numCommands; ++i)
3220 {
3221 switch (commands[i])
3222 {
3223 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3224 break;
3225 case GL_MOVE_TO_CHROMIUM:
3226 case GL_LINE_TO_CHROMIUM:
3227 expectedNumCoords += 2;
3228 break;
3229 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3230 expectedNumCoords += 4;
3231 break;
3232 case GL_CUBIC_CURVE_TO_CHROMIUM:
3233 expectedNumCoords += 6;
3234 break;
3235 case GL_CONIC_CURVE_TO_CHROMIUM:
3236 expectedNumCoords += 5;
3237 break;
3238 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003239 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003240 return false;
3241 }
3242 }
3243 if (expectedNumCoords != numCoords)
3244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003246 return false;
3247 }
3248
3249 return true;
3250}
3251
3252bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3253{
3254 if (!context->getExtensions().pathRendering)
3255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003256 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003257 return false;
3258 }
3259 if (!context->hasPath(path))
3260 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003262 return false;
3263 }
3264
3265 switch (pname)
3266 {
3267 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3268 if (value < 0.0f)
3269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003270 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003271 return false;
3272 }
3273 break;
3274 case GL_PATH_END_CAPS_CHROMIUM:
3275 switch (static_cast<GLenum>(value))
3276 {
3277 case GL_FLAT_CHROMIUM:
3278 case GL_SQUARE_CHROMIUM:
3279 case GL_ROUND_CHROMIUM:
3280 break;
3281 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003282 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003283 return false;
3284 }
3285 break;
3286 case GL_PATH_JOIN_STYLE_CHROMIUM:
3287 switch (static_cast<GLenum>(value))
3288 {
3289 case GL_MITER_REVERT_CHROMIUM:
3290 case GL_BEVEL_CHROMIUM:
3291 case GL_ROUND_CHROMIUM:
3292 break;
3293 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003294 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003295 return false;
3296 }
3297 case GL_PATH_MITER_LIMIT_CHROMIUM:
3298 if (value < 0.0f)
3299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003300 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003301 return false;
3302 }
3303 break;
3304
3305 case GL_PATH_STROKE_BOUND_CHROMIUM:
3306 // no errors, only clamping.
3307 break;
3308
3309 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003310 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003311 return false;
3312 }
3313 return true;
3314}
3315
3316bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3317{
3318 if (!context->getExtensions().pathRendering)
3319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003320 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003321 return false;
3322 }
3323
3324 if (!context->hasPath(path))
3325 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003327 return false;
3328 }
3329 if (!value)
3330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003331 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003332 return false;
3333 }
3334
3335 switch (pname)
3336 {
3337 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3338 case GL_PATH_END_CAPS_CHROMIUM:
3339 case GL_PATH_JOIN_STYLE_CHROMIUM:
3340 case GL_PATH_MITER_LIMIT_CHROMIUM:
3341 case GL_PATH_STROKE_BOUND_CHROMIUM:
3342 break;
3343
3344 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003345 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003346 return false;
3347 }
3348
3349 return true;
3350}
3351
3352bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3353{
3354 if (!context->getExtensions().pathRendering)
3355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003356 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003357 return false;
3358 }
3359
3360 switch (func)
3361 {
3362 case GL_NEVER:
3363 case GL_ALWAYS:
3364 case GL_LESS:
3365 case GL_LEQUAL:
3366 case GL_EQUAL:
3367 case GL_GEQUAL:
3368 case GL_GREATER:
3369 case GL_NOTEQUAL:
3370 break;
3371 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003373 return false;
3374 }
3375
3376 return true;
3377}
3378
3379// Note that the spec specifies that for the path drawing commands
3380// if the path object is not an existing path object the command
3381// does nothing and no error is generated.
3382// However if the path object exists but has not been specified any
3383// commands then an error is generated.
3384
3385bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3386{
3387 if (!context->getExtensions().pathRendering)
3388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003389 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003390 return false;
3391 }
3392 if (context->hasPath(path) && !context->hasPathData(path))
3393 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003395 return false;
3396 }
3397
3398 switch (fillMode)
3399 {
3400 case GL_COUNT_UP_CHROMIUM:
3401 case GL_COUNT_DOWN_CHROMIUM:
3402 break;
3403 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003405 return false;
3406 }
3407
3408 if (!isPow2(mask + 1))
3409 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003410 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003411 return false;
3412 }
3413
3414 return true;
3415}
3416
3417bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3418{
3419 if (!context->getExtensions().pathRendering)
3420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003421 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003422 return false;
3423 }
3424 if (context->hasPath(path) && !context->hasPathData(path))
3425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003426 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003427 return false;
3428 }
3429
3430 return true;
3431}
3432
3433bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3434{
3435 if (!context->getExtensions().pathRendering)
3436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003438 return false;
3439 }
3440 if (context->hasPath(path) && !context->hasPathData(path))
3441 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003442 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003443 return false;
3444 }
3445
3446 switch (coverMode)
3447 {
3448 case GL_CONVEX_HULL_CHROMIUM:
3449 case GL_BOUNDING_BOX_CHROMIUM:
3450 break;
3451 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003453 return false;
3454 }
3455 return true;
3456}
3457
3458bool ValidateStencilThenCoverFillPath(Context *context,
3459 GLuint path,
3460 GLenum fillMode,
3461 GLuint mask,
3462 GLenum coverMode)
3463{
3464 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3465 ValidateCoverPath(context, path, coverMode);
3466}
3467
3468bool ValidateStencilThenCoverStrokePath(Context *context,
3469 GLuint path,
3470 GLint reference,
3471 GLuint mask,
3472 GLenum coverMode)
3473{
3474 return ValidateStencilStrokePath(context, path, reference, mask) &&
3475 ValidateCoverPath(context, path, coverMode);
3476}
3477
3478bool ValidateIsPath(Context *context)
3479{
3480 if (!context->getExtensions().pathRendering)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003483 return false;
3484 }
3485 return true;
3486}
3487
Sami Väisänend59ca052016-06-21 16:10:00 +03003488bool ValidateCoverFillPathInstanced(Context *context,
3489 GLsizei numPaths,
3490 GLenum pathNameType,
3491 const void *paths,
3492 GLuint pathBase,
3493 GLenum coverMode,
3494 GLenum transformType,
3495 const GLfloat *transformValues)
3496{
3497 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3498 transformType, transformValues))
3499 return false;
3500
3501 switch (coverMode)
3502 {
3503 case GL_CONVEX_HULL_CHROMIUM:
3504 case GL_BOUNDING_BOX_CHROMIUM:
3505 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3506 break;
3507 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003508 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003509 return false;
3510 }
3511
3512 return true;
3513}
3514
3515bool ValidateCoverStrokePathInstanced(Context *context,
3516 GLsizei numPaths,
3517 GLenum pathNameType,
3518 const void *paths,
3519 GLuint pathBase,
3520 GLenum coverMode,
3521 GLenum transformType,
3522 const GLfloat *transformValues)
3523{
3524 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3525 transformType, transformValues))
3526 return false;
3527
3528 switch (coverMode)
3529 {
3530 case GL_CONVEX_HULL_CHROMIUM:
3531 case GL_BOUNDING_BOX_CHROMIUM:
3532 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3533 break;
3534 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003536 return false;
3537 }
3538
3539 return true;
3540}
3541
3542bool ValidateStencilFillPathInstanced(Context *context,
3543 GLsizei numPaths,
3544 GLenum pathNameType,
3545 const void *paths,
3546 GLuint pathBase,
3547 GLenum fillMode,
3548 GLuint mask,
3549 GLenum transformType,
3550 const GLfloat *transformValues)
3551{
3552
3553 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3554 transformType, transformValues))
3555 return false;
3556
3557 switch (fillMode)
3558 {
3559 case GL_COUNT_UP_CHROMIUM:
3560 case GL_COUNT_DOWN_CHROMIUM:
3561 break;
3562 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003563 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003564 return false;
3565 }
3566 if (!isPow2(mask + 1))
3567 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003568 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003569 return false;
3570 }
3571 return true;
3572}
3573
3574bool ValidateStencilStrokePathInstanced(Context *context,
3575 GLsizei numPaths,
3576 GLenum pathNameType,
3577 const void *paths,
3578 GLuint pathBase,
3579 GLint reference,
3580 GLuint mask,
3581 GLenum transformType,
3582 const GLfloat *transformValues)
3583{
3584 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3585 transformType, transformValues))
3586 return false;
3587
3588 // no more validation here.
3589
3590 return true;
3591}
3592
3593bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3594 GLsizei numPaths,
3595 GLenum pathNameType,
3596 const void *paths,
3597 GLuint pathBase,
3598 GLenum fillMode,
3599 GLuint mask,
3600 GLenum coverMode,
3601 GLenum transformType,
3602 const GLfloat *transformValues)
3603{
3604 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3605 transformType, transformValues))
3606 return false;
3607
3608 switch (coverMode)
3609 {
3610 case GL_CONVEX_HULL_CHROMIUM:
3611 case GL_BOUNDING_BOX_CHROMIUM:
3612 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3613 break;
3614 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003616 return false;
3617 }
3618
3619 switch (fillMode)
3620 {
3621 case GL_COUNT_UP_CHROMIUM:
3622 case GL_COUNT_DOWN_CHROMIUM:
3623 break;
3624 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003626 return false;
3627 }
3628 if (!isPow2(mask + 1))
3629 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003630 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
Sami Väisänend59ca052016-06-21 16:10:00 +03003631 return false;
3632 }
3633
3634 return true;
3635}
3636
3637bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3638 GLsizei numPaths,
3639 GLenum pathNameType,
3640 const void *paths,
3641 GLuint pathBase,
3642 GLint reference,
3643 GLuint mask,
3644 GLenum coverMode,
3645 GLenum transformType,
3646 const GLfloat *transformValues)
3647{
3648 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3649 transformType, transformValues))
3650 return false;
3651
3652 switch (coverMode)
3653 {
3654 case GL_CONVEX_HULL_CHROMIUM:
3655 case GL_BOUNDING_BOX_CHROMIUM:
3656 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3657 break;
3658 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003659 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
Sami Väisänend59ca052016-06-21 16:10:00 +03003660 return false;
3661 }
3662
3663 return true;
3664}
3665
Sami Väisänen46eaa942016-06-29 10:26:37 +03003666bool ValidateBindFragmentInputLocation(Context *context,
3667 GLuint program,
3668 GLint location,
3669 const GLchar *name)
3670{
3671 if (!context->getExtensions().pathRendering)
3672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003673 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003674 return false;
3675 }
3676
3677 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3678 if (location >= MaxLocation)
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003681 return false;
3682 }
3683
3684 const auto *programObject = context->getProgram(program);
3685 if (!programObject)
3686 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003688 return false;
3689 }
3690
3691 if (!name)
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003694 return false;
3695 }
3696
3697 if (angle::BeginsWith(name, "gl_"))
3698 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003700 return false;
3701 }
3702
3703 return true;
3704}
3705
3706bool ValidateProgramPathFragmentInputGen(Context *context,
3707 GLuint program,
3708 GLint location,
3709 GLenum genMode,
3710 GLint components,
3711 const GLfloat *coeffs)
3712{
3713 if (!context->getExtensions().pathRendering)
3714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003715 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003716 return false;
3717 }
3718
3719 const auto *programObject = context->getProgram(program);
3720 if (!programObject || programObject->isFlaggedForDeletion())
3721 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003723 return false;
3724 }
3725
3726 if (!programObject->isLinked())
3727 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003729 return false;
3730 }
3731
3732 switch (genMode)
3733 {
3734 case GL_NONE:
3735 if (components != 0)
3736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003737 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003738 return false;
3739 }
3740 break;
3741
3742 case GL_OBJECT_LINEAR_CHROMIUM:
3743 case GL_EYE_LINEAR_CHROMIUM:
3744 case GL_CONSTANT_CHROMIUM:
3745 if (components < 1 || components > 4)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003748 return false;
3749 }
3750 if (!coeffs)
3751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003753 return false;
3754 }
3755 break;
3756
3757 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003758 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003759 return false;
3760 }
3761
3762 // If the location is -1 then the command is silently ignored
3763 // and no further validation is needed.
3764 if (location == -1)
3765 return true;
3766
Jamie Madillbd044ed2017-06-05 12:59:21 -04003767 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003768
3769 if (!binding.valid)
3770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003772 return false;
3773 }
3774
3775 if (binding.type != GL_NONE)
3776 {
3777 GLint expectedComponents = 0;
3778 switch (binding.type)
3779 {
3780 case GL_FLOAT:
3781 expectedComponents = 1;
3782 break;
3783 case GL_FLOAT_VEC2:
3784 expectedComponents = 2;
3785 break;
3786 case GL_FLOAT_VEC3:
3787 expectedComponents = 3;
3788 break;
3789 case GL_FLOAT_VEC4:
3790 expectedComponents = 4;
3791 break;
3792 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003793 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003794 InvalidOperation()
3795 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003796 return false;
3797 }
3798 if (expectedComponents != components && genMode != GL_NONE)
3799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003800 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003801 return false;
3802 }
3803 }
3804 return true;
3805}
3806
Geoff Lang97073d12016-04-20 10:42:34 -07003807bool ValidateCopyTextureCHROMIUM(Context *context,
3808 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003809 GLint sourceLevel,
3810 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003811 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003812 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003813 GLint internalFormat,
3814 GLenum destType,
3815 GLboolean unpackFlipY,
3816 GLboolean unpackPremultiplyAlpha,
3817 GLboolean unpackUnmultiplyAlpha)
3818{
3819 if (!context->getExtensions().copyTexture)
3820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003821 context->handleError(InvalidOperation()
3822 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003823 return false;
3824 }
3825
Geoff Lang4f0e0032017-05-01 16:04:35 -04003826 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003827 if (source == nullptr)
3828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003829 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003830 return false;
3831 }
3832
3833 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003835 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003836 return false;
3837 }
3838
3839 GLenum sourceTarget = source->getTarget();
3840 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003841
3842 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003844 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003845 return false;
3846 }
3847
Geoff Lang4f0e0032017-05-01 16:04:35 -04003848 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3849 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3850 if (sourceWidth == 0 || sourceHeight == 0)
3851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003853 return false;
3854 }
3855
3856 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3857 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003859 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003860 return false;
3861 }
3862
Geoff Lang4f0e0032017-05-01 16:04:35 -04003863 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003864 if (dest == nullptr)
3865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003866 context->handleError(InvalidValue()
3867 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003868 return false;
3869 }
3870
Geoff Lang4f0e0032017-05-01 16:04:35 -04003871 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003873 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003874 return false;
3875 }
3876
Geoff Lang4f0e0032017-05-01 16:04:35 -04003877 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3878 sourceHeight))
3879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003880 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003881 return false;
3882 }
3883
Geoff Lang97073d12016-04-20 10:42:34 -07003884 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3885 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003887 return false;
3888 }
3889
Geoff Lang4f0e0032017-05-01 16:04:35 -04003890 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(
3893 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003894 return false;
3895 }
3896
Geoff Lang97073d12016-04-20 10:42:34 -07003897 if (dest->getImmutableFormat())
3898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003900 return false;
3901 }
3902
3903 return true;
3904}
3905
3906bool ValidateCopySubTextureCHROMIUM(Context *context,
3907 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003908 GLint sourceLevel,
3909 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003910 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003911 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003912 GLint xoffset,
3913 GLint yoffset,
3914 GLint x,
3915 GLint y,
3916 GLsizei width,
3917 GLsizei height,
3918 GLboolean unpackFlipY,
3919 GLboolean unpackPremultiplyAlpha,
3920 GLboolean unpackUnmultiplyAlpha)
3921{
3922 if (!context->getExtensions().copyTexture)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(InvalidOperation()
3925 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003926 return false;
3927 }
3928
Geoff Lang4f0e0032017-05-01 16:04:35 -04003929 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003930 if (source == nullptr)
3931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003932 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003933 return false;
3934 }
3935
3936 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003938 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003939 return false;
3940 }
3941
3942 GLenum sourceTarget = source->getTarget();
3943 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003944
3945 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003947 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003948 return false;
3949 }
3950
3951 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3952 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(InvalidValue()
3955 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003956 return false;
3957 }
3958
3959 if (x < 0 || y < 0)
3960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003961 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003962 return false;
3963 }
3964
3965 if (width < 0 || height < 0)
3966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003967 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003968 return false;
3969 }
3970
Geoff Lang4f0e0032017-05-01 16:04:35 -04003971 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3972 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003974 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003975 return false;
3976 }
3977
Geoff Lang4f0e0032017-05-01 16:04:35 -04003978 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3979 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003981 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003982 return false;
3983 }
3984
Geoff Lang4f0e0032017-05-01 16:04:35 -04003985 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003986 if (dest == nullptr)
3987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003988 context->handleError(InvalidValue()
3989 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003990 return false;
3991 }
3992
Geoff Lang4f0e0032017-05-01 16:04:35 -04003993 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003995 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003996 return false;
3997 }
3998
Geoff Lang4f0e0032017-05-01 16:04:35 -04003999 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07004000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004001 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004002 return false;
4003 }
4004
Geoff Lang4f0e0032017-05-01 16:04:35 -04004005 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
4006 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04004007 context
4008 ->handleError(InvalidOperation()
4009 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04004010 return false;
4011 }
4012
4013 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
4014 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07004015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004016 context->handleError(InvalidOperation()
4017 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07004018 return false;
4019 }
4020
4021 if (xoffset < 0 || yoffset < 0)
4022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004023 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07004024 return false;
4025 }
4026
Geoff Lang4f0e0032017-05-01 16:04:35 -04004027 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
4028 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07004029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004030 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07004031 return false;
4032 }
4033
4034 return true;
4035}
4036
Geoff Lang47110bf2016-04-20 11:13:22 -07004037bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
4038{
4039 if (!context->getExtensions().copyCompressedTexture)
4040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004041 context->handleError(InvalidOperation()
4042 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004043 return false;
4044 }
4045
4046 const gl::Texture *source = context->getTexture(sourceId);
4047 if (source == nullptr)
4048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004049 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004050 return false;
4051 }
4052
4053 if (source->getTarget() != GL_TEXTURE_2D)
4054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004055 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004056 return false;
4057 }
4058
4059 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
4060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004062 return false;
4063 }
4064
4065 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
4066 if (!sourceFormat.info->compressed)
4067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004068 context->handleError(InvalidOperation()
4069 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004070 return false;
4071 }
4072
4073 const gl::Texture *dest = context->getTexture(destId);
4074 if (dest == nullptr)
4075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidValue()
4077 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004078 return false;
4079 }
4080
4081 if (dest->getTarget() != GL_TEXTURE_2D)
4082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004083 context->handleError(InvalidValue()
4084 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004085 return false;
4086 }
4087
4088 if (dest->getImmutableFormat())
4089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004090 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07004091 return false;
4092 }
4093
4094 return true;
4095}
4096
Martin Radev4c4c8e72016-08-04 12:25:34 +03004097bool ValidateCreateShader(Context *context, GLenum type)
4098{
4099 switch (type)
4100 {
4101 case GL_VERTEX_SHADER:
4102 case GL_FRAGMENT_SHADER:
4103 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04004104
Martin Radev4c4c8e72016-08-04 12:25:34 +03004105 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04004106 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03004107 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004108 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Geoff Langeb66a6e2016-10-31 13:06:12 -04004109 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03004110 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04004111 break;
4112
Martin Radev4c4c8e72016-08-04 12:25:34 +03004113 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03004115 return false;
4116 }
Jamie Madill29639852016-09-02 15:00:09 -04004117
4118 return true;
4119}
4120
4121bool ValidateBufferData(ValidationContext *context,
4122 GLenum target,
4123 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004124 const void *data,
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004125 BufferUsage usage)
Jamie Madill29639852016-09-02 15:00:09 -04004126{
4127 if (size < 0)
4128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004129 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04004130 return false;
4131 }
4132
4133 switch (usage)
4134 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004135 case BufferUsage::StreamDraw:
4136 case BufferUsage::StaticDraw:
4137 case BufferUsage::DynamicDraw:
Jamie Madill29639852016-09-02 15:00:09 -04004138 break;
4139
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004140 case BufferUsage::StreamRead:
4141 case BufferUsage::StaticRead:
4142 case BufferUsage::DynamicRead:
4143 case BufferUsage::StreamCopy:
4144 case BufferUsage::StaticCopy:
4145 case BufferUsage::DynamicCopy:
Jamie Madill29639852016-09-02 15:00:09 -04004146 if (context->getClientMajorVersion() < 3)
4147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004149 return false;
4150 }
4151 break;
4152
4153 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004154 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004155 return false;
4156 }
4157
4158 if (!ValidBufferTarget(context, target))
4159 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004161 return false;
4162 }
4163
4164 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4165
4166 if (!buffer)
4167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004169 return false;
4170 }
4171
4172 return true;
4173}
4174
4175bool ValidateBufferSubData(ValidationContext *context,
4176 GLenum target,
4177 GLintptr offset,
4178 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004179 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004180{
Brandon Jones6cad5662017-06-14 13:25:13 -07004181 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004183 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4184 return false;
4185 }
4186
4187 if (offset < 0)
4188 {
4189 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004190 return false;
4191 }
4192
4193 if (!ValidBufferTarget(context, target))
4194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004196 return false;
4197 }
4198
4199 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4200
4201 if (!buffer)
4202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004204 return false;
4205 }
4206
4207 if (buffer->isMapped())
4208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004209 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004210 return false;
4211 }
4212
4213 // Check for possible overflow of size + offset
4214 angle::CheckedNumeric<size_t> checkedSize(size);
4215 checkedSize += offset;
4216 if (!checkedSize.IsValid())
4217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004218 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004219 return false;
4220 }
4221
4222 if (size + offset > buffer->getSize())
4223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004224 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004225 return false;
4226 }
4227
Martin Radev4c4c8e72016-08-04 12:25:34 +03004228 return true;
4229}
4230
Geoff Lang111a99e2017-10-17 10:58:41 -04004231bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004232{
Geoff Langc339c4e2016-11-29 10:37:36 -05004233 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004235 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004236 return false;
4237 }
4238
Geoff Lang111a99e2017-10-17 10:58:41 -04004239 if (!context->isExtensionRequestable(name))
Geoff Langc287ea62016-09-16 14:46:51 -04004240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004241 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004242 return false;
4243 }
4244
4245 return true;
4246}
4247
Jamie Madillef300b12016-10-07 15:12:09 -04004248bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4249{
4250 if (texture < GL_TEXTURE0 ||
4251 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004253 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004254 return false;
4255 }
4256
4257 return true;
4258}
4259
4260bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4261{
4262 Program *programObject = GetValidProgram(context, program);
4263 if (!programObject)
4264 {
4265 return false;
4266 }
4267
4268 Shader *shaderObject = GetValidShader(context, shader);
4269 if (!shaderObject)
4270 {
4271 return false;
4272 }
4273
4274 switch (shaderObject->getType())
4275 {
4276 case GL_VERTEX_SHADER:
4277 {
4278 if (programObject->getAttachedVertexShader())
4279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004281 return false;
4282 }
4283 break;
4284 }
4285 case GL_FRAGMENT_SHADER:
4286 {
4287 if (programObject->getAttachedFragmentShader())
4288 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004289 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004290 return false;
4291 }
4292 break;
4293 }
4294 case GL_COMPUTE_SHADER:
4295 {
4296 if (programObject->getAttachedComputeShader())
4297 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004298 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004299 return false;
4300 }
4301 break;
4302 }
4303 default:
4304 UNREACHABLE();
4305 break;
4306 }
4307
4308 return true;
4309}
4310
Jamie Madill01a80ee2016-11-07 12:06:18 -05004311bool ValidateBindAttribLocation(ValidationContext *context,
4312 GLuint program,
4313 GLuint index,
4314 const GLchar *name)
4315{
4316 if (index >= MAX_VERTEX_ATTRIBS)
4317 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004318 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004319 return false;
4320 }
4321
4322 if (strncmp(name, "gl_", 3) == 0)
4323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004325 return false;
4326 }
4327
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004328 if (context->isWebGL())
Geoff Langfc32e8b2017-05-31 14:16:59 -04004329 {
Brandon Jonesed5b46f2017-07-21 08:39:17 -07004330 const size_t length = strlen(name);
4331
4332 if (!IsValidESSLString(name, length))
4333 {
4334 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
4335 // for shader-related entry points
4336 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
4337 return false;
4338 }
4339
4340 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
4341 {
4342 return false;
4343 }
Geoff Langfc32e8b2017-05-31 14:16:59 -04004344 }
4345
Jamie Madill01a80ee2016-11-07 12:06:18 -05004346 return GetValidProgram(context, program) != nullptr;
4347}
4348
4349bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4350{
4351 if (!ValidBufferTarget(context, target))
4352 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004354 return false;
4355 }
4356
4357 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4358 !context->isBufferGenerated(buffer))
4359 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004360 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004361 return false;
4362 }
4363
4364 return true;
4365}
4366
4367bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4368{
4369 if (!ValidFramebufferTarget(target))
4370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004372 return false;
4373 }
4374
4375 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4376 !context->isFramebufferGenerated(framebuffer))
4377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004378 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004379 return false;
4380 }
4381
4382 return true;
4383}
4384
4385bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4386{
4387 if (target != GL_RENDERBUFFER)
4388 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004390 return false;
4391 }
4392
4393 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4394 !context->isRenderbufferGenerated(renderbuffer))
4395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004396 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004397 return false;
4398 }
4399
4400 return true;
4401}
4402
Geoff Lang50cac572017-09-26 17:37:43 -04004403static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004404{
4405 switch (mode)
4406 {
4407 case GL_FUNC_ADD:
4408 case GL_FUNC_SUBTRACT:
4409 case GL_FUNC_REVERSE_SUBTRACT:
Geoff Lang50cac572017-09-26 17:37:43 -04004410 return true;
4411
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004412 case GL_MIN:
4413 case GL_MAX:
Geoff Lang50cac572017-09-26 17:37:43 -04004414 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004415
4416 default:
4417 return false;
4418 }
4419}
4420
Jamie Madillc1d770e2017-04-13 17:31:24 -04004421bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004422 GLfloat red,
4423 GLfloat green,
4424 GLfloat blue,
4425 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004426{
4427 return true;
4428}
4429
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004430bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4431{
Geoff Lang50cac572017-09-26 17:37:43 -04004432 if (!ValidBlendEquationMode(context, mode))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004435 return false;
4436 }
4437
4438 return true;
4439}
4440
4441bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4442{
Geoff Lang50cac572017-09-26 17:37:43 -04004443 if (!ValidBlendEquationMode(context, modeRGB))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004444 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004446 return false;
4447 }
4448
Geoff Lang50cac572017-09-26 17:37:43 -04004449 if (!ValidBlendEquationMode(context, modeAlpha))
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004450 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004452 return false;
4453 }
4454
4455 return true;
4456}
4457
4458bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4459{
4460 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4461}
4462
4463static bool ValidSrcBlendFunc(GLenum srcBlend)
4464{
4465 switch (srcBlend)
4466 {
4467 case GL_ZERO:
4468 case GL_ONE:
4469 case GL_SRC_COLOR:
4470 case GL_ONE_MINUS_SRC_COLOR:
4471 case GL_DST_COLOR:
4472 case GL_ONE_MINUS_DST_COLOR:
4473 case GL_SRC_ALPHA:
4474 case GL_ONE_MINUS_SRC_ALPHA:
4475 case GL_DST_ALPHA:
4476 case GL_ONE_MINUS_DST_ALPHA:
4477 case GL_CONSTANT_COLOR:
4478 case GL_ONE_MINUS_CONSTANT_COLOR:
4479 case GL_CONSTANT_ALPHA:
4480 case GL_ONE_MINUS_CONSTANT_ALPHA:
4481 case GL_SRC_ALPHA_SATURATE:
4482 return true;
4483
4484 default:
4485 return false;
4486 }
4487}
4488
4489static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4490{
4491 switch (dstBlend)
4492 {
4493 case GL_ZERO:
4494 case GL_ONE:
4495 case GL_SRC_COLOR:
4496 case GL_ONE_MINUS_SRC_COLOR:
4497 case GL_DST_COLOR:
4498 case GL_ONE_MINUS_DST_COLOR:
4499 case GL_SRC_ALPHA:
4500 case GL_ONE_MINUS_SRC_ALPHA:
4501 case GL_DST_ALPHA:
4502 case GL_ONE_MINUS_DST_ALPHA:
4503 case GL_CONSTANT_COLOR:
4504 case GL_ONE_MINUS_CONSTANT_COLOR:
4505 case GL_CONSTANT_ALPHA:
4506 case GL_ONE_MINUS_CONSTANT_ALPHA:
4507 return true;
4508
4509 case GL_SRC_ALPHA_SATURATE:
4510 return (contextMajorVersion >= 3);
4511
4512 default:
4513 return false;
4514 }
4515}
4516
4517bool ValidateBlendFuncSeparate(ValidationContext *context,
4518 GLenum srcRGB,
4519 GLenum dstRGB,
4520 GLenum srcAlpha,
4521 GLenum dstAlpha)
4522{
4523 if (!ValidSrcBlendFunc(srcRGB))
4524 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004526 return false;
4527 }
4528
4529 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004532 return false;
4533 }
4534
4535 if (!ValidSrcBlendFunc(srcAlpha))
4536 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004538 return false;
4539 }
4540
4541 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4542 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004543 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004544 return false;
4545 }
4546
Frank Henigman146e8a12017-03-02 23:22:37 -05004547 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4548 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004549 {
4550 bool constantColorUsed =
4551 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4552 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4553
4554 bool constantAlphaUsed =
4555 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4556 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4557
4558 if (constantColorUsed && constantAlphaUsed)
4559 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004560 const char *msg;
4561 if (context->getExtensions().webglCompatibility)
4562 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004563 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004564 }
4565 else
4566 {
4567 msg =
4568 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4569 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4570 "implementation.";
4571 ERR() << msg;
4572 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004573 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004574 return false;
4575 }
4576 }
4577
4578 return true;
4579}
4580
Geoff Langc339c4e2016-11-29 10:37:36 -05004581bool ValidateGetString(Context *context, GLenum name)
4582{
4583 switch (name)
4584 {
4585 case GL_VENDOR:
4586 case GL_RENDERER:
4587 case GL_VERSION:
4588 case GL_SHADING_LANGUAGE_VERSION:
4589 case GL_EXTENSIONS:
4590 break;
4591
4592 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4593 if (!context->getExtensions().requestExtension)
4594 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004596 return false;
4597 }
4598 break;
4599
4600 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004601 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05004602 return false;
4603 }
4604
4605 return true;
4606}
4607
Geoff Lang47c48082016-12-07 15:38:13 -05004608bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4609{
4610 if (width <= 0.0f || isNaN(width))
4611 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004612 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
Geoff Lang47c48082016-12-07 15:38:13 -05004613 return false;
4614 }
4615
4616 return true;
4617}
4618
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004619bool ValidateVertexAttribPointer(ValidationContext *context,
4620 GLuint index,
4621 GLint size,
4622 GLenum type,
4623 GLboolean normalized,
4624 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004625 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004626{
Shao80957d92017-02-20 21:25:59 +08004627 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004628 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004629 return false;
4630 }
4631
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004632 if (stride < 0)
4633 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004634 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004635 return false;
4636 }
4637
Shao80957d92017-02-20 21:25:59 +08004638 const Caps &caps = context->getCaps();
4639 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004640 {
Shao80957d92017-02-20 21:25:59 +08004641 if (stride > caps.maxVertexAttribStride)
4642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004643 context->handleError(InvalidValue()
4644 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004645 return false;
4646 }
4647
4648 if (index >= caps.maxVertexAttribBindings)
4649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004650 context->handleError(InvalidValue()
4651 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004652 return false;
4653 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004654 }
4655
4656 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4657 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4658 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4659 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004660 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4661 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004662 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004664 context
4665 ->handleError(InvalidOperation()
4666 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004667 return false;
4668 }
4669
4670 if (context->getExtensions().webglCompatibility)
4671 {
4672 // WebGL 1.0 [Section 6.14] Fixed point support
4673 // The WebGL API does not support the GL_FIXED data type.
4674 if (type == GL_FIXED)
4675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004676 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004677 return false;
4678 }
4679
Geoff Lang2d62ab72017-03-23 16:54:40 -04004680 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004681 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004682 return false;
4683 }
4684 }
4685
4686 return true;
4687}
4688
Jamie Madill876429b2017-04-20 15:46:24 -04004689bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004690{
4691 if (context->getExtensions().webglCompatibility && zNear > zFar)
4692 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004694 return false;
4695 }
4696
4697 return true;
4698}
4699
Jamie Madille8fb6402017-02-14 17:56:40 -05004700bool ValidateRenderbufferStorage(ValidationContext *context,
4701 GLenum target,
4702 GLenum internalformat,
4703 GLsizei width,
4704 GLsizei height)
4705{
4706 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4707 height);
4708}
4709
4710bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4711 GLenum target,
4712 GLsizei samples,
4713 GLenum internalformat,
4714 GLsizei width,
4715 GLsizei height)
4716{
4717 if (!context->getExtensions().framebufferMultisample)
4718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004719 context->handleError(InvalidOperation()
4720 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004721 return false;
4722 }
4723
4724 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4725 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4726 // generated.
4727 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004729 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004730 return false;
4731 }
4732
4733 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4734 // the specified storage. This is different than ES 3.0 in which a sample number higher
4735 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4736 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4737 if (context->getClientMajorVersion() >= 3)
4738 {
4739 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4740 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004742 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004743 return false;
4744 }
4745 }
4746
4747 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4748 width, height);
4749}
4750
Jamie Madillc1d770e2017-04-13 17:31:24 -04004751bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4752{
4753 if (!ValidFramebufferTarget(target))
4754 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004755 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004756 return false;
4757 }
4758
4759 return true;
4760}
4761
4762bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004763 GLfloat red,
4764 GLfloat green,
4765 GLfloat blue,
4766 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004767{
4768 return true;
4769}
4770
Jamie Madill876429b2017-04-20 15:46:24 -04004771bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004772{
4773 return true;
4774}
4775
4776bool ValidateClearStencil(ValidationContext *context, GLint s)
4777{
4778 return true;
4779}
4780
4781bool ValidateColorMask(ValidationContext *context,
4782 GLboolean red,
4783 GLboolean green,
4784 GLboolean blue,
4785 GLboolean alpha)
4786{
4787 return true;
4788}
4789
4790bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4791{
4792 return true;
4793}
4794
4795bool ValidateCreateProgram(ValidationContext *context)
4796{
4797 return true;
4798}
4799
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004800bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004801{
4802 switch (mode)
4803 {
Corentin Wallez2e568cf2017-09-18 17:05:22 -04004804 case CullFaceMode::Front:
4805 case CullFaceMode::Back:
4806 case CullFaceMode::FrontAndBack:
Jamie Madillc1d770e2017-04-13 17:31:24 -04004807 break;
4808
4809 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004810 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004811 return false;
4812 }
4813
4814 return true;
4815}
4816
4817bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4818{
4819 if (program == 0)
4820 {
4821 return false;
4822 }
4823
4824 if (!context->getProgram(program))
4825 {
4826 if (context->getShader(program))
4827 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004828 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004829 return false;
4830 }
4831 else
4832 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004833 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004834 return false;
4835 }
4836 }
4837
4838 return true;
4839}
4840
4841bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4842{
4843 if (shader == 0)
4844 {
4845 return false;
4846 }
4847
4848 if (!context->getShader(shader))
4849 {
4850 if (context->getProgram(shader))
4851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004853 return false;
4854 }
4855 else
4856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004857 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004858 return false;
4859 }
4860 }
4861
4862 return true;
4863}
4864
4865bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4866{
4867 switch (func)
4868 {
4869 case GL_NEVER:
4870 case GL_ALWAYS:
4871 case GL_LESS:
4872 case GL_LEQUAL:
4873 case GL_EQUAL:
4874 case GL_GREATER:
4875 case GL_GEQUAL:
4876 case GL_NOTEQUAL:
4877 break;
4878
4879 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004880 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004881 return false;
4882 }
4883
4884 return true;
4885}
4886
4887bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4888{
4889 return true;
4890}
4891
4892bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4893{
4894 Program *programObject = GetValidProgram(context, program);
4895 if (!programObject)
4896 {
4897 return false;
4898 }
4899
4900 Shader *shaderObject = GetValidShader(context, shader);
4901 if (!shaderObject)
4902 {
4903 return false;
4904 }
4905
4906 const Shader *attachedShader = nullptr;
4907
4908 switch (shaderObject->getType())
4909 {
4910 case GL_VERTEX_SHADER:
4911 {
4912 attachedShader = programObject->getAttachedVertexShader();
4913 break;
4914 }
4915 case GL_FRAGMENT_SHADER:
4916 {
4917 attachedShader = programObject->getAttachedFragmentShader();
4918 break;
4919 }
4920 case GL_COMPUTE_SHADER:
4921 {
4922 attachedShader = programObject->getAttachedComputeShader();
4923 break;
4924 }
4925 default:
4926 UNREACHABLE();
4927 return false;
4928 }
4929
4930 if (attachedShader != shaderObject)
4931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004933 return false;
4934 }
4935
4936 return true;
4937}
4938
4939bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4940{
4941 if (index >= MAX_VERTEX_ATTRIBS)
4942 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004943 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004944 return false;
4945 }
4946
4947 return true;
4948}
4949
4950bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4951{
4952 if (index >= MAX_VERTEX_ATTRIBS)
4953 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004954 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004955 return false;
4956 }
4957
4958 return true;
4959}
4960
4961bool ValidateFinish(ValidationContext *context)
4962{
4963 return true;
4964}
4965
4966bool ValidateFlush(ValidationContext *context)
4967{
4968 return true;
4969}
4970
4971bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4972{
4973 switch (mode)
4974 {
4975 case GL_CW:
4976 case GL_CCW:
4977 break;
4978 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004980 return false;
4981 }
4982
4983 return true;
4984}
4985
4986bool ValidateGetActiveAttrib(ValidationContext *context,
4987 GLuint program,
4988 GLuint index,
4989 GLsizei bufsize,
4990 GLsizei *length,
4991 GLint *size,
4992 GLenum *type,
4993 GLchar *name)
4994{
4995 if (bufsize < 0)
4996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004997 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004998 return false;
4999 }
5000
5001 Program *programObject = GetValidProgram(context, program);
5002
5003 if (!programObject)
5004 {
5005 return false;
5006 }
5007
5008 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
5009 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005010 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005011 return false;
5012 }
5013
5014 return true;
5015}
5016
5017bool ValidateGetActiveUniform(ValidationContext *context,
5018 GLuint program,
5019 GLuint index,
5020 GLsizei bufsize,
5021 GLsizei *length,
5022 GLint *size,
5023 GLenum *type,
5024 GLchar *name)
5025{
5026 if (bufsize < 0)
5027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005028 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005029 return false;
5030 }
5031
5032 Program *programObject = GetValidProgram(context, program);
5033
5034 if (!programObject)
5035 {
5036 return false;
5037 }
5038
5039 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
5040 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005041 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005042 return false;
5043 }
5044
5045 return true;
5046}
5047
5048bool ValidateGetAttachedShaders(ValidationContext *context,
5049 GLuint program,
5050 GLsizei maxcount,
5051 GLsizei *count,
5052 GLuint *shaders)
5053{
5054 if (maxcount < 0)
5055 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005056 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005057 return false;
5058 }
5059
5060 Program *programObject = GetValidProgram(context, program);
5061
5062 if (!programObject)
5063 {
5064 return false;
5065 }
5066
5067 return true;
5068}
5069
5070bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
5071{
Geoff Langfc32e8b2017-05-31 14:16:59 -04005072 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5073 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005074 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005076 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005077 return false;
5078 }
5079
Jamie Madillc1d770e2017-04-13 17:31:24 -04005080 Program *programObject = GetValidProgram(context, program);
5081
5082 if (!programObject)
5083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005085 return false;
5086 }
5087
5088 if (!programObject->isLinked())
5089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005090 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005091 return false;
5092 }
5093
5094 return true;
5095}
5096
5097bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
5098{
5099 GLenum nativeType;
5100 unsigned int numParams = 0;
5101 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5102}
5103
5104bool ValidateGetError(ValidationContext *context)
5105{
5106 return true;
5107}
5108
5109bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
5110{
5111 GLenum nativeType;
5112 unsigned int numParams = 0;
5113 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5114}
5115
5116bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
5117{
5118 GLenum nativeType;
5119 unsigned int numParams = 0;
5120 return ValidateStateQuery(context, pname, &nativeType, &numParams);
5121}
5122
5123bool ValidateGetProgramInfoLog(ValidationContext *context,
5124 GLuint program,
5125 GLsizei bufsize,
5126 GLsizei *length,
5127 GLchar *infolog)
5128{
5129 if (bufsize < 0)
5130 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005132 return false;
5133 }
5134
5135 Program *programObject = GetValidProgram(context, program);
5136 if (!programObject)
5137 {
5138 return false;
5139 }
5140
5141 return true;
5142}
5143
5144bool ValidateGetShaderInfoLog(ValidationContext *context,
5145 GLuint shader,
5146 GLsizei bufsize,
5147 GLsizei *length,
5148 GLchar *infolog)
5149{
5150 if (bufsize < 0)
5151 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005152 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005153 return false;
5154 }
5155
5156 Shader *shaderObject = GetValidShader(context, shader);
5157 if (!shaderObject)
5158 {
5159 return false;
5160 }
5161
5162 return true;
5163}
5164
5165bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5166 GLenum shadertype,
5167 GLenum precisiontype,
5168 GLint *range,
5169 GLint *precision)
5170{
5171 switch (shadertype)
5172 {
5173 case GL_VERTEX_SHADER:
5174 case GL_FRAGMENT_SHADER:
5175 break;
5176 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005177 context->handleError(InvalidOperation()
5178 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005179 return false;
5180 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005182 return false;
5183 }
5184
5185 switch (precisiontype)
5186 {
5187 case GL_LOW_FLOAT:
5188 case GL_MEDIUM_FLOAT:
5189 case GL_HIGH_FLOAT:
5190 case GL_LOW_INT:
5191 case GL_MEDIUM_INT:
5192 case GL_HIGH_INT:
5193 break;
5194
5195 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005197 return false;
5198 }
5199
5200 return true;
5201}
5202
5203bool ValidateGetShaderSource(ValidationContext *context,
5204 GLuint shader,
5205 GLsizei bufsize,
5206 GLsizei *length,
5207 GLchar *source)
5208{
5209 if (bufsize < 0)
5210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005211 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005212 return false;
5213 }
5214
5215 Shader *shaderObject = GetValidShader(context, shader);
5216 if (!shaderObject)
5217 {
5218 return false;
5219 }
5220
5221 return true;
5222}
5223
5224bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5225{
5226 if (strstr(name, "gl_") == name)
5227 {
5228 return false;
5229 }
5230
Geoff Langfc32e8b2017-05-31 14:16:59 -04005231 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5232 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005233 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005236 return false;
5237 }
5238
Jamie Madillc1d770e2017-04-13 17:31:24 -04005239 Program *programObject = GetValidProgram(context, program);
5240
5241 if (!programObject)
5242 {
5243 return false;
5244 }
5245
5246 if (!programObject->isLinked())
5247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005249 return false;
5250 }
5251
5252 return true;
5253}
5254
5255bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5256{
5257 switch (mode)
5258 {
5259 case GL_FASTEST:
5260 case GL_NICEST:
5261 case GL_DONT_CARE:
5262 break;
5263
5264 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005265 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005266 return false;
5267 }
5268
5269 switch (target)
5270 {
5271 case GL_GENERATE_MIPMAP_HINT:
5272 break;
5273
Geoff Lange7bd2182017-06-16 16:13:13 -04005274 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5275 if (context->getClientVersion() < ES_3_0 &&
5276 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005277 {
Brandon Jones72f58fa2017-09-19 10:47:41 -07005278 context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005279 return false;
5280 }
5281 break;
5282
5283 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005284 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005285 return false;
5286 }
5287
5288 return true;
5289}
5290
5291bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5292{
5293 return true;
5294}
5295
5296bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5297{
5298 return true;
5299}
5300
5301bool ValidateIsProgram(ValidationContext *context, GLuint program)
5302{
5303 return true;
5304}
5305
5306bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5307{
5308 return true;
5309}
5310
5311bool ValidateIsShader(ValidationContext *context, GLuint shader)
5312{
5313 return true;
5314}
5315
5316bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5317{
5318 return true;
5319}
5320
5321bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5322{
5323 if (context->getClientMajorVersion() < 3)
5324 {
5325 switch (pname)
5326 {
5327 case GL_UNPACK_IMAGE_HEIGHT:
5328 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005329 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005330 return false;
5331
5332 case GL_UNPACK_ROW_LENGTH:
5333 case GL_UNPACK_SKIP_ROWS:
5334 case GL_UNPACK_SKIP_PIXELS:
5335 if (!context->getExtensions().unpackSubimage)
5336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005337 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005338 return false;
5339 }
5340 break;
5341
5342 case GL_PACK_ROW_LENGTH:
5343 case GL_PACK_SKIP_ROWS:
5344 case GL_PACK_SKIP_PIXELS:
5345 if (!context->getExtensions().packSubimage)
5346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005347 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005348 return false;
5349 }
5350 break;
5351 }
5352 }
5353
5354 if (param < 0)
5355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005356 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005357 return false;
5358 }
5359
5360 switch (pname)
5361 {
5362 case GL_UNPACK_ALIGNMENT:
5363 if (param != 1 && param != 2 && param != 4 && param != 8)
5364 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005365 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005366 return false;
5367 }
5368 break;
5369
5370 case GL_PACK_ALIGNMENT:
5371 if (param != 1 && param != 2 && param != 4 && param != 8)
5372 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005373 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005374 return false;
5375 }
5376 break;
5377
5378 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
Geoff Lang000dab82017-09-27 14:27:07 -04005379 if (!context->getExtensions().packReverseRowOrder)
5380 {
5381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5382 }
5383 break;
5384
Jamie Madillc1d770e2017-04-13 17:31:24 -04005385 case GL_UNPACK_ROW_LENGTH:
5386 case GL_UNPACK_IMAGE_HEIGHT:
5387 case GL_UNPACK_SKIP_IMAGES:
5388 case GL_UNPACK_SKIP_ROWS:
5389 case GL_UNPACK_SKIP_PIXELS:
5390 case GL_PACK_ROW_LENGTH:
5391 case GL_PACK_SKIP_ROWS:
5392 case GL_PACK_SKIP_PIXELS:
5393 break;
5394
5395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005397 return false;
5398 }
5399
5400 return true;
5401}
5402
5403bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5404{
5405 return true;
5406}
5407
5408bool ValidateReleaseShaderCompiler(ValidationContext *context)
5409{
5410 return true;
5411}
5412
Jamie Madill876429b2017-04-20 15:46:24 -04005413bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005414{
5415 return true;
5416}
5417
5418bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5419{
5420 if (width < 0 || height < 0)
5421 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005422 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005423 return false;
5424 }
5425
5426 return true;
5427}
5428
5429bool ValidateShaderBinary(ValidationContext *context,
5430 GLsizei n,
5431 const GLuint *shaders,
5432 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005433 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005434 GLsizei length)
5435{
5436 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5437 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5438 shaderBinaryFormats.end())
5439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005440 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005441 return false;
5442 }
5443
5444 return true;
5445}
5446
5447bool ValidateShaderSource(ValidationContext *context,
5448 GLuint shader,
5449 GLsizei count,
5450 const GLchar *const *string,
5451 const GLint *length)
5452{
5453 if (count < 0)
5454 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005455 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005456 return false;
5457 }
5458
Geoff Langfc32e8b2017-05-31 14:16:59 -04005459 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5460 // shader-related entry points
5461 if (context->getExtensions().webglCompatibility)
5462 {
5463 for (GLsizei i = 0; i < count; i++)
5464 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005465 size_t len =
5466 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005467
5468 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005469 if (!IsValidESSLShaderSourceString(string[i], len,
5470 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005471 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005472 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005473 return false;
5474 }
5475 }
5476 }
5477
Jamie Madillc1d770e2017-04-13 17:31:24 -04005478 Shader *shaderObject = GetValidShader(context, shader);
5479 if (!shaderObject)
5480 {
5481 return false;
5482 }
5483
5484 return true;
5485}
5486
5487bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5488{
5489 if (!IsValidStencilFunc(func))
5490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005492 return false;
5493 }
5494
5495 return true;
5496}
5497
5498bool ValidateStencilFuncSeparate(ValidationContext *context,
5499 GLenum face,
5500 GLenum func,
5501 GLint ref,
5502 GLuint mask)
5503{
5504 if (!IsValidStencilFace(face))
5505 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005507 return false;
5508 }
5509
5510 if (!IsValidStencilFunc(func))
5511 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005513 return false;
5514 }
5515
5516 return true;
5517}
5518
5519bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5520{
5521 return true;
5522}
5523
5524bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5525{
5526 if (!IsValidStencilFace(face))
5527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005529 return false;
5530 }
5531
5532 return true;
5533}
5534
5535bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5536{
5537 if (!IsValidStencilOp(fail))
5538 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005539 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005540 return false;
5541 }
5542
5543 if (!IsValidStencilOp(zfail))
5544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005546 return false;
5547 }
5548
5549 if (!IsValidStencilOp(zpass))
5550 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005551 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005552 return false;
5553 }
5554
5555 return true;
5556}
5557
5558bool ValidateStencilOpSeparate(ValidationContext *context,
5559 GLenum face,
5560 GLenum fail,
5561 GLenum zfail,
5562 GLenum zpass)
5563{
5564 if (!IsValidStencilFace(face))
5565 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005567 return false;
5568 }
5569
5570 return ValidateStencilOp(context, fail, zfail, zpass);
5571}
5572
5573bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5574{
5575 return ValidateUniform(context, GL_FLOAT, location, 1);
5576}
5577
5578bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5579{
5580 return ValidateUniform(context, GL_FLOAT, location, count);
5581}
5582
Jamie Madillbe849e42017-05-02 15:49:00 -04005583bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5584{
5585 return ValidateUniform1iv(context, location, 1, &x);
5586}
5587
Jamie Madillc1d770e2017-04-13 17:31:24 -04005588bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5589{
5590 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5591}
5592
5593bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5594{
5595 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5596}
5597
5598bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5599{
5600 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5601}
5602
5603bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5604{
5605 return ValidateUniform(context, GL_INT_VEC2, location, count);
5606}
5607
5608bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5609{
5610 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5611}
5612
5613bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5614{
5615 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5616}
5617
5618bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5619{
5620 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5621}
5622
5623bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5624{
5625 return ValidateUniform(context, GL_INT_VEC3, location, count);
5626}
5627
5628bool ValidateUniform4f(ValidationContext *context,
5629 GLint location,
5630 GLfloat x,
5631 GLfloat y,
5632 GLfloat z,
5633 GLfloat w)
5634{
5635 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5636}
5637
5638bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5639{
5640 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5641}
5642
5643bool ValidateUniform4i(ValidationContext *context,
5644 GLint location,
5645 GLint x,
5646 GLint y,
5647 GLint z,
5648 GLint w)
5649{
5650 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5651}
5652
5653bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5654{
5655 return ValidateUniform(context, GL_INT_VEC4, location, count);
5656}
5657
5658bool ValidateUniformMatrix2fv(ValidationContext *context,
5659 GLint location,
5660 GLsizei count,
5661 GLboolean transpose,
5662 const GLfloat *value)
5663{
5664 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5665}
5666
5667bool ValidateUniformMatrix3fv(ValidationContext *context,
5668 GLint location,
5669 GLsizei count,
5670 GLboolean transpose,
5671 const GLfloat *value)
5672{
5673 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5674}
5675
5676bool ValidateUniformMatrix4fv(ValidationContext *context,
5677 GLint location,
5678 GLsizei count,
5679 GLboolean transpose,
5680 const GLfloat *value)
5681{
5682 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5683}
5684
5685bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5686{
5687 Program *programObject = GetValidProgram(context, program);
5688
5689 if (!programObject)
5690 {
5691 return false;
5692 }
5693
5694 return true;
5695}
5696
Jamie Madillc1d770e2017-04-13 17:31:24 -04005697bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5698{
5699 return ValidateVertexAttribIndex(context, index);
5700}
5701
5702bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5703{
5704 return ValidateVertexAttribIndex(context, index);
5705}
5706
5707bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5708{
5709 return ValidateVertexAttribIndex(context, index);
5710}
5711
5712bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5713{
5714 return ValidateVertexAttribIndex(context, index);
5715}
5716
5717bool ValidateVertexAttrib3f(ValidationContext *context,
5718 GLuint index,
5719 GLfloat x,
5720 GLfloat y,
5721 GLfloat z)
5722{
5723 return ValidateVertexAttribIndex(context, index);
5724}
5725
5726bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5727{
5728 return ValidateVertexAttribIndex(context, index);
5729}
5730
5731bool ValidateVertexAttrib4f(ValidationContext *context,
5732 GLuint index,
5733 GLfloat x,
5734 GLfloat y,
5735 GLfloat z,
5736 GLfloat w)
5737{
5738 return ValidateVertexAttribIndex(context, index);
5739}
5740
5741bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5742{
5743 return ValidateVertexAttribIndex(context, index);
5744}
5745
5746bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5747{
5748 if (width < 0 || height < 0)
5749 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005750 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005751 return false;
5752 }
5753
5754 return true;
5755}
5756
5757bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5758{
5759 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5760}
5761
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005762bool ValidateDrawElements(ValidationContext *context,
5763 GLenum mode,
5764 GLsizei count,
5765 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005766 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005767{
5768 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5769}
5770
Jamie Madillbe849e42017-05-02 15:49:00 -04005771bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5772 GLenum target,
5773 GLenum attachment,
5774 GLenum pname,
5775 GLint *params)
5776{
5777 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5778 nullptr);
5779}
5780
5781bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5782{
5783 return ValidateGetProgramivBase(context, program, pname, nullptr);
5784}
5785
5786bool ValidateCopyTexImage2D(ValidationContext *context,
5787 GLenum target,
5788 GLint level,
5789 GLenum internalformat,
5790 GLint x,
5791 GLint y,
5792 GLsizei width,
5793 GLsizei height,
5794 GLint border)
5795{
5796 if (context->getClientMajorVersion() < 3)
5797 {
5798 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5799 0, x, y, width, height, border);
5800 }
5801
5802 ASSERT(context->getClientMajorVersion() == 3);
5803 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5804 0, x, y, width, height, border);
5805}
5806
5807bool ValidateCopyTexSubImage2D(Context *context,
5808 GLenum target,
5809 GLint level,
5810 GLint xoffset,
5811 GLint yoffset,
5812 GLint x,
5813 GLint y,
5814 GLsizei width,
5815 GLsizei height)
5816{
5817 if (context->getClientMajorVersion() < 3)
5818 {
5819 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5820 yoffset, x, y, width, height, 0);
5821 }
5822
5823 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5824 yoffset, 0, x, y, width, height, 0);
5825}
5826
5827bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5828{
5829 return ValidateGenOrDelete(context, n);
5830}
5831
5832bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5833{
5834 return ValidateGenOrDelete(context, n);
5835}
5836
5837bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5838{
5839 return ValidateGenOrDelete(context, n);
5840}
5841
5842bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5843{
5844 return ValidateGenOrDelete(context, n);
5845}
5846
5847bool ValidateDisable(Context *context, GLenum cap)
5848{
5849 if (!ValidCap(context, cap, false))
5850 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005852 return false;
5853 }
5854
5855 return true;
5856}
5857
5858bool ValidateEnable(Context *context, GLenum cap)
5859{
5860 if (!ValidCap(context, cap, false))
5861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005862 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005863 return false;
5864 }
5865
5866 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5867 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5868 {
5869 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005870 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005871
5872 // We also output an error message to the debugger window if tracing is active, so that
5873 // developers can see the error message.
5874 ERR() << errorMessage;
5875 return false;
5876 }
5877
5878 return true;
5879}
5880
5881bool ValidateFramebufferRenderbuffer(Context *context,
5882 GLenum target,
5883 GLenum attachment,
5884 GLenum renderbuffertarget,
5885 GLuint renderbuffer)
5886{
Brandon Jones6cad5662017-06-14 13:25:13 -07005887 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5890 return false;
5891 }
5892
5893 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5894 {
5895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005896 return false;
5897 }
5898
5899 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5900 renderbuffertarget, renderbuffer);
5901}
5902
5903bool ValidateFramebufferTexture2D(Context *context,
5904 GLenum target,
5905 GLenum attachment,
5906 GLenum textarget,
5907 GLuint texture,
5908 GLint level)
5909{
5910 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5911 // extension
5912 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5913 level != 0)
5914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005915 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 return false;
5917 }
5918
5919 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5920 {
5921 return false;
5922 }
5923
5924 if (texture != 0)
5925 {
5926 gl::Texture *tex = context->getTexture(texture);
5927 ASSERT(tex);
5928
5929 const gl::Caps &caps = context->getCaps();
5930
5931 switch (textarget)
5932 {
5933 case GL_TEXTURE_2D:
5934 {
5935 if (level > gl::log2(caps.max2DTextureSize))
5936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005937 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005938 return false;
5939 }
5940 if (tex->getTarget() != GL_TEXTURE_2D)
5941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005943 return false;
5944 }
5945 }
5946 break;
5947
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005948 case GL_TEXTURE_RECTANGLE_ANGLE:
5949 {
5950 if (level != 0)
5951 {
5952 context->handleError(InvalidValue());
5953 return false;
5954 }
5955 if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
5956 {
5957 context->handleError(InvalidOperation()
5958 << "Textarget must match the texture target type.");
5959 return false;
5960 }
5961 }
5962 break;
5963
Jamie Madillbe849e42017-05-02 15:49:00 -04005964 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5968 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5969 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5970 {
5971 if (level > gl::log2(caps.maxCubeMapTextureSize))
5972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005973 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005974 return false;
5975 }
5976 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005978 context->handleError(InvalidOperation()
5979 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 return false;
5981 }
5982 }
5983 break;
5984
5985 case GL_TEXTURE_2D_MULTISAMPLE:
5986 {
5987 if (context->getClientVersion() < ES_3_1)
5988 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 return false;
5991 }
5992
5993 if (level != 0)
5994 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005995 ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
Jamie Madillbe849e42017-05-02 15:49:00 -04005996 return false;
5997 }
5998 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006000 context->handleError(InvalidOperation()
6001 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006002 return false;
6003 }
6004 }
6005 break;
6006
6007 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006008 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006009 return false;
6010 }
6011
6012 const Format &format = tex->getFormat(textarget, level);
6013 if (format.info->compressed)
6014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006015 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006016 return false;
6017 }
6018 }
6019
6020 return true;
6021}
6022
6023bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
6024{
6025 return ValidateGenOrDelete(context, n);
6026}
6027
6028bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
6029{
6030 return ValidateGenOrDelete(context, n);
6031}
6032
6033bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
6034{
6035 return ValidateGenOrDelete(context, n);
6036}
6037
6038bool ValidateGenTextures(Context *context, GLint n, GLuint *)
6039{
6040 return ValidateGenOrDelete(context, n);
6041}
6042
6043bool ValidateGenerateMipmap(Context *context, GLenum target)
6044{
6045 if (!ValidTextureTarget(context, target))
6046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04006048 return false;
6049 }
6050
6051 Texture *texture = context->getTargetTexture(target);
6052
6053 if (texture == nullptr)
6054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04006056 return false;
6057 }
6058
6059 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
6060
6061 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
6062 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
6063 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006065 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04006066 return false;
6067 }
6068
6069 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
Geoff Lang536eca12017-09-13 11:23:35 -04006070 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
6071 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
6072 format.stencilBits > 0)
Brandon Jones6cad5662017-06-14 13:25:13 -07006073 {
6074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6075 return false;
6076 }
6077
Geoff Lang536eca12017-09-13 11:23:35 -04006078 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
6079 bool formatUnsized = !format.sized;
6080 bool formatColorRenderableAndFilterable =
6081 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
6082 format.renderSupport(context->getClientVersion(), context->getExtensions());
6083 if (!formatUnsized && !formatColorRenderableAndFilterable)
Jamie Madillbe849e42017-05-02 15:49:00 -04006084 {
Geoff Lang536eca12017-09-13 11:23:35 -04006085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006086 return false;
6087 }
6088
Geoff Lang536eca12017-09-13 11:23:35 -04006089 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
6090 // generation
6091 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
6092 {
6093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
6094 return false;
6095 }
6096
6097 // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
6098 // not.
Geoff Lang65ac5b92017-05-01 13:16:30 -04006099 bool supportsSRGBMipmapGeneration =
6100 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
Geoff Lang536eca12017-09-13 11:23:35 -04006101 if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04006102 {
Geoff Lang536eca12017-09-13 11:23:35 -04006103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
Jamie Madillbe849e42017-05-02 15:49:00 -04006104 return false;
6105 }
6106
6107 // Non-power of 2 ES2 check
6108 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
6109 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
6110 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
6111 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006112 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
6113 target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07006114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04006115 return false;
6116 }
6117
6118 // Cube completeness check
6119 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
6120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04006122 return false;
6123 }
6124
6125 return true;
6126}
6127
6128bool ValidateGetBufferParameteriv(ValidationContext *context,
6129 GLenum target,
6130 GLenum pname,
6131 GLint *params)
6132{
6133 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
6134}
6135
6136bool ValidateGetRenderbufferParameteriv(Context *context,
6137 GLenum target,
6138 GLenum pname,
6139 GLint *params)
6140{
6141 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
6142}
6143
6144bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
6145{
6146 return ValidateGetShaderivBase(context, shader, pname, nullptr);
6147}
6148
6149bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
6150{
6151 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6152}
6153
6154bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
6155{
6156 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6157}
6158
6159bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6160{
6161 return ValidateGetUniformBase(context, program, location);
6162}
6163
6164bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6165{
6166 return ValidateGetUniformBase(context, program, location);
6167}
6168
6169bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6170{
6171 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6172}
6173
6174bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6175{
6176 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6177}
6178
6179bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6180{
6181 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6182}
6183
6184bool ValidateIsEnabled(Context *context, GLenum cap)
6185{
6186 if (!ValidCap(context, cap, true))
6187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006189 return false;
6190 }
6191
6192 return true;
6193}
6194
6195bool ValidateLinkProgram(Context *context, GLuint program)
6196{
6197 if (context->hasActiveTransformFeedback(program))
6198 {
6199 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006200 context->handleError(InvalidOperation() << "Cannot link program while program is "
6201 "associated with an active transform "
6202 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006203 return false;
6204 }
6205
6206 Program *programObject = GetValidProgram(context, program);
6207 if (!programObject)
6208 {
6209 return false;
6210 }
6211
6212 return true;
6213}
6214
Jamie Madill4928b7c2017-06-20 12:57:39 -04006215bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006216 GLint x,
6217 GLint y,
6218 GLsizei width,
6219 GLsizei height,
6220 GLenum format,
6221 GLenum type,
6222 void *pixels)
6223{
6224 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6225 nullptr, pixels);
6226}
6227
6228bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6229{
6230 return ValidateTexParameterBase(context, target, pname, -1, &param);
6231}
6232
6233bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6234{
6235 return ValidateTexParameterBase(context, target, pname, -1, params);
6236}
6237
6238bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6239{
6240 return ValidateTexParameterBase(context, target, pname, -1, &param);
6241}
6242
6243bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6244{
6245 return ValidateTexParameterBase(context, target, pname, -1, params);
6246}
6247
6248bool ValidateUseProgram(Context *context, GLuint program)
6249{
6250 if (program != 0)
6251 {
6252 Program *programObject = context->getProgram(program);
6253 if (!programObject)
6254 {
6255 // ES 3.1.0 section 7.3 page 72
6256 if (context->getShader(program))
6257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006259 return false;
6260 }
6261 else
6262 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006263 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006264 return false;
6265 }
6266 }
6267 if (!programObject->isLinked())
6268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006270 return false;
6271 }
6272 }
6273 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6274 {
6275 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006276 context
6277 ->handleError(InvalidOperation()
6278 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006279 return false;
6280 }
6281
6282 return true;
6283}
6284
Jamie Madillc29968b2016-01-20 11:17:23 -05006285} // namespace gl