blob: 6598c58494bfd429135b8a9a6c2bf92f6ca12a28 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070017#include "libANGLE/ErrorStrings.h"
Jamie Madillef300b12016-10-07 15:12:09 -040018#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/Texture.h"
Jamie Madillef300b12016-10-07 15:12:09 -040023#include "libANGLE/Uniform.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/VertexArray.h"
Jamie Madillef300b12016-10-07 15:12:09 -040025#include "libANGLE/formatutils.h"
26#include "libANGLE/validationES.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29namespace gl
30{
31
Jamie Madillc29968b2016-01-20 11:17:23 -050032namespace
33{
34
35bool IsPartialBlit(gl::Context *context,
36 const FramebufferAttachment *readBuffer,
37 const FramebufferAttachment *writeBuffer,
38 GLint srcX0,
39 GLint srcY0,
40 GLint srcX1,
41 GLint srcY1,
42 GLint dstX0,
43 GLint dstY0,
44 GLint dstX1,
45 GLint dstY1)
46{
47 const Extents &writeSize = writeBuffer->getSize();
48 const Extents &readSize = readBuffer->getSize();
49
50 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
51 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
52 {
53 return true;
54 }
55
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050057 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070058 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050059 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
60 scissor.height < writeSize.height;
61 }
62
63 return false;
64}
65
Sami Väisänend59ca052016-06-21 16:10:00 +030066template <typename T>
67bool ValidatePathInstances(gl::Context *context,
68 GLsizei numPaths,
69 const void *paths,
70 GLuint pathBase)
71{
72 const auto *array = static_cast<const T *>(paths);
73
74 for (GLsizei i = 0; i < numPaths; ++i)
75 {
76 const GLuint pathName = array[i] + pathBase;
77 if (context->hasPath(pathName) && !context->hasPathData(pathName))
78 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050079 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänend59ca052016-06-21 16:10:00 +030080 return false;
81 }
82 }
83 return true;
84}
85
86bool ValidateInstancedPathParameters(gl::Context *context,
87 GLsizei numPaths,
88 GLenum pathNameType,
89 const void *paths,
90 GLuint pathBase,
91 GLenum transformType,
92 const GLfloat *transformValues)
93{
94 if (!context->getExtensions().pathRendering)
95 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050096 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänend59ca052016-06-21 16:10:00 +030097 return false;
98 }
99
100 if (paths == nullptr)
101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500102 context->handleError(InvalidValue() << "No path name array.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300103 return false;
104 }
105
106 if (numPaths < 0)
107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500108 context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500160 context->handleError(InvalidEnum() << "Invalid path name type.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500188 context->handleError(InvalidEnum() << "Invalid transformation.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidValue() << "No transform array given.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang4f0e0032017-05-01 16:04:35 -0400209bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700210{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400211 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400212 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700213 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400214 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700215 case GL_ALPHA:
216 case GL_LUMINANCE:
217 case GL_LUMINANCE_ALPHA:
218 case GL_RGB:
219 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400220 case GL_RGB8:
221 case GL_RGBA8:
222 case GL_BGRA_EXT:
223 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700224 return true;
225
Geoff Lang4f0e0032017-05-01 16:04:35 -0400226 default:
227 return false;
228 }
229}
Geoff Lang97073d12016-04-20 10:42:34 -0700230
Geoff Lang4f0e0032017-05-01 16:04:35 -0400231bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
232{
233 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
234}
235
Geoff Lang4f0e0032017-05-01 16:04:35 -0400236bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
237{
238 // Table 1.0 from the CHROMIUM_copy_texture spec
239 switch (internalFormat)
240 {
241 case GL_RGB:
242 case GL_RGBA:
243 case GL_RGB8:
244 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700245 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400246 case GL_BGRA8_EXT:
247 case GL_SRGB_EXT:
248 case GL_SRGB_ALPHA_EXT:
249 case GL_R8:
250 case GL_R8UI:
251 case GL_RG8:
252 case GL_RG8UI:
253 case GL_SRGB8:
254 case GL_RGB565:
255 case GL_RGB8UI:
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400256 case GL_RGB10_A2:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400257 case GL_SRGB8_ALPHA8:
258 case GL_RGB5_A1:
259 case GL_RGBA4:
260 case GL_RGBA8UI:
261 case GL_RGB9_E5:
262 case GL_R16F:
263 case GL_R32F:
264 case GL_RG16F:
265 case GL_RG32F:
266 case GL_RGB16F:
267 case GL_RGB32F:
268 case GL_RGBA16F:
269 case GL_RGBA32F:
270 case GL_R11F_G11F_B10F:
Brandon Jones340b7b82017-06-26 13:02:31 -0700271 case GL_LUMINANCE:
272 case GL_LUMINANCE_ALPHA:
273 case GL_ALPHA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400274 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700275
276 default:
277 return false;
278 }
279}
280
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400281bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
282{
283 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
284}
285
Geoff Lang97073d12016-04-20 10:42:34 -0700286bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
287{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400288 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700289 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400290 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700291 }
292
Geoff Lang4f0e0032017-05-01 16:04:35 -0400293 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
294 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700295 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400296 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700297 }
298
299 return true;
300}
301
Geoff Lang4f0e0032017-05-01 16:04:35 -0400302bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700303{
304 switch (target)
305 {
306 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400307 return textureType == GL_TEXTURE_2D;
308
309 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
310 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
311 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
312 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
313 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
314 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
315 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700316
317 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
318 // supported
319
320 default:
321 return false;
322 }
323}
324
325bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
326{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400327 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700328 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400329 case GL_TEXTURE_2D:
330 return true;
331
332 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
333 // supported
334
335 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
336 // supported
337
338 default:
339 return false;
340 }
341}
342
343bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
344{
Geoff Lang3847f942017-07-12 11:17:28 -0400345 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400346 {
347 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700348 }
349
Geoff Lang4f0e0032017-05-01 16:04:35 -0400350 if (level > 0 && context->getClientVersion() < ES_3_0)
351 {
352 return false;
353 }
Geoff Lang97073d12016-04-20 10:42:34 -0700354
Geoff Lang4f0e0032017-05-01 16:04:35 -0400355 return true;
356}
357
358bool IsValidCopyTextureDestinationLevel(Context *context,
359 GLenum target,
360 GLint level,
361 GLsizei width,
362 GLsizei height)
363{
Geoff Lang3847f942017-07-12 11:17:28 -0400364 if (!ValidMipLevel(context, target, level))
Geoff Lang4f0e0032017-05-01 16:04:35 -0400365 {
366 return false;
367 }
368
Geoff Lang4f0e0032017-05-01 16:04:35 -0400369 const Caps &caps = context->getCaps();
370 if (target == GL_TEXTURE_2D)
371 {
372 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
373 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
374 {
375 return false;
376 }
377 }
378 else if (IsCubeMapTextureTarget(target))
379 {
380 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
381 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
382 {
383 return false;
384 }
385 }
386
387 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700388}
389
Jamie Madillc1d770e2017-04-13 17:31:24 -0400390bool IsValidStencilFunc(GLenum func)
391{
392 switch (func)
393 {
394 case GL_NEVER:
395 case GL_ALWAYS:
396 case GL_LESS:
397 case GL_LEQUAL:
398 case GL_EQUAL:
399 case GL_GEQUAL:
400 case GL_GREATER:
401 case GL_NOTEQUAL:
402 return true;
403
404 default:
405 return false;
406 }
407}
408
409bool IsValidStencilFace(GLenum face)
410{
411 switch (face)
412 {
413 case GL_FRONT:
414 case GL_BACK:
415 case GL_FRONT_AND_BACK:
416 return true;
417
418 default:
419 return false;
420 }
421}
422
423bool IsValidStencilOp(GLenum op)
424{
425 switch (op)
426 {
427 case GL_ZERO:
428 case GL_KEEP:
429 case GL_REPLACE:
430 case GL_INCR:
431 case GL_DECR:
432 case GL_INVERT:
433 case GL_INCR_WRAP:
434 case GL_DECR_WRAP:
435 return true;
436
437 default:
438 return false;
439 }
440}
441
Jamie Madillbe849e42017-05-02 15:49:00 -0400442bool ValidateES2CopyTexImageParameters(ValidationContext *context,
443 GLenum target,
444 GLint level,
445 GLenum internalformat,
446 bool isSubImage,
447 GLint xoffset,
448 GLint yoffset,
449 GLint x,
450 GLint y,
451 GLsizei width,
452 GLsizei height,
453 GLint border)
454{
455 if (!ValidTexture2DDestinationTarget(context, target))
456 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700457 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400458 return false;
459 }
460
461 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500463 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400464 return false;
465 }
466
467 Format textureFormat = Format::Invalid();
468 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
469 xoffset, yoffset, 0, x, y, width, height, border,
470 &textureFormat))
471 {
472 return false;
473 }
474
475 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
476 GLenum colorbufferFormat =
477 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
478 const auto &formatInfo = *textureFormat.info;
479
480 // [OpenGL ES 2.0.24] table 3.9
481 if (isSubImage)
482 {
483 switch (formatInfo.format)
484 {
485 case GL_ALPHA:
486 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400487 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
488 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400489 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400491 return false;
492 }
493 break;
494 case GL_LUMINANCE:
495 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
496 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
497 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400498 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
499 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400500 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700501 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400502 return false;
503 }
504 break;
505 case GL_RED_EXT:
506 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
507 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
508 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
509 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
510 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400511 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
512 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400513 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400515 return false;
516 }
517 break;
518 case GL_RG_EXT:
519 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
520 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
521 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
522 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400523 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
524 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400525 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700526 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400527 return false;
528 }
529 break;
530 case GL_RGB:
531 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
532 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
533 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400534 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
535 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400536 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400538 return false;
539 }
540 break;
541 case GL_LUMINANCE_ALPHA:
542 case GL_RGBA:
543 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400544 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
545 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400546 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700547 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400548 return false;
549 }
550 break;
551 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
552 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
553 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
554 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
555 case GL_ETC1_RGB8_OES:
556 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
557 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
558 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
559 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
560 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 case GL_DEPTH_COMPONENT:
564 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700565 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400566 return false;
567 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400569 return false;
570 }
571
572 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
573 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700574 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400575 return false;
576 }
577 }
578 else
579 {
580 switch (internalformat)
581 {
582 case GL_ALPHA:
583 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
584 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
585 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
586 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400588 return false;
589 }
590 break;
591 case GL_LUMINANCE:
592 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
593 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
594 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
595 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
596 colorbufferFormat != GL_BGR5_A1_ANGLEX)
597 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400599 return false;
600 }
601 break;
602 case GL_RED_EXT:
603 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
604 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
605 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
606 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
607 colorbufferFormat != GL_BGR5_A1_ANGLEX)
608 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400610 return false;
611 }
612 break;
613 case GL_RG_EXT:
614 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
615 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
616 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
617 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
618 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400620 return false;
621 }
622 break;
623 case GL_RGB:
624 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
625 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
626 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
627 colorbufferFormat != GL_BGR5_A1_ANGLEX)
628 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400630 return false;
631 }
632 break;
633 case GL_LUMINANCE_ALPHA:
634 case GL_RGBA:
635 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
636 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
637 colorbufferFormat != GL_BGR5_A1_ANGLEX)
638 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400640 return false;
641 }
642 break;
643 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
644 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
645 if (context->getExtensions().textureCompressionDXT1)
646 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400648 return false;
649 }
650 else
651 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400653 return false;
654 }
655 break;
656 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
657 if (context->getExtensions().textureCompressionDXT3)
658 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 return false;
661 }
662 else
663 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666 }
667 break;
668 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
669 if (context->getExtensions().textureCompressionDXT5)
670 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 return false;
673 }
674 else
675 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400677 return false;
678 }
679 break;
680 case GL_ETC1_RGB8_OES:
681 if (context->getExtensions().compressedETC1RGB8Texture)
682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500683 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400684 return false;
685 }
686 else
687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500688 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 return false;
690 }
691 break;
692 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
693 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
694 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
695 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
696 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
697 if (context->getExtensions().lossyETCDecode)
698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation()
700 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400701 return false;
702 }
703 else
704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500705 context->handleError(InvalidEnum()
706 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400707 return false;
708 }
709 break;
710 case GL_DEPTH_COMPONENT:
711 case GL_DEPTH_COMPONENT16:
712 case GL_DEPTH_COMPONENT32_OES:
713 case GL_DEPTH_STENCIL_OES:
714 case GL_DEPTH24_STENCIL8_OES:
715 if (context->getExtensions().depthTextures)
716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500717 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400718 return false;
719 }
720 else
721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500722 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400727 return false;
728 }
729 }
730
731 // If width or height is zero, it is a no-op. Return false without setting an error.
732 return (width > 0 && height > 0);
733}
734
735bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
736{
737 switch (cap)
738 {
739 // EXT_multisample_compatibility
740 case GL_MULTISAMPLE_EXT:
741 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
742 return context->getExtensions().multisampleCompatibility;
743
744 case GL_CULL_FACE:
745 case GL_POLYGON_OFFSET_FILL:
746 case GL_SAMPLE_ALPHA_TO_COVERAGE:
747 case GL_SAMPLE_COVERAGE:
748 case GL_SCISSOR_TEST:
749 case GL_STENCIL_TEST:
750 case GL_DEPTH_TEST:
751 case GL_BLEND:
752 case GL_DITHER:
753 return true;
754
755 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
756 case GL_RASTERIZER_DISCARD:
757 return (context->getClientMajorVersion() >= 3);
758
759 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
760 case GL_DEBUG_OUTPUT:
761 return context->getExtensions().debug;
762
763 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
764 return queryOnly && context->getExtensions().bindGeneratesResource;
765
766 case GL_CLIENT_ARRAYS_ANGLE:
767 return queryOnly && context->getExtensions().clientArrays;
768
769 case GL_FRAMEBUFFER_SRGB_EXT:
770 return context->getExtensions().sRGBWriteControl;
771
772 case GL_SAMPLE_MASK:
773 return context->getClientVersion() >= Version(3, 1);
774
775 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
776 return queryOnly && context->getExtensions().robustResourceInitialization;
777
778 default:
779 return false;
780 }
781}
782
Geoff Langfc32e8b2017-05-31 14:16:59 -0400783// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
784// 3.1.
Geoff Langcab92ee2017-07-19 17:32:07 -0400785bool IsValidESSLCharacter(unsigned char c)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400786{
787 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langcab92ee2017-07-19 17:32:07 -0400788 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
789 c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400790 {
791 return true;
792 }
793
794 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
795 if (c >= 9 && c <= 13)
796 {
797 return true;
798 }
799
800 return false;
801}
802
Geoff Langcab92ee2017-07-19 17:32:07 -0400803bool IsValidESSLString(const char *str, size_t len)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400804{
Geoff Langa71a98e2017-06-19 15:15:00 -0400805 for (size_t i = 0; i < len; i++)
806 {
Geoff Langcab92ee2017-07-19 17:32:07 -0400807 if (!IsValidESSLCharacter(str[i]))
Geoff Langa71a98e2017-06-19 15:15:00 -0400808 {
809 return false;
810 }
811 }
812
813 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400814}
815
Geoff Langcab92ee2017-07-19 17:32:07 -0400816bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
817{
818 enum class ParseState
819 {
820 // Have not seen an ASCII non-whitespace character yet on
821 // this line. Possible that we might see a preprocessor
822 // directive.
823 BEGINING_OF_LINE,
824
825 // Have seen at least one ASCII non-whitespace character
826 // on this line.
827 MIDDLE_OF_LINE,
828
829 // Handling a preprocessor directive. Passes through all
830 // characters up to the end of the line. Disables comment
831 // processing.
832 IN_PREPROCESSOR_DIRECTIVE,
833
834 // Handling a single-line comment. The comment text is
835 // replaced with a single space.
836 IN_SINGLE_LINE_COMMENT,
837
838 // Handling a multi-line comment. Newlines are passed
839 // through to preserve line numbers.
840 IN_MULTI_LINE_COMMENT
841 };
842
843 ParseState state = ParseState::BEGINING_OF_LINE;
844 size_t pos = 0;
845
846 while (pos < len)
847 {
848 char c = str[pos];
849 char next = pos + 1 < len ? str[pos + 1] : 0;
850
851 // Check for newlines
852 if (c == '\n' || c == '\r')
853 {
854 if (state != ParseState::IN_MULTI_LINE_COMMENT)
855 {
856 state = ParseState::BEGINING_OF_LINE;
857 }
858
859 pos++;
860 continue;
861 }
862
863 switch (state)
864 {
865 case ParseState::BEGINING_OF_LINE:
866 if (c == ' ')
867 {
868 // Maintain the BEGINING_OF_LINE state until a non-space is seen
869 pos++;
870 }
871 else if (c == '#')
872 {
873 state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
874 pos++;
875 }
876 else
877 {
878 // Don't advance, re-process this character with the MIDDLE_OF_LINE state
879 state = ParseState::MIDDLE_OF_LINE;
880 }
881 break;
882
883 case ParseState::MIDDLE_OF_LINE:
884 if (c == '/' && next == '/')
885 {
886 state = ParseState::IN_SINGLE_LINE_COMMENT;
887 pos++;
888 }
889 else if (c == '/' && next == '*')
890 {
891 state = ParseState::IN_MULTI_LINE_COMMENT;
892 pos++;
893 }
894 else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
895 {
896 // Skip line continuation characters
897 }
898 else if (!IsValidESSLCharacter(c))
899 {
900 return false;
901 }
902 pos++;
903 break;
904
905 case ParseState::IN_PREPROCESSOR_DIRECTIVE:
906 // No matter what the character is, just pass it
907 // through. Do not parse comments in this state.
908 pos++;
909 break;
910
911 case ParseState::IN_SINGLE_LINE_COMMENT:
912 // Line-continuation characters are processed before comment processing.
913 // Advance string if a new line character is immediately behind
914 // line-continuation character.
915 if (c == '\\' && (next == '\n' || next == '\r'))
916 {
917 pos++;
918 }
919 pos++;
920 break;
921
922 case ParseState::IN_MULTI_LINE_COMMENT:
923 if (c == '*' && next == '/')
924 {
925 state = ParseState::MIDDLE_OF_LINE;
926 pos++;
927 }
928 pos++;
929 break;
930 }
931 }
932
933 return true;
934}
935
Jamie Madillc29968b2016-01-20 11:17:23 -0500936} // anonymous namespace
937
Geoff Langff5b2d52016-09-07 11:32:23 -0400938bool ValidateES2TexImageParameters(Context *context,
939 GLenum target,
940 GLint level,
941 GLenum internalformat,
942 bool isCompressed,
943 bool isSubImage,
944 GLint xoffset,
945 GLint yoffset,
946 GLsizei width,
947 GLsizei height,
948 GLint border,
949 GLenum format,
950 GLenum type,
951 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400952 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953{
Jamie Madill6f38f822014-06-06 17:12:20 -0400954 if (!ValidTexture2DDestinationTarget(context, target))
955 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400958 }
959
Austin Kinross08528e12015-10-07 16:24:40 -0700960 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965
Brandon Jones6cad5662017-06-14 13:25:13 -0700966 if (!ValidMipLevel(context, target, level))
967 {
968 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
969 return false;
970 }
971
972 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973 std::numeric_limits<GLsizei>::max() - yoffset < height)
974 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700975 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -0400976 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400977 }
978
Geoff Lang6e898aa2017-06-02 11:17:26 -0400979 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
980 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
981 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
982 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
983 // case.
984 bool nonEqualFormatsAllowed =
985 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
986 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
987
988 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500990 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400991 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400992 }
993
Geoff Langaae65a42014-05-26 12:43:44 -0400994 const gl::Caps &caps = context->getCaps();
995
Geoff Langa9be0dc2014-12-17 12:34:40 -0500996 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500998 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
999 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001001 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001002 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001004 }
Geoff Lang691e58c2014-12-19 17:03:25 -05001005 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -05001006 {
1007 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001009 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001010 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012
Geoff Langa9be0dc2014-12-17 12:34:40 -05001013 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
1014 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
1015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001016 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001017 return false;
1018 }
1019 }
1020 else
1021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001022 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001023 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024 }
1025
He Yunchaoced53ae2016-11-29 15:00:51 +08001026 gl::Texture *texture =
1027 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 if (!texture)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04001031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001032 }
1033
Geoff Langa9be0dc2014-12-17 12:34:40 -05001034 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035 {
Geoff Langca271392017-04-05 12:30:00 -04001036 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1037 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -05001038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001039 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -05001040 return false;
1041 }
1042
Geoff Langa9be0dc2014-12-17 12:34:40 -05001043 if (format != GL_NONE)
1044 {
Geoff Langca271392017-04-05 12:30:00 -04001045 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1046 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001047 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Geoff Langa9be0dc2014-12-17 12:34:40 -05001049 return false;
1050 }
1051 }
1052
1053 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1054 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001056 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001057 return false;
1058 }
1059 }
1060 else
1061 {
Geoff Lang69cce582015-09-17 13:20:36 -04001062 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -05001063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001064 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001065 return false;
1066 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001067 }
1068
1069 // Verify zero border
1070 if (border != 0)
1071 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001072 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04001073 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 }
1075
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 if (isCompressed)
1077 {
tmartino0ccd5ae2015-10-01 14:33:14 -04001078 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -04001079 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1080 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 switch (actualInternalFormat)
1082 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1084 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1085 if (!context->getExtensions().textureCompressionDXT1)
1086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001088 return false;
1089 }
1090 break;
1091 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1092 if (!context->getExtensions().textureCompressionDXT1)
1093 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 return false;
1096 }
1097 break;
1098 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1099 if (!context->getExtensions().textureCompressionDXT5)
1100 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001101 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001102 return false;
1103 }
1104 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001105 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1106 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1107 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1108 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
1109 if (!context->getExtensions().textureCompressionS3TCsRGB)
1110 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -08001112 return false;
1113 }
1114 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 case GL_ETC1_RGB8_OES:
1116 if (!context->getExtensions().compressedETC1RGB8Texture)
1117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001119 return false;
1120 }
1121 break;
1122 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001123 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1124 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1125 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1126 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 if (!context->getExtensions().lossyETCDecode)
1128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001129 context->handleError(InvalidEnum()
1130 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001131 return false;
1132 }
1133 break;
1134 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001137 }
Geoff Lang966c9402017-04-18 12:38:27 -04001138
1139 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001140 {
Geoff Lang966c9402017-04-18 12:38:27 -04001141 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1142 height, texture->getWidth(target, level),
1143 texture->getHeight(target, level)))
1144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001145 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001146 return false;
1147 }
1148
1149 if (format != actualInternalFormat)
1150 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001151 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001152 return false;
1153 }
1154 }
1155 else
1156 {
1157 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001159 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001160 return false;
1161 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001162 }
1163 }
1164 else
1165 {
1166 // validate <type> by itself (used as secondary key below)
1167 switch (type)
1168 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001169 case GL_UNSIGNED_BYTE:
1170 case GL_UNSIGNED_SHORT_5_6_5:
1171 case GL_UNSIGNED_SHORT_4_4_4_4:
1172 case GL_UNSIGNED_SHORT_5_5_5_1:
1173 case GL_UNSIGNED_SHORT:
1174 case GL_UNSIGNED_INT:
1175 case GL_UNSIGNED_INT_24_8_OES:
1176 case GL_HALF_FLOAT_OES:
1177 case GL_FLOAT:
1178 break;
1179 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 }
1183
1184 // validate <format> + <type> combinations
1185 // - invalid <format> -> sets INVALID_ENUM
1186 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1187 switch (format)
1188 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001189 case GL_ALPHA:
1190 case GL_LUMINANCE:
1191 case GL_LUMINANCE_ALPHA:
1192 switch (type)
1193 {
1194 case GL_UNSIGNED_BYTE:
1195 case GL_FLOAT:
1196 case GL_HALF_FLOAT_OES:
1197 break;
1198 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001200 return false;
1201 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 case GL_RED:
1204 case GL_RG:
1205 if (!context->getExtensions().textureRG)
1206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001207 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001208 return false;
1209 }
1210 switch (type)
1211 {
1212 case GL_UNSIGNED_BYTE:
1213 case GL_FLOAT:
1214 case GL_HALF_FLOAT_OES:
1215 break;
1216 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
1219 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001220 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 case GL_RGB:
1222 switch (type)
1223 {
1224 case GL_UNSIGNED_BYTE:
1225 case GL_UNSIGNED_SHORT_5_6_5:
1226 case GL_FLOAT:
1227 case GL_HALF_FLOAT_OES:
1228 break;
1229 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001231 return false;
1232 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001233 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 case GL_RGBA:
1235 switch (type)
1236 {
1237 case GL_UNSIGNED_BYTE:
1238 case GL_UNSIGNED_SHORT_4_4_4_4:
1239 case GL_UNSIGNED_SHORT_5_5_5_1:
1240 case GL_FLOAT:
1241 case GL_HALF_FLOAT_OES:
1242 break;
1243 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001245 return false;
1246 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001248 case GL_BGRA_EXT:
1249 switch (type)
1250 {
1251 case GL_UNSIGNED_BYTE:
1252 break;
1253 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001255 return false;
1256 }
1257 break;
1258 case GL_SRGB_EXT:
1259 case GL_SRGB_ALPHA_EXT:
1260 if (!context->getExtensions().sRGB)
1261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001262 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001263 return false;
1264 }
1265 switch (type)
1266 {
1267 case GL_UNSIGNED_BYTE:
1268 break;
1269 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001271 return false;
1272 }
1273 break;
1274 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1275 // handled below
1276 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1277 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1278 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1279 break;
1280 case GL_DEPTH_COMPONENT:
1281 switch (type)
1282 {
1283 case GL_UNSIGNED_SHORT:
1284 case GL_UNSIGNED_INT:
1285 break;
1286 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001288 return false;
1289 }
1290 break;
1291 case GL_DEPTH_STENCIL_OES:
1292 switch (type)
1293 {
1294 case GL_UNSIGNED_INT_24_8_OES:
1295 break;
1296 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001298 return false;
1299 }
1300 break;
1301 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001302 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 }
1305
1306 switch (format)
1307 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001308 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1309 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1310 if (context->getExtensions().textureCompressionDXT1)
1311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001312 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001313 return false;
1314 }
1315 else
1316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001317 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001318 return false;
1319 }
1320 break;
1321 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1322 if (context->getExtensions().textureCompressionDXT3)
1323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 return false;
1326 }
1327 else
1328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001329 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001330 return false;
1331 }
1332 break;
1333 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1334 if (context->getExtensions().textureCompressionDXT5)
1335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 return false;
1338 }
1339 else
1340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001341 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 return false;
1343 }
1344 break;
1345 case GL_ETC1_RGB8_OES:
1346 if (context->getExtensions().compressedETC1RGB8Texture)
1347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001349 return false;
1350 }
1351 else
1352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001354 return false;
1355 }
1356 break;
1357 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001358 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1359 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1360 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1361 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001362 if (context->getExtensions().lossyETCDecode)
1363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation()
1365 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001366 return false;
1367 }
1368 else
1369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidEnum()
1371 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001372 return false;
1373 }
1374 break;
1375 case GL_DEPTH_COMPONENT:
1376 case GL_DEPTH_STENCIL_OES:
1377 if (!context->getExtensions().depthTextures)
1378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001380 return false;
1381 }
1382 if (target != GL_TEXTURE_2D)
1383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001385 return false;
1386 }
1387 // OES_depth_texture supports loading depth data and multiple levels,
1388 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001389 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001392 return false;
1393 }
1394 break;
1395 default:
1396 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
1398
Geoff Lang6e898aa2017-06-02 11:17:26 -04001399 if (!isSubImage)
1400 {
1401 switch (internalformat)
1402 {
1403 case GL_RGBA32F:
1404 if (!context->getExtensions().colorBufferFloatRGBA)
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidValue()
1407 << "Sized GL_RGBA32F internal format requires "
1408 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001409 return false;
1410 }
1411 if (type != GL_FLOAT)
1412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001414 return false;
1415 }
1416 if (format != GL_RGBA)
1417 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001419 return false;
1420 }
1421 break;
1422
1423 case GL_RGB32F:
1424 if (!context->getExtensions().colorBufferFloatRGB)
1425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001426 context->handleError(InvalidValue()
1427 << "Sized GL_RGB32F internal format requires "
1428 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001429 return false;
1430 }
1431 if (type != GL_FLOAT)
1432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001434 return false;
1435 }
1436 if (format != GL_RGB)
1437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001439 return false;
1440 }
1441 break;
1442
1443 default:
1444 break;
1445 }
1446 }
1447
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 if (type == GL_FLOAT)
1449 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001450 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455 }
1456 else if (type == GL_HALF_FLOAT_OES)
1457 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001458 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001460 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 }
1463 }
1464 }
1465
Geoff Langdbcced82017-06-06 15:55:54 -04001466 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1467 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001468 imageSize))
1469 {
1470 return false;
1471 }
1472
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 return true;
1474}
1475
He Yunchaoced53ae2016-11-29 15:00:51 +08001476bool ValidateES2TexStorageParameters(Context *context,
1477 GLenum target,
1478 GLsizei levels,
1479 GLenum internalformat,
1480 GLsizei width,
1481 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001482{
1483 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001485 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001486 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001487 }
1488
1489 if (width < 1 || height < 1 || levels < 1)
1490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001492 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001493 }
1494
1495 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500
1501 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 }
1506
Geoff Langca271392017-04-05 12:30:00 -04001507 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001508 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001511 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 }
1513
Geoff Langaae65a42014-05-26 12:43:44 -04001514 const gl::Caps &caps = context->getCaps();
1515
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516 switch (target)
1517 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001518 case GL_TEXTURE_2D:
1519 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1520 static_cast<GLuint>(height) > caps.max2DTextureSize)
1521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001522 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001523 return false;
1524 }
1525 break;
1526 case GL_TEXTURE_CUBE_MAP:
1527 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1528 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001531 return false;
1532 }
1533 break;
1534 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001536 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 }
1538
Geoff Langc0b9ef42014-07-02 10:02:37 -04001539 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001540 {
1541 if (!gl::isPow2(width) || !gl::isPow2(height))
1542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001543 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001544 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545 }
1546 }
1547
1548 switch (internalformat)
1549 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001550 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1551 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1552 if (!context->getExtensions().textureCompressionDXT1)
1553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001554 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001555 return false;
1556 }
1557 break;
1558 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1559 if (!context->getExtensions().textureCompressionDXT3)
1560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001562 return false;
1563 }
1564 break;
1565 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1566 if (!context->getExtensions().textureCompressionDXT5)
1567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001568 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001569 return false;
1570 }
1571 break;
1572 case GL_ETC1_RGB8_OES:
1573 if (!context->getExtensions().compressedETC1RGB8Texture)
1574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001575 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001576 return false;
1577 }
1578 break;
1579 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001580 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1581 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1582 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1583 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001584 if (!context->getExtensions().lossyETCDecode)
1585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001586 context->handleError(InvalidEnum()
1587 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001588 return false;
1589 }
1590 break;
1591 case GL_RGBA32F_EXT:
1592 case GL_RGB32F_EXT:
1593 case GL_ALPHA32F_EXT:
1594 case GL_LUMINANCE32F_EXT:
1595 case GL_LUMINANCE_ALPHA32F_EXT:
1596 if (!context->getExtensions().textureFloat)
1597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001598 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 return false;
1600 }
1601 break;
1602 case GL_RGBA16F_EXT:
1603 case GL_RGB16F_EXT:
1604 case GL_ALPHA16F_EXT:
1605 case GL_LUMINANCE16F_EXT:
1606 case GL_LUMINANCE_ALPHA16F_EXT:
1607 if (!context->getExtensions().textureHalfFloat)
1608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001610 return false;
1611 }
1612 break;
1613 case GL_R8_EXT:
1614 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001615 if (!context->getExtensions().textureRG)
1616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001618 return false;
1619 }
1620 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001621 case GL_R16F_EXT:
1622 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001623 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001626 return false;
1627 }
1628 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001629 case GL_R32F_EXT:
1630 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001631 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001634 return false;
1635 }
1636 break;
1637 case GL_DEPTH_COMPONENT16:
1638 case GL_DEPTH_COMPONENT32_OES:
1639 case GL_DEPTH24_STENCIL8_OES:
1640 if (!context->getExtensions().depthTextures)
1641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001642 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001643 return false;
1644 }
1645 if (target != GL_TEXTURE_2D)
1646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001648 return false;
1649 }
1650 // ANGLE_depth_texture only supports 1-level textures
1651 if (levels != 1)
1652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001654 return false;
1655 }
1656 break;
1657 default:
1658 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 }
1660
Geoff Lang691e58c2014-12-19 17:03:25 -05001661 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001662 if (!texture || texture->id() == 0)
1663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001664 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001665 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001666 }
1667
Geoff Lang69cce582015-09-17 13:20:36 -04001668 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001671 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001672 }
1673
1674 return true;
1675}
1676
He Yunchaoced53ae2016-11-29 15:00:51 +08001677bool ValidateDiscardFramebufferEXT(Context *context,
1678 GLenum target,
1679 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001680 const GLenum *attachments)
1681{
Jamie Madillc29968b2016-01-20 11:17:23 -05001682 if (!context->getExtensions().discardFramebuffer)
1683 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001685 return false;
1686 }
1687
Austin Kinross08332632015-05-05 13:35:47 -07001688 bool defaultFramebuffer = false;
1689
1690 switch (target)
1691 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001692 case GL_FRAMEBUFFER:
1693 defaultFramebuffer =
1694 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1695 break;
1696 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001697 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001698 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001699 }
1700
He Yunchaoced53ae2016-11-29 15:00:51 +08001701 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1702 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001703}
1704
Austin Kinrossbc781f32015-10-26 09:27:38 -07001705bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1706{
1707 if (!context->getExtensions().vertexArrayObject)
1708 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001709 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001710 return false;
1711 }
1712
1713 return ValidateBindVertexArrayBase(context, array);
1714}
1715
1716bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1717{
1718 if (!context->getExtensions().vertexArrayObject)
1719 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001721 return false;
1722 }
1723
Olli Etuaho41997e72016-03-10 13:38:39 +02001724 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001725}
1726
1727bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1728{
1729 if (!context->getExtensions().vertexArrayObject)
1730 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001731 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001732 return false;
1733 }
1734
Olli Etuaho41997e72016-03-10 13:38:39 +02001735 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001736}
1737
1738bool ValidateIsVertexArrayOES(Context *context)
1739{
1740 if (!context->getExtensions().vertexArrayObject)
1741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001742 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001743 return false;
1744 }
1745
1746 return true;
1747}
Geoff Langc5629752015-12-07 16:29:04 -05001748
1749bool ValidateProgramBinaryOES(Context *context,
1750 GLuint program,
1751 GLenum binaryFormat,
1752 const void *binary,
1753 GLint length)
1754{
1755 if (!context->getExtensions().getProgramBinary)
1756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001758 return false;
1759 }
1760
1761 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1762}
1763
1764bool ValidateGetProgramBinaryOES(Context *context,
1765 GLuint program,
1766 GLsizei bufSize,
1767 GLsizei *length,
1768 GLenum *binaryFormat,
1769 void *binary)
1770{
1771 if (!context->getExtensions().getProgramBinary)
1772 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001774 return false;
1775 }
1776
1777 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1778}
Geoff Lange102fee2015-12-10 11:23:30 -05001779
Geoff Lang70d0f492015-12-10 17:45:46 -05001780static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1781{
1782 switch (source)
1783 {
1784 case GL_DEBUG_SOURCE_API:
1785 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1786 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1787 case GL_DEBUG_SOURCE_OTHER:
1788 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1789 return !mustBeThirdPartyOrApplication;
1790
1791 case GL_DEBUG_SOURCE_THIRD_PARTY:
1792 case GL_DEBUG_SOURCE_APPLICATION:
1793 return true;
1794
1795 default:
1796 return false;
1797 }
1798}
1799
1800static bool ValidDebugType(GLenum type)
1801{
1802 switch (type)
1803 {
1804 case GL_DEBUG_TYPE_ERROR:
1805 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1806 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1807 case GL_DEBUG_TYPE_PERFORMANCE:
1808 case GL_DEBUG_TYPE_PORTABILITY:
1809 case GL_DEBUG_TYPE_OTHER:
1810 case GL_DEBUG_TYPE_MARKER:
1811 case GL_DEBUG_TYPE_PUSH_GROUP:
1812 case GL_DEBUG_TYPE_POP_GROUP:
1813 return true;
1814
1815 default:
1816 return false;
1817 }
1818}
1819
1820static bool ValidDebugSeverity(GLenum severity)
1821{
1822 switch (severity)
1823 {
1824 case GL_DEBUG_SEVERITY_HIGH:
1825 case GL_DEBUG_SEVERITY_MEDIUM:
1826 case GL_DEBUG_SEVERITY_LOW:
1827 case GL_DEBUG_SEVERITY_NOTIFICATION:
1828 return true;
1829
1830 default:
1831 return false;
1832 }
1833}
1834
Geoff Lange102fee2015-12-10 11:23:30 -05001835bool ValidateDebugMessageControlKHR(Context *context,
1836 GLenum source,
1837 GLenum type,
1838 GLenum severity,
1839 GLsizei count,
1840 const GLuint *ids,
1841 GLboolean enabled)
1842{
1843 if (!context->getExtensions().debug)
1844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001846 return false;
1847 }
1848
Geoff Lang70d0f492015-12-10 17:45:46 -05001849 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001851 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001852 return false;
1853 }
1854
1855 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001857 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001858 return false;
1859 }
1860
1861 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001863 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001864 return false;
1865 }
1866
1867 if (count > 0)
1868 {
1869 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001871 context->handleError(
1872 InvalidOperation()
1873 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001874 return false;
1875 }
1876
1877 if (severity != GL_DONT_CARE)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001880 InvalidOperation()
1881 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001882 return false;
1883 }
1884 }
1885
Geoff Lange102fee2015-12-10 11:23:30 -05001886 return true;
1887}
1888
1889bool ValidateDebugMessageInsertKHR(Context *context,
1890 GLenum source,
1891 GLenum type,
1892 GLuint id,
1893 GLenum severity,
1894 GLsizei length,
1895 const GLchar *buf)
1896{
1897 if (!context->getExtensions().debug)
1898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001900 return false;
1901 }
1902
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001903 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 {
1905 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1906 // not generate an error.
1907 return false;
1908 }
1909
1910 if (!ValidDebugSeverity(severity))
1911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001912 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001913 return false;
1914 }
1915
1916 if (!ValidDebugType(type))
1917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001918 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001919 return false;
1920 }
1921
1922 if (!ValidDebugSource(source, true))
1923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001924 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001925 return false;
1926 }
1927
1928 size_t messageLength = (length < 0) ? strlen(buf) : length;
1929 if (messageLength > context->getExtensions().maxDebugMessageLength)
1930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001931 context->handleError(InvalidValue()
1932 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001933 return false;
1934 }
1935
Geoff Lange102fee2015-12-10 11:23:30 -05001936 return true;
1937}
1938
1939bool ValidateDebugMessageCallbackKHR(Context *context,
1940 GLDEBUGPROCKHR callback,
1941 const void *userParam)
1942{
1943 if (!context->getExtensions().debug)
1944 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001945 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001946 return false;
1947 }
1948
Geoff Lange102fee2015-12-10 11:23:30 -05001949 return true;
1950}
1951
1952bool ValidateGetDebugMessageLogKHR(Context *context,
1953 GLuint count,
1954 GLsizei bufSize,
1955 GLenum *sources,
1956 GLenum *types,
1957 GLuint *ids,
1958 GLenum *severities,
1959 GLsizei *lengths,
1960 GLchar *messageLog)
1961{
1962 if (!context->getExtensions().debug)
1963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001965 return false;
1966 }
1967
Geoff Lang70d0f492015-12-10 17:45:46 -05001968 if (bufSize < 0 && messageLog != nullptr)
1969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001970 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05001971 return false;
1972 }
1973
Geoff Lange102fee2015-12-10 11:23:30 -05001974 return true;
1975}
1976
1977bool ValidatePushDebugGroupKHR(Context *context,
1978 GLenum source,
1979 GLuint id,
1980 GLsizei length,
1981 const GLchar *message)
1982{
1983 if (!context->getExtensions().debug)
1984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001986 return false;
1987 }
1988
Geoff Lang70d0f492015-12-10 17:45:46 -05001989 if (!ValidDebugSource(source, true))
1990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001991 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001992 return false;
1993 }
1994
1995 size_t messageLength = (length < 0) ? strlen(message) : length;
1996 if (messageLength > context->getExtensions().maxDebugMessageLength)
1997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001998 context->handleError(InvalidValue()
1999 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002000 return false;
2001 }
2002
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002003 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002004 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002006 context
2007 ->handleError(StackOverflow()
2008 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002009 return false;
2010 }
2011
Geoff Lange102fee2015-12-10 11:23:30 -05002012 return true;
2013}
2014
2015bool ValidatePopDebugGroupKHR(Context *context)
2016{
2017 if (!context->getExtensions().debug)
2018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002020 return false;
2021 }
2022
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002023 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05002024 if (currentStackSize <= 1)
2025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002026 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002027 return false;
2028 }
2029
2030 return true;
2031}
2032
2033static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
2034{
2035 switch (identifier)
2036 {
2037 case GL_BUFFER:
2038 if (context->getBuffer(name) == nullptr)
2039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002040 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002041 return false;
2042 }
2043 return true;
2044
2045 case GL_SHADER:
2046 if (context->getShader(name) == nullptr)
2047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002048 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002049 return false;
2050 }
2051 return true;
2052
2053 case GL_PROGRAM:
2054 if (context->getProgram(name) == nullptr)
2055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002056 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002057 return false;
2058 }
2059 return true;
2060
2061 case GL_VERTEX_ARRAY:
2062 if (context->getVertexArray(name) == nullptr)
2063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002064 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002065 return false;
2066 }
2067 return true;
2068
2069 case GL_QUERY:
2070 if (context->getQuery(name) == nullptr)
2071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002072 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002073 return false;
2074 }
2075 return true;
2076
2077 case GL_TRANSFORM_FEEDBACK:
2078 if (context->getTransformFeedback(name) == nullptr)
2079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002080 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002081 return false;
2082 }
2083 return true;
2084
2085 case GL_SAMPLER:
2086 if (context->getSampler(name) == nullptr)
2087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002088 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002089 return false;
2090 }
2091 return true;
2092
2093 case GL_TEXTURE:
2094 if (context->getTexture(name) == nullptr)
2095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002096 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002097 return false;
2098 }
2099 return true;
2100
2101 case GL_RENDERBUFFER:
2102 if (context->getRenderbuffer(name) == nullptr)
2103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002104 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002105 return false;
2106 }
2107 return true;
2108
2109 case GL_FRAMEBUFFER:
2110 if (context->getFramebuffer(name) == nullptr)
2111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002113 return false;
2114 }
2115 return true;
2116
2117 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002118 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002119 return false;
2120 }
Geoff Lange102fee2015-12-10 11:23:30 -05002121}
2122
Martin Radev9d901792016-07-15 15:58:58 +03002123static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2124{
2125 size_t labelLength = 0;
2126
2127 if (length < 0)
2128 {
2129 if (label != nullptr)
2130 {
2131 labelLength = strlen(label);
2132 }
2133 }
2134 else
2135 {
2136 labelLength = static_cast<size_t>(length);
2137 }
2138
2139 if (labelLength > context->getExtensions().maxLabelLength)
2140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002142 return false;
2143 }
2144
2145 return true;
2146}
2147
Geoff Lange102fee2015-12-10 11:23:30 -05002148bool ValidateObjectLabelKHR(Context *context,
2149 GLenum identifier,
2150 GLuint name,
2151 GLsizei length,
2152 const GLchar *label)
2153{
2154 if (!context->getExtensions().debug)
2155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002157 return false;
2158 }
2159
Geoff Lang70d0f492015-12-10 17:45:46 -05002160 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2161 {
2162 return false;
2163 }
2164
Martin Radev9d901792016-07-15 15:58:58 +03002165 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002166 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002167 return false;
2168 }
2169
Geoff Lange102fee2015-12-10 11:23:30 -05002170 return true;
2171}
2172
2173bool ValidateGetObjectLabelKHR(Context *context,
2174 GLenum identifier,
2175 GLuint name,
2176 GLsizei bufSize,
2177 GLsizei *length,
2178 GLchar *label)
2179{
2180 if (!context->getExtensions().debug)
2181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002183 return false;
2184 }
2185
Geoff Lang70d0f492015-12-10 17:45:46 -05002186 if (bufSize < 0)
2187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002188 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002189 return false;
2190 }
2191
2192 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2193 {
2194 return false;
2195 }
2196
Martin Radev9d901792016-07-15 15:58:58 +03002197 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002198}
2199
2200static bool ValidateObjectPtrName(Context *context, const void *ptr)
2201{
2202 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002204 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002205 return false;
2206 }
2207
Geoff Lange102fee2015-12-10 11:23:30 -05002208 return true;
2209}
2210
2211bool ValidateObjectPtrLabelKHR(Context *context,
2212 const void *ptr,
2213 GLsizei length,
2214 const GLchar *label)
2215{
2216 if (!context->getExtensions().debug)
2217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002219 return false;
2220 }
2221
Geoff Lang70d0f492015-12-10 17:45:46 -05002222 if (!ValidateObjectPtrName(context, ptr))
2223 {
2224 return false;
2225 }
2226
Martin Radev9d901792016-07-15 15:58:58 +03002227 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002228 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002229 return false;
2230 }
2231
Geoff Lange102fee2015-12-10 11:23:30 -05002232 return true;
2233}
2234
2235bool ValidateGetObjectPtrLabelKHR(Context *context,
2236 const void *ptr,
2237 GLsizei bufSize,
2238 GLsizei *length,
2239 GLchar *label)
2240{
2241 if (!context->getExtensions().debug)
2242 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002244 return false;
2245 }
2246
Geoff Lang70d0f492015-12-10 17:45:46 -05002247 if (bufSize < 0)
2248 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002249 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002250 return false;
2251 }
2252
2253 if (!ValidateObjectPtrName(context, ptr))
2254 {
2255 return false;
2256 }
2257
Martin Radev9d901792016-07-15 15:58:58 +03002258 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002259}
2260
2261bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2262{
2263 if (!context->getExtensions().debug)
2264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002266 return false;
2267 }
2268
Geoff Lang70d0f492015-12-10 17:45:46 -05002269 // TODO: represent this in Context::getQueryParameterInfo.
2270 switch (pname)
2271 {
2272 case GL_DEBUG_CALLBACK_FUNCTION:
2273 case GL_DEBUG_CALLBACK_USER_PARAM:
2274 break;
2275
2276 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002278 return false;
2279 }
2280
Geoff Lange102fee2015-12-10 11:23:30 -05002281 return true;
2282}
Jamie Madillc29968b2016-01-20 11:17:23 -05002283
2284bool ValidateBlitFramebufferANGLE(Context *context,
2285 GLint srcX0,
2286 GLint srcY0,
2287 GLint srcX1,
2288 GLint srcY1,
2289 GLint dstX0,
2290 GLint dstY0,
2291 GLint dstX1,
2292 GLint dstY1,
2293 GLbitfield mask,
2294 GLenum filter)
2295{
2296 if (!context->getExtensions().framebufferBlit)
2297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002298 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002299 return false;
2300 }
2301
2302 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2303 {
2304 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002305 context->handleError(InvalidOperation() << "Scaling and flipping in "
2306 "BlitFramebufferANGLE not supported by this "
2307 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002308 return false;
2309 }
2310
2311 if (filter == GL_LINEAR)
2312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002313 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002314 return false;
2315 }
2316
Jamie Madill51f40ec2016-06-15 14:06:00 -04002317 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2318 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002319
2320 if (mask & GL_COLOR_BUFFER_BIT)
2321 {
2322 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2323 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2324
2325 if (readColorAttachment && drawColorAttachment)
2326 {
2327 if (!(readColorAttachment->type() == GL_TEXTURE &&
2328 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2329 readColorAttachment->type() != GL_RENDERBUFFER &&
2330 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002332 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002333 return false;
2334 }
2335
Geoff Langa15472a2015-08-11 11:48:03 -04002336 for (size_t drawbufferIdx = 0;
2337 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002338 {
Geoff Langa15472a2015-08-11 11:48:03 -04002339 const FramebufferAttachment *attachment =
2340 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2341 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002342 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002343 if (!(attachment->type() == GL_TEXTURE &&
2344 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2345 attachment->type() != GL_RENDERBUFFER &&
2346 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002348 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002349 return false;
2350 }
2351
2352 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002353 if (!Format::SameSized(attachment->getFormat(),
2354 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002356 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002357 return false;
2358 }
2359 }
2360 }
2361
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002362 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002363 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2364 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002366 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002367 return false;
2368 }
2369 }
2370 }
2371
2372 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2373 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2374 for (size_t i = 0; i < 2; i++)
2375 {
2376 if (mask & masks[i])
2377 {
2378 const FramebufferAttachment *readBuffer =
2379 readFramebuffer->getAttachment(attachments[i]);
2380 const FramebufferAttachment *drawBuffer =
2381 drawFramebuffer->getAttachment(attachments[i]);
2382
2383 if (readBuffer && drawBuffer)
2384 {
2385 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2386 dstX0, dstY0, dstX1, dstY1))
2387 {
2388 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002389 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2390 "stencil blits are supported by "
2391 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002392 return false;
2393 }
2394
2395 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002397 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002398 return false;
2399 }
2400 }
2401 }
2402 }
2403
2404 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2405 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002406}
Jamie Madillc29968b2016-01-20 11:17:23 -05002407
2408bool ValidateClear(ValidationContext *context, GLbitfield mask)
2409{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002410 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002411 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002413 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002414 return false;
2415 }
2416
2417 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002419 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002420 return false;
2421 }
2422
Geoff Lang76e65652017-03-27 14:58:02 -04002423 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2424 {
2425 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2426 GL_SIGNED_NORMALIZED};
2427
Corentin Wallez59c41592017-07-11 13:19:54 -04002428 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002429 drawBufferIdx++)
2430 {
2431 if (!ValidateWebGLFramebufferAttachmentClearType(
2432 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2433 {
2434 return false;
2435 }
2436 }
2437 }
2438
Jamie Madillc29968b2016-01-20 11:17:23 -05002439 return true;
2440}
2441
2442bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2443{
2444 if (!context->getExtensions().drawBuffers)
2445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002446 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002447 return false;
2448 }
2449
2450 return ValidateDrawBuffersBase(context, n, bufs);
2451}
2452
Jamie Madill73a84962016-02-12 09:27:23 -05002453bool ValidateTexImage2D(Context *context,
2454 GLenum target,
2455 GLint level,
2456 GLint internalformat,
2457 GLsizei width,
2458 GLsizei height,
2459 GLint border,
2460 GLenum format,
2461 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002462 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002463{
Martin Radev1be913c2016-07-11 17:59:16 +03002464 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002465 {
2466 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002467 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002468 }
2469
Martin Radev1be913c2016-07-11 17:59:16 +03002470 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002471 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002472 0, 0, width, height, 1, border, format, type, -1,
2473 pixels);
2474}
2475
2476bool ValidateTexImage2DRobust(Context *context,
2477 GLenum target,
2478 GLint level,
2479 GLint internalformat,
2480 GLsizei width,
2481 GLsizei height,
2482 GLint border,
2483 GLenum format,
2484 GLenum type,
2485 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002486 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002487{
2488 if (!ValidateRobustEntryPoint(context, bufSize))
2489 {
2490 return false;
2491 }
2492
2493 if (context->getClientMajorVersion() < 3)
2494 {
2495 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2496 0, 0, width, height, border, format, type, bufSize,
2497 pixels);
2498 }
2499
2500 ASSERT(context->getClientMajorVersion() >= 3);
2501 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2502 0, 0, width, height, 1, border, format, type, bufSize,
2503 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002504}
2505
2506bool ValidateTexSubImage2D(Context *context,
2507 GLenum target,
2508 GLint level,
2509 GLint xoffset,
2510 GLint yoffset,
2511 GLsizei width,
2512 GLsizei height,
2513 GLenum format,
2514 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002515 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002516{
2517
Martin Radev1be913c2016-07-11 17:59:16 +03002518 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002519 {
2520 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002521 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002522 }
2523
Martin Radev1be913c2016-07-11 17:59:16 +03002524 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002525 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002526 yoffset, 0, width, height, 1, 0, format, type, -1,
2527 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002528}
2529
Geoff Langc52f6f12016-10-14 10:18:00 -04002530bool ValidateTexSubImage2DRobustANGLE(Context *context,
2531 GLenum target,
2532 GLint level,
2533 GLint xoffset,
2534 GLint yoffset,
2535 GLsizei width,
2536 GLsizei height,
2537 GLenum format,
2538 GLenum type,
2539 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002540 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002541{
2542 if (!ValidateRobustEntryPoint(context, bufSize))
2543 {
2544 return false;
2545 }
2546
2547 if (context->getClientMajorVersion() < 3)
2548 {
2549 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2550 yoffset, width, height, 0, format, type, bufSize,
2551 pixels);
2552 }
2553
2554 ASSERT(context->getClientMajorVersion() >= 3);
2555 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2556 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2557 pixels);
2558}
2559
Jamie Madill73a84962016-02-12 09:27:23 -05002560bool ValidateCompressedTexImage2D(Context *context,
2561 GLenum target,
2562 GLint level,
2563 GLenum internalformat,
2564 GLsizei width,
2565 GLsizei height,
2566 GLint border,
2567 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002568 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002569{
Martin Radev1be913c2016-07-11 17:59:16 +03002570 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002571 {
2572 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002573 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002574 {
2575 return false;
2576 }
2577 }
2578 else
2579 {
Martin Radev1be913c2016-07-11 17:59:16 +03002580 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002581 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002582 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002583 data))
2584 {
2585 return false;
2586 }
2587 }
2588
Geoff Langca271392017-04-05 12:30:00 -04002589 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002590 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002591 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002592 if (blockSizeOrErr.isError())
2593 {
2594 context->handleError(blockSizeOrErr.getError());
2595 return false;
2596 }
2597
2598 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002600 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002601 return false;
2602 }
2603
2604 return true;
2605}
2606
Corentin Wallezb2931602017-04-11 15:58:57 -04002607bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2608 GLenum target,
2609 GLint level,
2610 GLenum internalformat,
2611 GLsizei width,
2612 GLsizei height,
2613 GLint border,
2614 GLsizei imageSize,
2615 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002616 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002617{
2618 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2619 {
2620 return false;
2621 }
2622
2623 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2624 border, imageSize, data);
2625}
2626bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2627 GLenum target,
2628 GLint level,
2629 GLint xoffset,
2630 GLint yoffset,
2631 GLsizei width,
2632 GLsizei height,
2633 GLenum format,
2634 GLsizei imageSize,
2635 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002636 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002637{
2638 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2639 {
2640 return false;
2641 }
2642
2643 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2644 format, imageSize, data);
2645}
2646
Jamie Madill73a84962016-02-12 09:27:23 -05002647bool ValidateCompressedTexSubImage2D(Context *context,
2648 GLenum target,
2649 GLint level,
2650 GLint xoffset,
2651 GLint yoffset,
2652 GLsizei width,
2653 GLsizei height,
2654 GLenum format,
2655 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002656 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002657{
Martin Radev1be913c2016-07-11 17:59:16 +03002658 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002659 {
2660 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002661 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002662 {
2663 return false;
2664 }
2665 }
2666 else
2667 {
Martin Radev1be913c2016-07-11 17:59:16 +03002668 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002669 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002670 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002671 data))
2672 {
2673 return false;
2674 }
2675 }
2676
Geoff Langca271392017-04-05 12:30:00 -04002677 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002678 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002679 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002680 if (blockSizeOrErr.isError())
2681 {
2682 context->handleError(blockSizeOrErr.getError());
2683 return false;
2684 }
2685
2686 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002688 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002689 return false;
2690 }
2691
2692 return true;
2693}
2694
Olli Etuaho4f667482016-03-30 15:56:35 +03002695bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2696{
Geoff Lang496c02d2016-10-20 11:38:11 -07002697 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002698}
2699
2700bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2701{
2702 if (!context->getExtensions().mapBuffer)
2703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002704 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002705 return false;
2706 }
2707
2708 if (!ValidBufferTarget(context, target))
2709 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002710 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002711 return false;
2712 }
2713
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002714 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002715
2716 if (buffer == nullptr)
2717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002718 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002719 return false;
2720 }
2721
2722 if (access != GL_WRITE_ONLY_OES)
2723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002724 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002725 return false;
2726 }
2727
2728 if (buffer->isMapped())
2729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002730 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002731 return false;
2732 }
2733
2734 return true;
2735}
2736
2737bool ValidateUnmapBufferOES(Context *context, GLenum target)
2738{
2739 if (!context->getExtensions().mapBuffer)
2740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002741 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002742 return false;
2743 }
2744
2745 return ValidateUnmapBufferBase(context, target);
2746}
2747
2748bool ValidateMapBufferRangeEXT(Context *context,
2749 GLenum target,
2750 GLintptr offset,
2751 GLsizeiptr length,
2752 GLbitfield access)
2753{
2754 if (!context->getExtensions().mapBufferRange)
2755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002756 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002757 return false;
2758 }
2759
2760 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2761}
2762
2763bool ValidateFlushMappedBufferRangeEXT(Context *context,
2764 GLenum target,
2765 GLintptr offset,
2766 GLsizeiptr length)
2767{
2768 if (!context->getExtensions().mapBufferRange)
2769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002770 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002771 return false;
2772 }
2773
2774 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2775}
2776
Ian Ewell54f87462016-03-10 13:47:21 -05002777bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2778{
2779 Texture *textureObject = context->getTexture(texture);
2780 if (textureObject && textureObject->getTarget() != target && texture != 0)
2781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Ian Ewell54f87462016-03-10 13:47:21 -05002783 return false;
2784 }
2785
Geoff Langf41a7152016-09-19 15:11:17 -04002786 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2787 !context->isTextureGenerated(texture))
2788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002789 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002790 return false;
2791 }
2792
Ian Ewell54f87462016-03-10 13:47:21 -05002793 switch (target)
2794 {
2795 case GL_TEXTURE_2D:
2796 case GL_TEXTURE_CUBE_MAP:
2797 break;
2798
2799 case GL_TEXTURE_3D:
2800 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002801 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002803 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002804 return false;
2805 }
2806 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002807
2808 case GL_TEXTURE_2D_MULTISAMPLE:
2809 if (context->getClientVersion() < Version(3, 1))
2810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002811 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002812 return false;
2813 }
Geoff Lang3b573612016-10-31 14:08:10 -04002814 break;
2815
Ian Ewell54f87462016-03-10 13:47:21 -05002816 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002817 if (!context->getExtensions().eglImageExternal &&
2818 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002820 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002821 return false;
2822 }
2823 break;
2824 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002825 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002826 return false;
2827 }
2828
2829 return true;
2830}
2831
Geoff Langd8605522016-04-13 10:19:12 -04002832bool ValidateBindUniformLocationCHROMIUM(Context *context,
2833 GLuint program,
2834 GLint location,
2835 const GLchar *name)
2836{
2837 if (!context->getExtensions().bindUniformLocation)
2838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002839 context->handleError(InvalidOperation()
2840 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002841 return false;
2842 }
2843
2844 Program *programObject = GetValidProgram(context, program);
2845 if (!programObject)
2846 {
2847 return false;
2848 }
2849
2850 if (location < 0)
2851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002852 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002853 return false;
2854 }
2855
2856 const Caps &caps = context->getCaps();
2857 if (static_cast<size_t>(location) >=
2858 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002860 context->handleError(InvalidValue() << "Location must be less than "
2861 "(MAX_VERTEX_UNIFORM_VECTORS + "
2862 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002863 return false;
2864 }
2865
Geoff Langfc32e8b2017-05-31 14:16:59 -04002866 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2867 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04002868 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002870 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04002871 return false;
2872 }
2873
Geoff Langd8605522016-04-13 10:19:12 -04002874 if (strncmp(name, "gl_", 3) == 0)
2875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002876 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04002877 return false;
2878 }
2879
2880 return true;
2881}
2882
Jamie Madille2e406c2016-06-02 13:04:10 -04002883bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002884{
2885 if (!context->getExtensions().framebufferMixedSamples)
2886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002887 context->handleError(InvalidOperation()
2888 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002889 return false;
2890 }
2891 switch (components)
2892 {
2893 case GL_RGB:
2894 case GL_RGBA:
2895 case GL_ALPHA:
2896 case GL_NONE:
2897 break;
2898 default:
2899 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002900 InvalidEnum()
2901 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002902 return false;
2903 }
2904
2905 return true;
2906}
2907
Sami Väisänene45e53b2016-05-25 10:36:04 +03002908// CHROMIUM_path_rendering
2909
2910bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2911{
2912 if (!context->getExtensions().pathRendering)
2913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002914 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002915 return false;
2916 }
2917 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002919 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002920 return false;
2921 }
2922 if (matrix == nullptr)
2923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002924 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002925 return false;
2926 }
2927 return true;
2928}
2929
2930bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2931{
2932 if (!context->getExtensions().pathRendering)
2933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002934 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002935 return false;
2936 }
2937 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002939 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002940 return false;
2941 }
2942 return true;
2943}
2944
2945bool ValidateGenPaths(Context *context, GLsizei range)
2946{
2947 if (!context->getExtensions().pathRendering)
2948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002949 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002950 return false;
2951 }
2952
2953 // range = 0 is undefined in NV_path_rendering.
2954 // we add stricter semantic check here and require a non zero positive range.
2955 if (range <= 0)
2956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002957 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002958 return false;
2959 }
2960
2961 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002964 return false;
2965 }
2966
2967 return true;
2968}
2969
2970bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2971{
2972 if (!context->getExtensions().pathRendering)
2973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002974 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002975 return false;
2976 }
2977
2978 // range = 0 is undefined in NV_path_rendering.
2979 // we add stricter semantic check here and require a non zero positive range.
2980 if (range <= 0)
2981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002982 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002983 return false;
2984 }
2985
2986 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2987 checkedRange += range;
2988
2989 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2990 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002991 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002992 return false;
2993 }
2994 return true;
2995}
2996
2997bool ValidatePathCommands(Context *context,
2998 GLuint path,
2999 GLsizei numCommands,
3000 const GLubyte *commands,
3001 GLsizei numCoords,
3002 GLenum coordType,
3003 const void *coords)
3004{
3005 if (!context->getExtensions().pathRendering)
3006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003007 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003008 return false;
3009 }
3010 if (!context->hasPath(path))
3011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003012 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003013 return false;
3014 }
3015
3016 if (numCommands < 0)
3017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003019 return false;
3020 }
3021 else if (numCommands > 0)
3022 {
3023 if (!commands)
3024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003025 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003026 return false;
3027 }
3028 }
3029
3030 if (numCoords < 0)
3031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003032 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003033 return false;
3034 }
3035 else if (numCoords > 0)
3036 {
3037 if (!coords)
3038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003039 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003040 return false;
3041 }
3042 }
3043
3044 std::uint32_t coordTypeSize = 0;
3045 switch (coordType)
3046 {
3047 case GL_BYTE:
3048 coordTypeSize = sizeof(GLbyte);
3049 break;
3050
3051 case GL_UNSIGNED_BYTE:
3052 coordTypeSize = sizeof(GLubyte);
3053 break;
3054
3055 case GL_SHORT:
3056 coordTypeSize = sizeof(GLshort);
3057 break;
3058
3059 case GL_UNSIGNED_SHORT:
3060 coordTypeSize = sizeof(GLushort);
3061 break;
3062
3063 case GL_FLOAT:
3064 coordTypeSize = sizeof(GLfloat);
3065 break;
3066
3067 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003068 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003069 return false;
3070 }
3071
3072 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
3073 checkedSize += (coordTypeSize * numCoords);
3074 if (!checkedSize.IsValid())
3075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003077 return false;
3078 }
3079
3080 // early return skips command data validation when it doesn't exist.
3081 if (!commands)
3082 return true;
3083
3084 GLsizei expectedNumCoords = 0;
3085 for (GLsizei i = 0; i < numCommands; ++i)
3086 {
3087 switch (commands[i])
3088 {
3089 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
3090 break;
3091 case GL_MOVE_TO_CHROMIUM:
3092 case GL_LINE_TO_CHROMIUM:
3093 expectedNumCoords += 2;
3094 break;
3095 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
3096 expectedNumCoords += 4;
3097 break;
3098 case GL_CUBIC_CURVE_TO_CHROMIUM:
3099 expectedNumCoords += 6;
3100 break;
3101 case GL_CONIC_CURVE_TO_CHROMIUM:
3102 expectedNumCoords += 5;
3103 break;
3104 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003105 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003106 return false;
3107 }
3108 }
3109 if (expectedNumCoords != numCoords)
3110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003111 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003112 return false;
3113 }
3114
3115 return true;
3116}
3117
3118bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3119{
3120 if (!context->getExtensions().pathRendering)
3121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003122 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003123 return false;
3124 }
3125 if (!context->hasPath(path))
3126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003127 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003128 return false;
3129 }
3130
3131 switch (pname)
3132 {
3133 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3134 if (value < 0.0f)
3135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003136 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003137 return false;
3138 }
3139 break;
3140 case GL_PATH_END_CAPS_CHROMIUM:
3141 switch (static_cast<GLenum>(value))
3142 {
3143 case GL_FLAT_CHROMIUM:
3144 case GL_SQUARE_CHROMIUM:
3145 case GL_ROUND_CHROMIUM:
3146 break;
3147 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003148 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003149 return false;
3150 }
3151 break;
3152 case GL_PATH_JOIN_STYLE_CHROMIUM:
3153 switch (static_cast<GLenum>(value))
3154 {
3155 case GL_MITER_REVERT_CHROMIUM:
3156 case GL_BEVEL_CHROMIUM:
3157 case GL_ROUND_CHROMIUM:
3158 break;
3159 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003160 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003161 return false;
3162 }
3163 case GL_PATH_MITER_LIMIT_CHROMIUM:
3164 if (value < 0.0f)
3165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003166 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003167 return false;
3168 }
3169 break;
3170
3171 case GL_PATH_STROKE_BOUND_CHROMIUM:
3172 // no errors, only clamping.
3173 break;
3174
3175 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003176 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003177 return false;
3178 }
3179 return true;
3180}
3181
3182bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3183{
3184 if (!context->getExtensions().pathRendering)
3185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003186 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003187 return false;
3188 }
3189
3190 if (!context->hasPath(path))
3191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003192 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003193 return false;
3194 }
3195 if (!value)
3196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003197 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003198 return false;
3199 }
3200
3201 switch (pname)
3202 {
3203 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3204 case GL_PATH_END_CAPS_CHROMIUM:
3205 case GL_PATH_JOIN_STYLE_CHROMIUM:
3206 case GL_PATH_MITER_LIMIT_CHROMIUM:
3207 case GL_PATH_STROKE_BOUND_CHROMIUM:
3208 break;
3209
3210 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003211 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003212 return false;
3213 }
3214
3215 return true;
3216}
3217
3218bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3219{
3220 if (!context->getExtensions().pathRendering)
3221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003222 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003223 return false;
3224 }
3225
3226 switch (func)
3227 {
3228 case GL_NEVER:
3229 case GL_ALWAYS:
3230 case GL_LESS:
3231 case GL_LEQUAL:
3232 case GL_EQUAL:
3233 case GL_GEQUAL:
3234 case GL_GREATER:
3235 case GL_NOTEQUAL:
3236 break;
3237 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003238 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003239 return false;
3240 }
3241
3242 return true;
3243}
3244
3245// Note that the spec specifies that for the path drawing commands
3246// if the path object is not an existing path object the command
3247// does nothing and no error is generated.
3248// However if the path object exists but has not been specified any
3249// commands then an error is generated.
3250
3251bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3252{
3253 if (!context->getExtensions().pathRendering)
3254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003255 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003256 return false;
3257 }
3258 if (context->hasPath(path) && !context->hasPathData(path))
3259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003260 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003261 return false;
3262 }
3263
3264 switch (fillMode)
3265 {
3266 case GL_COUNT_UP_CHROMIUM:
3267 case GL_COUNT_DOWN_CHROMIUM:
3268 break;
3269 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003270 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003271 return false;
3272 }
3273
3274 if (!isPow2(mask + 1))
3275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003277 return false;
3278 }
3279
3280 return true;
3281}
3282
3283bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3284{
3285 if (!context->getExtensions().pathRendering)
3286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003287 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003288 return false;
3289 }
3290 if (context->hasPath(path) && !context->hasPathData(path))
3291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003292 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003293 return false;
3294 }
3295
3296 return true;
3297}
3298
3299bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3300{
3301 if (!context->getExtensions().pathRendering)
3302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003303 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003304 return false;
3305 }
3306 if (context->hasPath(path) && !context->hasPathData(path))
3307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003308 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003309 return false;
3310 }
3311
3312 switch (coverMode)
3313 {
3314 case GL_CONVEX_HULL_CHROMIUM:
3315 case GL_BOUNDING_BOX_CHROMIUM:
3316 break;
3317 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003319 return false;
3320 }
3321 return true;
3322}
3323
3324bool ValidateStencilThenCoverFillPath(Context *context,
3325 GLuint path,
3326 GLenum fillMode,
3327 GLuint mask,
3328 GLenum coverMode)
3329{
3330 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3331 ValidateCoverPath(context, path, coverMode);
3332}
3333
3334bool ValidateStencilThenCoverStrokePath(Context *context,
3335 GLuint path,
3336 GLint reference,
3337 GLuint mask,
3338 GLenum coverMode)
3339{
3340 return ValidateStencilStrokePath(context, path, reference, mask) &&
3341 ValidateCoverPath(context, path, coverMode);
3342}
3343
3344bool ValidateIsPath(Context *context)
3345{
3346 if (!context->getExtensions().pathRendering)
3347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003348 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003349 return false;
3350 }
3351 return true;
3352}
3353
Sami Väisänend59ca052016-06-21 16:10:00 +03003354bool ValidateCoverFillPathInstanced(Context *context,
3355 GLsizei numPaths,
3356 GLenum pathNameType,
3357 const void *paths,
3358 GLuint pathBase,
3359 GLenum coverMode,
3360 GLenum transformType,
3361 const GLfloat *transformValues)
3362{
3363 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3364 transformType, transformValues))
3365 return false;
3366
3367 switch (coverMode)
3368 {
3369 case GL_CONVEX_HULL_CHROMIUM:
3370 case GL_BOUNDING_BOX_CHROMIUM:
3371 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3372 break;
3373 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003374 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003375 return false;
3376 }
3377
3378 return true;
3379}
3380
3381bool ValidateCoverStrokePathInstanced(Context *context,
3382 GLsizei numPaths,
3383 GLenum pathNameType,
3384 const void *paths,
3385 GLuint pathBase,
3386 GLenum coverMode,
3387 GLenum transformType,
3388 const GLfloat *transformValues)
3389{
3390 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3391 transformType, transformValues))
3392 return false;
3393
3394 switch (coverMode)
3395 {
3396 case GL_CONVEX_HULL_CHROMIUM:
3397 case GL_BOUNDING_BOX_CHROMIUM:
3398 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3399 break;
3400 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003401 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003402 return false;
3403 }
3404
3405 return true;
3406}
3407
3408bool ValidateStencilFillPathInstanced(Context *context,
3409 GLsizei numPaths,
3410 GLenum pathNameType,
3411 const void *paths,
3412 GLuint pathBase,
3413 GLenum fillMode,
3414 GLuint mask,
3415 GLenum transformType,
3416 const GLfloat *transformValues)
3417{
3418
3419 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3420 transformType, transformValues))
3421 return false;
3422
3423 switch (fillMode)
3424 {
3425 case GL_COUNT_UP_CHROMIUM:
3426 case GL_COUNT_DOWN_CHROMIUM:
3427 break;
3428 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003429 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003430 return false;
3431 }
3432 if (!isPow2(mask + 1))
3433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003434 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003435 return false;
3436 }
3437 return true;
3438}
3439
3440bool ValidateStencilStrokePathInstanced(Context *context,
3441 GLsizei numPaths,
3442 GLenum pathNameType,
3443 const void *paths,
3444 GLuint pathBase,
3445 GLint reference,
3446 GLuint mask,
3447 GLenum transformType,
3448 const GLfloat *transformValues)
3449{
3450 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3451 transformType, transformValues))
3452 return false;
3453
3454 // no more validation here.
3455
3456 return true;
3457}
3458
3459bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3460 GLsizei numPaths,
3461 GLenum pathNameType,
3462 const void *paths,
3463 GLuint pathBase,
3464 GLenum fillMode,
3465 GLuint mask,
3466 GLenum coverMode,
3467 GLenum transformType,
3468 const GLfloat *transformValues)
3469{
3470 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3471 transformType, transformValues))
3472 return false;
3473
3474 switch (coverMode)
3475 {
3476 case GL_CONVEX_HULL_CHROMIUM:
3477 case GL_BOUNDING_BOX_CHROMIUM:
3478 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3479 break;
3480 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003481 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003482 return false;
3483 }
3484
3485 switch (fillMode)
3486 {
3487 case GL_COUNT_UP_CHROMIUM:
3488 case GL_COUNT_DOWN_CHROMIUM:
3489 break;
3490 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003492 return false;
3493 }
3494 if (!isPow2(mask + 1))
3495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003496 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003497 return false;
3498 }
3499
3500 return true;
3501}
3502
3503bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3504 GLsizei numPaths,
3505 GLenum pathNameType,
3506 const void *paths,
3507 GLuint pathBase,
3508 GLint reference,
3509 GLuint mask,
3510 GLenum coverMode,
3511 GLenum transformType,
3512 const GLfloat *transformValues)
3513{
3514 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3515 transformType, transformValues))
3516 return false;
3517
3518 switch (coverMode)
3519 {
3520 case GL_CONVEX_HULL_CHROMIUM:
3521 case GL_BOUNDING_BOX_CHROMIUM:
3522 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3523 break;
3524 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003525 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003526 return false;
3527 }
3528
3529 return true;
3530}
3531
Sami Väisänen46eaa942016-06-29 10:26:37 +03003532bool ValidateBindFragmentInputLocation(Context *context,
3533 GLuint program,
3534 GLint location,
3535 const GLchar *name)
3536{
3537 if (!context->getExtensions().pathRendering)
3538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003539 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003540 return false;
3541 }
3542
3543 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3544 if (location >= MaxLocation)
3545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003547 return false;
3548 }
3549
3550 const auto *programObject = context->getProgram(program);
3551 if (!programObject)
3552 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003553 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003554 return false;
3555 }
3556
3557 if (!name)
3558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003560 return false;
3561 }
3562
3563 if (angle::BeginsWith(name, "gl_"))
3564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003566 return false;
3567 }
3568
3569 return true;
3570}
3571
3572bool ValidateProgramPathFragmentInputGen(Context *context,
3573 GLuint program,
3574 GLint location,
3575 GLenum genMode,
3576 GLint components,
3577 const GLfloat *coeffs)
3578{
3579 if (!context->getExtensions().pathRendering)
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003582 return false;
3583 }
3584
3585 const auto *programObject = context->getProgram(program);
3586 if (!programObject || programObject->isFlaggedForDeletion())
3587 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003588 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003589 return false;
3590 }
3591
3592 if (!programObject->isLinked())
3593 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003595 return false;
3596 }
3597
3598 switch (genMode)
3599 {
3600 case GL_NONE:
3601 if (components != 0)
3602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003604 return false;
3605 }
3606 break;
3607
3608 case GL_OBJECT_LINEAR_CHROMIUM:
3609 case GL_EYE_LINEAR_CHROMIUM:
3610 case GL_CONSTANT_CHROMIUM:
3611 if (components < 1 || components > 4)
3612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003614 return false;
3615 }
3616 if (!coeffs)
3617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003619 return false;
3620 }
3621 break;
3622
3623 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003625 return false;
3626 }
3627
3628 // If the location is -1 then the command is silently ignored
3629 // and no further validation is needed.
3630 if (location == -1)
3631 return true;
3632
Jamie Madillbd044ed2017-06-05 12:59:21 -04003633 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003634
3635 if (!binding.valid)
3636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003637 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003638 return false;
3639 }
3640
3641 if (binding.type != GL_NONE)
3642 {
3643 GLint expectedComponents = 0;
3644 switch (binding.type)
3645 {
3646 case GL_FLOAT:
3647 expectedComponents = 1;
3648 break;
3649 case GL_FLOAT_VEC2:
3650 expectedComponents = 2;
3651 break;
3652 case GL_FLOAT_VEC3:
3653 expectedComponents = 3;
3654 break;
3655 case GL_FLOAT_VEC4:
3656 expectedComponents = 4;
3657 break;
3658 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003659 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003660 InvalidOperation()
3661 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003662 return false;
3663 }
3664 if (expectedComponents != components && genMode != GL_NONE)
3665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003666 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003667 return false;
3668 }
3669 }
3670 return true;
3671}
3672
Geoff Lang97073d12016-04-20 10:42:34 -07003673bool ValidateCopyTextureCHROMIUM(Context *context,
3674 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003675 GLint sourceLevel,
3676 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003677 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003678 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003679 GLint internalFormat,
3680 GLenum destType,
3681 GLboolean unpackFlipY,
3682 GLboolean unpackPremultiplyAlpha,
3683 GLboolean unpackUnmultiplyAlpha)
3684{
3685 if (!context->getExtensions().copyTexture)
3686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidOperation()
3688 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003689 return false;
3690 }
3691
Geoff Lang4f0e0032017-05-01 16:04:35 -04003692 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003693 if (source == nullptr)
3694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003695 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003696 return false;
3697 }
3698
3699 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003701 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003702 return false;
3703 }
3704
3705 GLenum sourceTarget = source->getTarget();
3706 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003707
3708 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003710 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003711 return false;
3712 }
3713
Geoff Lang4f0e0032017-05-01 16:04:35 -04003714 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3715 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3716 if (sourceWidth == 0 || sourceHeight == 0)
3717 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003719 return false;
3720 }
3721
3722 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3723 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003726 return false;
3727 }
3728
Geoff Lang4f0e0032017-05-01 16:04:35 -04003729 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003730 if (dest == nullptr)
3731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003732 context->handleError(InvalidValue()
3733 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003734 return false;
3735 }
3736
Geoff Lang4f0e0032017-05-01 16:04:35 -04003737 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003740 return false;
3741 }
3742
Geoff Lang4f0e0032017-05-01 16:04:35 -04003743 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3744 sourceHeight))
3745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003746 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003747 return false;
3748 }
3749
Geoff Lang97073d12016-04-20 10:42:34 -07003750 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003753 return false;
3754 }
3755
Geoff Lang4f0e0032017-05-01 16:04:35 -04003756 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003758 context->handleError(
3759 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003760 return false;
3761 }
3762
Geoff Lang97073d12016-04-20 10:42:34 -07003763 if (dest->getImmutableFormat())
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003766 return false;
3767 }
3768
3769 return true;
3770}
3771
3772bool ValidateCopySubTextureCHROMIUM(Context *context,
3773 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003774 GLint sourceLevel,
3775 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003776 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003777 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003778 GLint xoffset,
3779 GLint yoffset,
3780 GLint x,
3781 GLint y,
3782 GLsizei width,
3783 GLsizei height,
3784 GLboolean unpackFlipY,
3785 GLboolean unpackPremultiplyAlpha,
3786 GLboolean unpackUnmultiplyAlpha)
3787{
3788 if (!context->getExtensions().copyTexture)
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidOperation()
3791 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003792 return false;
3793 }
3794
Geoff Lang4f0e0032017-05-01 16:04:35 -04003795 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003796 if (source == nullptr)
3797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003799 return false;
3800 }
3801
3802 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003804 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003805 return false;
3806 }
3807
3808 GLenum sourceTarget = source->getTarget();
3809 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003810
3811 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003813 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003814 return false;
3815 }
3816
3817 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3818 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003820 context->handleError(InvalidValue()
3821 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003822 return false;
3823 }
3824
3825 if (x < 0 || y < 0)
3826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003828 return false;
3829 }
3830
3831 if (width < 0 || height < 0)
3832 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003833 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003834 return false;
3835 }
3836
Geoff Lang4f0e0032017-05-01 16:04:35 -04003837 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3838 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003840 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003841 return false;
3842 }
3843
Geoff Lang4f0e0032017-05-01 16:04:35 -04003844 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3845 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003848 return false;
3849 }
3850
Geoff Lang4f0e0032017-05-01 16:04:35 -04003851 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003852 if (dest == nullptr)
3853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003854 context->handleError(InvalidValue()
3855 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003856 return false;
3857 }
3858
Geoff Lang4f0e0032017-05-01 16:04:35 -04003859 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003862 return false;
3863 }
3864
Geoff Lang4f0e0032017-05-01 16:04:35 -04003865 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003867 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003868 return false;
3869 }
3870
Geoff Lang4f0e0032017-05-01 16:04:35 -04003871 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3872 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003873 context
3874 ->handleError(InvalidOperation()
3875 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003876 return false;
3877 }
3878
3879 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3880 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003882 context->handleError(InvalidOperation()
3883 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003884 return false;
3885 }
3886
3887 if (xoffset < 0 || yoffset < 0)
3888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003889 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07003890 return false;
3891 }
3892
Geoff Lang4f0e0032017-05-01 16:04:35 -04003893 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3894 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003896 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003897 return false;
3898 }
3899
3900 return true;
3901}
3902
Geoff Lang47110bf2016-04-20 11:13:22 -07003903bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3904{
3905 if (!context->getExtensions().copyCompressedTexture)
3906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidOperation()
3908 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003909 return false;
3910 }
3911
3912 const gl::Texture *source = context->getTexture(sourceId);
3913 if (source == nullptr)
3914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003915 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003916 return false;
3917 }
3918
3919 if (source->getTarget() != GL_TEXTURE_2D)
3920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003921 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003922 return false;
3923 }
3924
3925 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003927 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003928 return false;
3929 }
3930
3931 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3932 if (!sourceFormat.info->compressed)
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidOperation()
3935 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003936 return false;
3937 }
3938
3939 const gl::Texture *dest = context->getTexture(destId);
3940 if (dest == nullptr)
3941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003942 context->handleError(InvalidValue()
3943 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003944 return false;
3945 }
3946
3947 if (dest->getTarget() != GL_TEXTURE_2D)
3948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003949 context->handleError(InvalidValue()
3950 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003951 return false;
3952 }
3953
3954 if (dest->getImmutableFormat())
3955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003956 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003957 return false;
3958 }
3959
3960 return true;
3961}
3962
Martin Radev4c4c8e72016-08-04 12:25:34 +03003963bool ValidateCreateShader(Context *context, GLenum type)
3964{
3965 switch (type)
3966 {
3967 case GL_VERTEX_SHADER:
3968 case GL_FRAGMENT_SHADER:
3969 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003970
Martin Radev4c4c8e72016-08-04 12:25:34 +03003971 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003972 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003974 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003975 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003976 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003977 break;
3978
Martin Radev4c4c8e72016-08-04 12:25:34 +03003979 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003980 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03003981 return false;
3982 }
Jamie Madill29639852016-09-02 15:00:09 -04003983
3984 return true;
3985}
3986
3987bool ValidateBufferData(ValidationContext *context,
3988 GLenum target,
3989 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003990 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003991 GLenum usage)
3992{
3993 if (size < 0)
3994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003995 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04003996 return false;
3997 }
3998
3999 switch (usage)
4000 {
4001 case GL_STREAM_DRAW:
4002 case GL_STATIC_DRAW:
4003 case GL_DYNAMIC_DRAW:
4004 break;
4005
4006 case GL_STREAM_READ:
4007 case GL_STREAM_COPY:
4008 case GL_STATIC_READ:
4009 case GL_STATIC_COPY:
4010 case GL_DYNAMIC_READ:
4011 case GL_DYNAMIC_COPY:
4012 if (context->getClientMajorVersion() < 3)
4013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004015 return false;
4016 }
4017 break;
4018
4019 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04004021 return false;
4022 }
4023
4024 if (!ValidBufferTarget(context, target))
4025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004026 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004027 return false;
4028 }
4029
4030 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4031
4032 if (!buffer)
4033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004035 return false;
4036 }
4037
4038 return true;
4039}
4040
4041bool ValidateBufferSubData(ValidationContext *context,
4042 GLenum target,
4043 GLintptr offset,
4044 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04004045 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04004046{
Brandon Jones6cad5662017-06-14 13:25:13 -07004047 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04004048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004049 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
4050 return false;
4051 }
4052
4053 if (offset < 0)
4054 {
4055 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04004056 return false;
4057 }
4058
4059 if (!ValidBufferTarget(context, target))
4060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004061 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04004062 return false;
4063 }
4064
4065 Buffer *buffer = context->getGLState().getTargetBuffer(target);
4066
4067 if (!buffer)
4068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004069 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04004070 return false;
4071 }
4072
4073 if (buffer->isMapped())
4074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004075 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04004076 return false;
4077 }
4078
4079 // Check for possible overflow of size + offset
4080 angle::CheckedNumeric<size_t> checkedSize(size);
4081 checkedSize += offset;
4082 if (!checkedSize.IsValid())
4083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004084 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04004085 return false;
4086 }
4087
4088 if (size + offset > buffer->getSize())
4089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004090 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04004091 return false;
4092 }
4093
Martin Radev4c4c8e72016-08-04 12:25:34 +03004094 return true;
4095}
4096
Geoff Langc339c4e2016-11-29 10:37:36 -05004097bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04004098{
Geoff Langc339c4e2016-11-29 10:37:36 -05004099 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04004100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004101 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04004102 return false;
4103 }
4104
4105 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
4106 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05004107 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04004108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004109 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04004110 return false;
4111 }
4112
4113 return true;
4114}
4115
Jamie Madillef300b12016-10-07 15:12:09 -04004116bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
4117{
4118 if (texture < GL_TEXTURE0 ||
4119 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004121 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004122 return false;
4123 }
4124
4125 return true;
4126}
4127
4128bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4129{
4130 Program *programObject = GetValidProgram(context, program);
4131 if (!programObject)
4132 {
4133 return false;
4134 }
4135
4136 Shader *shaderObject = GetValidShader(context, shader);
4137 if (!shaderObject)
4138 {
4139 return false;
4140 }
4141
4142 switch (shaderObject->getType())
4143 {
4144 case GL_VERTEX_SHADER:
4145 {
4146 if (programObject->getAttachedVertexShader())
4147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004149 return false;
4150 }
4151 break;
4152 }
4153 case GL_FRAGMENT_SHADER:
4154 {
4155 if (programObject->getAttachedFragmentShader())
4156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004158 return false;
4159 }
4160 break;
4161 }
4162 case GL_COMPUTE_SHADER:
4163 {
4164 if (programObject->getAttachedComputeShader())
4165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004167 return false;
4168 }
4169 break;
4170 }
4171 default:
4172 UNREACHABLE();
4173 break;
4174 }
4175
4176 return true;
4177}
4178
Jamie Madill01a80ee2016-11-07 12:06:18 -05004179bool ValidateBindAttribLocation(ValidationContext *context,
4180 GLuint program,
4181 GLuint index,
4182 const GLchar *name)
4183{
4184 if (index >= MAX_VERTEX_ATTRIBS)
4185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004186 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004187 return false;
4188 }
4189
4190 if (strncmp(name, "gl_", 3) == 0)
4191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004193 return false;
4194 }
4195
Geoff Langfc32e8b2017-05-31 14:16:59 -04004196 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4197 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04004198 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004200 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004201 return false;
4202 }
4203
Jamie Madill01a80ee2016-11-07 12:06:18 -05004204 return GetValidProgram(context, program) != nullptr;
4205}
4206
4207bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4208{
4209 if (!ValidBufferTarget(context, target))
4210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004212 return false;
4213 }
4214
4215 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4216 !context->isBufferGenerated(buffer))
4217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004219 return false;
4220 }
4221
4222 return true;
4223}
4224
4225bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4226{
4227 if (!ValidFramebufferTarget(target))
4228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004230 return false;
4231 }
4232
4233 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4234 !context->isFramebufferGenerated(framebuffer))
4235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004237 return false;
4238 }
4239
4240 return true;
4241}
4242
4243bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4244{
4245 if (target != GL_RENDERBUFFER)
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004248 return false;
4249 }
4250
4251 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4252 !context->isRenderbufferGenerated(renderbuffer))
4253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004255 return false;
4256 }
4257
4258 return true;
4259}
4260
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004261static bool ValidBlendEquationMode(GLenum mode)
4262{
4263 switch (mode)
4264 {
4265 case GL_FUNC_ADD:
4266 case GL_FUNC_SUBTRACT:
4267 case GL_FUNC_REVERSE_SUBTRACT:
4268 case GL_MIN:
4269 case GL_MAX:
4270 return true;
4271
4272 default:
4273 return false;
4274 }
4275}
4276
Jamie Madillc1d770e2017-04-13 17:31:24 -04004277bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004278 GLfloat red,
4279 GLfloat green,
4280 GLfloat blue,
4281 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004282{
4283 return true;
4284}
4285
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004286bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4287{
4288 if (!ValidBlendEquationMode(mode))
4289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004290 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004291 return false;
4292 }
4293
4294 return true;
4295}
4296
4297bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4298{
4299 if (!ValidBlendEquationMode(modeRGB))
4300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004302 return false;
4303 }
4304
4305 if (!ValidBlendEquationMode(modeAlpha))
4306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004308 return false;
4309 }
4310
4311 return true;
4312}
4313
4314bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4315{
4316 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4317}
4318
4319static bool ValidSrcBlendFunc(GLenum srcBlend)
4320{
4321 switch (srcBlend)
4322 {
4323 case GL_ZERO:
4324 case GL_ONE:
4325 case GL_SRC_COLOR:
4326 case GL_ONE_MINUS_SRC_COLOR:
4327 case GL_DST_COLOR:
4328 case GL_ONE_MINUS_DST_COLOR:
4329 case GL_SRC_ALPHA:
4330 case GL_ONE_MINUS_SRC_ALPHA:
4331 case GL_DST_ALPHA:
4332 case GL_ONE_MINUS_DST_ALPHA:
4333 case GL_CONSTANT_COLOR:
4334 case GL_ONE_MINUS_CONSTANT_COLOR:
4335 case GL_CONSTANT_ALPHA:
4336 case GL_ONE_MINUS_CONSTANT_ALPHA:
4337 case GL_SRC_ALPHA_SATURATE:
4338 return true;
4339
4340 default:
4341 return false;
4342 }
4343}
4344
4345static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4346{
4347 switch (dstBlend)
4348 {
4349 case GL_ZERO:
4350 case GL_ONE:
4351 case GL_SRC_COLOR:
4352 case GL_ONE_MINUS_SRC_COLOR:
4353 case GL_DST_COLOR:
4354 case GL_ONE_MINUS_DST_COLOR:
4355 case GL_SRC_ALPHA:
4356 case GL_ONE_MINUS_SRC_ALPHA:
4357 case GL_DST_ALPHA:
4358 case GL_ONE_MINUS_DST_ALPHA:
4359 case GL_CONSTANT_COLOR:
4360 case GL_ONE_MINUS_CONSTANT_COLOR:
4361 case GL_CONSTANT_ALPHA:
4362 case GL_ONE_MINUS_CONSTANT_ALPHA:
4363 return true;
4364
4365 case GL_SRC_ALPHA_SATURATE:
4366 return (contextMajorVersion >= 3);
4367
4368 default:
4369 return false;
4370 }
4371}
4372
4373bool ValidateBlendFuncSeparate(ValidationContext *context,
4374 GLenum srcRGB,
4375 GLenum dstRGB,
4376 GLenum srcAlpha,
4377 GLenum dstAlpha)
4378{
4379 if (!ValidSrcBlendFunc(srcRGB))
4380 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004382 return false;
4383 }
4384
4385 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004388 return false;
4389 }
4390
4391 if (!ValidSrcBlendFunc(srcAlpha))
4392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004394 return false;
4395 }
4396
4397 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4398 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004400 return false;
4401 }
4402
Frank Henigman146e8a12017-03-02 23:22:37 -05004403 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4404 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004405 {
4406 bool constantColorUsed =
4407 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4408 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4409
4410 bool constantAlphaUsed =
4411 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4412 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4413
4414 if (constantColorUsed && constantAlphaUsed)
4415 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004416 const char *msg;
4417 if (context->getExtensions().webglCompatibility)
4418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004419 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004420 }
4421 else
4422 {
4423 msg =
4424 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4425 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4426 "implementation.";
4427 ERR() << msg;
4428 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004429 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004430 return false;
4431 }
4432 }
4433
4434 return true;
4435}
4436
Geoff Langc339c4e2016-11-29 10:37:36 -05004437bool ValidateGetString(Context *context, GLenum name)
4438{
4439 switch (name)
4440 {
4441 case GL_VENDOR:
4442 case GL_RENDERER:
4443 case GL_VERSION:
4444 case GL_SHADING_LANGUAGE_VERSION:
4445 case GL_EXTENSIONS:
4446 break;
4447
4448 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4449 if (!context->getExtensions().requestExtension)
4450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004451 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004452 return false;
4453 }
4454 break;
4455
4456 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004457 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004458 return false;
4459 }
4460
4461 return true;
4462}
4463
Geoff Lang47c48082016-12-07 15:38:13 -05004464bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4465{
4466 if (width <= 0.0f || isNaN(width))
4467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004468 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004469 return false;
4470 }
4471
4472 return true;
4473}
4474
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004475bool ValidateVertexAttribPointer(ValidationContext *context,
4476 GLuint index,
4477 GLint size,
4478 GLenum type,
4479 GLboolean normalized,
4480 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004481 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004482{
Shao80957d92017-02-20 21:25:59 +08004483 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004484 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004485 return false;
4486 }
4487
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004488 if (stride < 0)
4489 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004490 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004491 return false;
4492 }
4493
Shao80957d92017-02-20 21:25:59 +08004494 const Caps &caps = context->getCaps();
4495 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004496 {
Shao80957d92017-02-20 21:25:59 +08004497 if (stride > caps.maxVertexAttribStride)
4498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004499 context->handleError(InvalidValue()
4500 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004501 return false;
4502 }
4503
4504 if (index >= caps.maxVertexAttribBindings)
4505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004506 context->handleError(InvalidValue()
4507 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004508 return false;
4509 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004510 }
4511
4512 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4513 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4514 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4515 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004516 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4517 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004518 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004520 context
4521 ->handleError(InvalidOperation()
4522 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004523 return false;
4524 }
4525
4526 if (context->getExtensions().webglCompatibility)
4527 {
4528 // WebGL 1.0 [Section 6.14] Fixed point support
4529 // The WebGL API does not support the GL_FIXED data type.
4530 if (type == GL_FIXED)
4531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004532 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004533 return false;
4534 }
4535
Geoff Lang2d62ab72017-03-23 16:54:40 -04004536 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004537 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004538 return false;
4539 }
4540 }
4541
4542 return true;
4543}
4544
Jamie Madill876429b2017-04-20 15:46:24 -04004545bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004546{
4547 if (context->getExtensions().webglCompatibility && zNear > zFar)
4548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004550 return false;
4551 }
4552
4553 return true;
4554}
4555
Jamie Madille8fb6402017-02-14 17:56:40 -05004556bool ValidateRenderbufferStorage(ValidationContext *context,
4557 GLenum target,
4558 GLenum internalformat,
4559 GLsizei width,
4560 GLsizei height)
4561{
4562 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4563 height);
4564}
4565
4566bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4567 GLenum target,
4568 GLsizei samples,
4569 GLenum internalformat,
4570 GLsizei width,
4571 GLsizei height)
4572{
4573 if (!context->getExtensions().framebufferMultisample)
4574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004575 context->handleError(InvalidOperation()
4576 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004577 return false;
4578 }
4579
4580 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4581 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4582 // generated.
4583 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004585 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004586 return false;
4587 }
4588
4589 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4590 // the specified storage. This is different than ES 3.0 in which a sample number higher
4591 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4592 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4593 if (context->getClientMajorVersion() >= 3)
4594 {
4595 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4596 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004598 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004599 return false;
4600 }
4601 }
4602
4603 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4604 width, height);
4605}
4606
Jamie Madillc1d770e2017-04-13 17:31:24 -04004607bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4608{
4609 if (!ValidFramebufferTarget(target))
4610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004612 return false;
4613 }
4614
4615 return true;
4616}
4617
4618bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004619 GLfloat red,
4620 GLfloat green,
4621 GLfloat blue,
4622 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004623{
4624 return true;
4625}
4626
Jamie Madill876429b2017-04-20 15:46:24 -04004627bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004628{
4629 return true;
4630}
4631
4632bool ValidateClearStencil(ValidationContext *context, GLint s)
4633{
4634 return true;
4635}
4636
4637bool ValidateColorMask(ValidationContext *context,
4638 GLboolean red,
4639 GLboolean green,
4640 GLboolean blue,
4641 GLboolean alpha)
4642{
4643 return true;
4644}
4645
4646bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4647{
4648 return true;
4649}
4650
4651bool ValidateCreateProgram(ValidationContext *context)
4652{
4653 return true;
4654}
4655
4656bool ValidateCullFace(ValidationContext *context, GLenum mode)
4657{
4658 switch (mode)
4659 {
4660 case GL_FRONT:
4661 case GL_BACK:
4662 case GL_FRONT_AND_BACK:
4663 break;
4664
4665 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004666 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004667 return false;
4668 }
4669
4670 return true;
4671}
4672
4673bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4674{
4675 if (program == 0)
4676 {
4677 return false;
4678 }
4679
4680 if (!context->getProgram(program))
4681 {
4682 if (context->getShader(program))
4683 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004685 return false;
4686 }
4687 else
4688 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004689 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004690 return false;
4691 }
4692 }
4693
4694 return true;
4695}
4696
4697bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4698{
4699 if (shader == 0)
4700 {
4701 return false;
4702 }
4703
4704 if (!context->getShader(shader))
4705 {
4706 if (context->getProgram(shader))
4707 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004709 return false;
4710 }
4711 else
4712 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004713 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004714 return false;
4715 }
4716 }
4717
4718 return true;
4719}
4720
4721bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4722{
4723 switch (func)
4724 {
4725 case GL_NEVER:
4726 case GL_ALWAYS:
4727 case GL_LESS:
4728 case GL_LEQUAL:
4729 case GL_EQUAL:
4730 case GL_GREATER:
4731 case GL_GEQUAL:
4732 case GL_NOTEQUAL:
4733 break;
4734
4735 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004736 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004737 return false;
4738 }
4739
4740 return true;
4741}
4742
4743bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4744{
4745 return true;
4746}
4747
4748bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4749{
4750 Program *programObject = GetValidProgram(context, program);
4751 if (!programObject)
4752 {
4753 return false;
4754 }
4755
4756 Shader *shaderObject = GetValidShader(context, shader);
4757 if (!shaderObject)
4758 {
4759 return false;
4760 }
4761
4762 const Shader *attachedShader = nullptr;
4763
4764 switch (shaderObject->getType())
4765 {
4766 case GL_VERTEX_SHADER:
4767 {
4768 attachedShader = programObject->getAttachedVertexShader();
4769 break;
4770 }
4771 case GL_FRAGMENT_SHADER:
4772 {
4773 attachedShader = programObject->getAttachedFragmentShader();
4774 break;
4775 }
4776 case GL_COMPUTE_SHADER:
4777 {
4778 attachedShader = programObject->getAttachedComputeShader();
4779 break;
4780 }
4781 default:
4782 UNREACHABLE();
4783 return false;
4784 }
4785
4786 if (attachedShader != shaderObject)
4787 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004789 return false;
4790 }
4791
4792 return true;
4793}
4794
4795bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4796{
4797 if (index >= MAX_VERTEX_ATTRIBS)
4798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004799 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004800 return false;
4801 }
4802
4803 return true;
4804}
4805
4806bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4807{
4808 if (index >= MAX_VERTEX_ATTRIBS)
4809 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004810 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004811 return false;
4812 }
4813
4814 return true;
4815}
4816
4817bool ValidateFinish(ValidationContext *context)
4818{
4819 return true;
4820}
4821
4822bool ValidateFlush(ValidationContext *context)
4823{
4824 return true;
4825}
4826
4827bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4828{
4829 switch (mode)
4830 {
4831 case GL_CW:
4832 case GL_CCW:
4833 break;
4834 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004835 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004836 return false;
4837 }
4838
4839 return true;
4840}
4841
4842bool ValidateGetActiveAttrib(ValidationContext *context,
4843 GLuint program,
4844 GLuint index,
4845 GLsizei bufsize,
4846 GLsizei *length,
4847 GLint *size,
4848 GLenum *type,
4849 GLchar *name)
4850{
4851 if (bufsize < 0)
4852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004854 return false;
4855 }
4856
4857 Program *programObject = GetValidProgram(context, program);
4858
4859 if (!programObject)
4860 {
4861 return false;
4862 }
4863
4864 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004866 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004867 return false;
4868 }
4869
4870 return true;
4871}
4872
4873bool ValidateGetActiveUniform(ValidationContext *context,
4874 GLuint program,
4875 GLuint index,
4876 GLsizei bufsize,
4877 GLsizei *length,
4878 GLint *size,
4879 GLenum *type,
4880 GLchar *name)
4881{
4882 if (bufsize < 0)
4883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004884 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004885 return false;
4886 }
4887
4888 Program *programObject = GetValidProgram(context, program);
4889
4890 if (!programObject)
4891 {
4892 return false;
4893 }
4894
4895 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004897 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004898 return false;
4899 }
4900
4901 return true;
4902}
4903
4904bool ValidateGetAttachedShaders(ValidationContext *context,
4905 GLuint program,
4906 GLsizei maxcount,
4907 GLsizei *count,
4908 GLuint *shaders)
4909{
4910 if (maxcount < 0)
4911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004912 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004913 return false;
4914 }
4915
4916 Program *programObject = GetValidProgram(context, program);
4917
4918 if (!programObject)
4919 {
4920 return false;
4921 }
4922
4923 return true;
4924}
4925
4926bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4927{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004928 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4929 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04004930 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004933 return false;
4934 }
4935
Jamie Madillc1d770e2017-04-13 17:31:24 -04004936 Program *programObject = GetValidProgram(context, program);
4937
4938 if (!programObject)
4939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004941 return false;
4942 }
4943
4944 if (!programObject->isLinked())
4945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004947 return false;
4948 }
4949
4950 return true;
4951}
4952
4953bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4954{
4955 GLenum nativeType;
4956 unsigned int numParams = 0;
4957 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4958}
4959
4960bool ValidateGetError(ValidationContext *context)
4961{
4962 return true;
4963}
4964
4965bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4966{
4967 GLenum nativeType;
4968 unsigned int numParams = 0;
4969 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4970}
4971
4972bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4973{
4974 GLenum nativeType;
4975 unsigned int numParams = 0;
4976 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4977}
4978
4979bool ValidateGetProgramInfoLog(ValidationContext *context,
4980 GLuint program,
4981 GLsizei bufsize,
4982 GLsizei *length,
4983 GLchar *infolog)
4984{
4985 if (bufsize < 0)
4986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004987 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004988 return false;
4989 }
4990
4991 Program *programObject = GetValidProgram(context, program);
4992 if (!programObject)
4993 {
4994 return false;
4995 }
4996
4997 return true;
4998}
4999
5000bool ValidateGetShaderInfoLog(ValidationContext *context,
5001 GLuint shader,
5002 GLsizei bufsize,
5003 GLsizei *length,
5004 GLchar *infolog)
5005{
5006 if (bufsize < 0)
5007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005009 return false;
5010 }
5011
5012 Shader *shaderObject = GetValidShader(context, shader);
5013 if (!shaderObject)
5014 {
5015 return false;
5016 }
5017
5018 return true;
5019}
5020
5021bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
5022 GLenum shadertype,
5023 GLenum precisiontype,
5024 GLint *range,
5025 GLint *precision)
5026{
5027 switch (shadertype)
5028 {
5029 case GL_VERTEX_SHADER:
5030 case GL_FRAGMENT_SHADER:
5031 break;
5032 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005033 context->handleError(InvalidOperation()
5034 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005035 return false;
5036 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005037 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005038 return false;
5039 }
5040
5041 switch (precisiontype)
5042 {
5043 case GL_LOW_FLOAT:
5044 case GL_MEDIUM_FLOAT:
5045 case GL_HIGH_FLOAT:
5046 case GL_LOW_INT:
5047 case GL_MEDIUM_INT:
5048 case GL_HIGH_INT:
5049 break;
5050
5051 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005052 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005053 return false;
5054 }
5055
5056 return true;
5057}
5058
5059bool ValidateGetShaderSource(ValidationContext *context,
5060 GLuint shader,
5061 GLsizei bufsize,
5062 GLsizei *length,
5063 GLchar *source)
5064{
5065 if (bufsize < 0)
5066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005068 return false;
5069 }
5070
5071 Shader *shaderObject = GetValidShader(context, shader);
5072 if (!shaderObject)
5073 {
5074 return false;
5075 }
5076
5077 return true;
5078}
5079
5080bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
5081{
5082 if (strstr(name, "gl_") == name)
5083 {
5084 return false;
5085 }
5086
Geoff Langfc32e8b2017-05-31 14:16:59 -04005087 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5088 // shader-related entry points
Geoff Langcab92ee2017-07-19 17:32:07 -04005089 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005090 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005091 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005092 return false;
5093 }
5094
Jamie Madillc1d770e2017-04-13 17:31:24 -04005095 Program *programObject = GetValidProgram(context, program);
5096
5097 if (!programObject)
5098 {
5099 return false;
5100 }
5101
5102 if (!programObject->isLinked())
5103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005105 return false;
5106 }
5107
5108 return true;
5109}
5110
5111bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
5112{
5113 switch (mode)
5114 {
5115 case GL_FASTEST:
5116 case GL_NICEST:
5117 case GL_DONT_CARE:
5118 break;
5119
5120 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005122 return false;
5123 }
5124
5125 switch (target)
5126 {
5127 case GL_GENERATE_MIPMAP_HINT:
5128 break;
5129
Geoff Lange7bd2182017-06-16 16:13:13 -04005130 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5131 if (context->getClientVersion() < ES_3_0 &&
5132 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005134 context->handleError(InvalidOperation()
5135 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005136 return false;
5137 }
5138 break;
5139
5140 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005142 return false;
5143 }
5144
5145 return true;
5146}
5147
5148bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5149{
5150 return true;
5151}
5152
5153bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5154{
5155 return true;
5156}
5157
5158bool ValidateIsProgram(ValidationContext *context, GLuint program)
5159{
5160 return true;
5161}
5162
5163bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5164{
5165 return true;
5166}
5167
5168bool ValidateIsShader(ValidationContext *context, GLuint shader)
5169{
5170 return true;
5171}
5172
5173bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5174{
5175 return true;
5176}
5177
5178bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5179{
5180 if (context->getClientMajorVersion() < 3)
5181 {
5182 switch (pname)
5183 {
5184 case GL_UNPACK_IMAGE_HEIGHT:
5185 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005186 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005187 return false;
5188
5189 case GL_UNPACK_ROW_LENGTH:
5190 case GL_UNPACK_SKIP_ROWS:
5191 case GL_UNPACK_SKIP_PIXELS:
5192 if (!context->getExtensions().unpackSubimage)
5193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005194 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005195 return false;
5196 }
5197 break;
5198
5199 case GL_PACK_ROW_LENGTH:
5200 case GL_PACK_SKIP_ROWS:
5201 case GL_PACK_SKIP_PIXELS:
5202 if (!context->getExtensions().packSubimage)
5203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005204 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005205 return false;
5206 }
5207 break;
5208 }
5209 }
5210
5211 if (param < 0)
5212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005213 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005214 return false;
5215 }
5216
5217 switch (pname)
5218 {
5219 case GL_UNPACK_ALIGNMENT:
5220 if (param != 1 && param != 2 && param != 4 && param != 8)
5221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005223 return false;
5224 }
5225 break;
5226
5227 case GL_PACK_ALIGNMENT:
5228 if (param != 1 && param != 2 && param != 4 && param != 8)
5229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005230 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005231 return false;
5232 }
5233 break;
5234
5235 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5236 case GL_UNPACK_ROW_LENGTH:
5237 case GL_UNPACK_IMAGE_HEIGHT:
5238 case GL_UNPACK_SKIP_IMAGES:
5239 case GL_UNPACK_SKIP_ROWS:
5240 case GL_UNPACK_SKIP_PIXELS:
5241 case GL_PACK_ROW_LENGTH:
5242 case GL_PACK_SKIP_ROWS:
5243 case GL_PACK_SKIP_PIXELS:
5244 break;
5245
5246 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005248 return false;
5249 }
5250
5251 return true;
5252}
5253
5254bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5255{
5256 return true;
5257}
5258
5259bool ValidateReleaseShaderCompiler(ValidationContext *context)
5260{
5261 return true;
5262}
5263
Jamie Madill876429b2017-04-20 15:46:24 -04005264bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005265{
5266 return true;
5267}
5268
5269bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5270{
5271 if (width < 0 || height < 0)
5272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005273 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005274 return false;
5275 }
5276
5277 return true;
5278}
5279
5280bool ValidateShaderBinary(ValidationContext *context,
5281 GLsizei n,
5282 const GLuint *shaders,
5283 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005284 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005285 GLsizei length)
5286{
5287 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5288 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5289 shaderBinaryFormats.end())
5290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005291 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005292 return false;
5293 }
5294
5295 return true;
5296}
5297
5298bool ValidateShaderSource(ValidationContext *context,
5299 GLuint shader,
5300 GLsizei count,
5301 const GLchar *const *string,
5302 const GLint *length)
5303{
5304 if (count < 0)
5305 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005306 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005307 return false;
5308 }
5309
Geoff Langfc32e8b2017-05-31 14:16:59 -04005310 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5311 // shader-related entry points
5312 if (context->getExtensions().webglCompatibility)
5313 {
5314 for (GLsizei i = 0; i < count; i++)
5315 {
Geoff Langcab92ee2017-07-19 17:32:07 -04005316 size_t len =
5317 (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005318
5319 // Backslash as line-continuation is allowed in WebGL 2.0.
Geoff Langcab92ee2017-07-19 17:32:07 -04005320 if (!IsValidESSLShaderSourceString(string[i], len,
5321 context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005322 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005323 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005324 return false;
5325 }
5326 }
5327 }
5328
Jamie Madillc1d770e2017-04-13 17:31:24 -04005329 Shader *shaderObject = GetValidShader(context, shader);
5330 if (!shaderObject)
5331 {
5332 return false;
5333 }
5334
5335 return true;
5336}
5337
5338bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5339{
5340 if (!IsValidStencilFunc(func))
5341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005343 return false;
5344 }
5345
5346 return true;
5347}
5348
5349bool ValidateStencilFuncSeparate(ValidationContext *context,
5350 GLenum face,
5351 GLenum func,
5352 GLint ref,
5353 GLuint mask)
5354{
5355 if (!IsValidStencilFace(face))
5356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005358 return false;
5359 }
5360
5361 if (!IsValidStencilFunc(func))
5362 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005364 return false;
5365 }
5366
5367 return true;
5368}
5369
5370bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5371{
5372 return true;
5373}
5374
5375bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5376{
5377 if (!IsValidStencilFace(face))
5378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005379 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005380 return false;
5381 }
5382
5383 return true;
5384}
5385
5386bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5387{
5388 if (!IsValidStencilOp(fail))
5389 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005390 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005391 return false;
5392 }
5393
5394 if (!IsValidStencilOp(zfail))
5395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005397 return false;
5398 }
5399
5400 if (!IsValidStencilOp(zpass))
5401 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005402 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005403 return false;
5404 }
5405
5406 return true;
5407}
5408
5409bool ValidateStencilOpSeparate(ValidationContext *context,
5410 GLenum face,
5411 GLenum fail,
5412 GLenum zfail,
5413 GLenum zpass)
5414{
5415 if (!IsValidStencilFace(face))
5416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005417 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005418 return false;
5419 }
5420
5421 return ValidateStencilOp(context, fail, zfail, zpass);
5422}
5423
5424bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5425{
5426 return ValidateUniform(context, GL_FLOAT, location, 1);
5427}
5428
5429bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5430{
5431 return ValidateUniform(context, GL_FLOAT, location, count);
5432}
5433
Jamie Madillbe849e42017-05-02 15:49:00 -04005434bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5435{
5436 return ValidateUniform1iv(context, location, 1, &x);
5437}
5438
Jamie Madillc1d770e2017-04-13 17:31:24 -04005439bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5440{
5441 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5442}
5443
5444bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5445{
5446 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5447}
5448
5449bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5450{
5451 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5452}
5453
5454bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5455{
5456 return ValidateUniform(context, GL_INT_VEC2, location, count);
5457}
5458
5459bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5460{
5461 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5462}
5463
5464bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5465{
5466 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5467}
5468
5469bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5470{
5471 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5472}
5473
5474bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5475{
5476 return ValidateUniform(context, GL_INT_VEC3, location, count);
5477}
5478
5479bool ValidateUniform4f(ValidationContext *context,
5480 GLint location,
5481 GLfloat x,
5482 GLfloat y,
5483 GLfloat z,
5484 GLfloat w)
5485{
5486 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5487}
5488
5489bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5490{
5491 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5492}
5493
5494bool ValidateUniform4i(ValidationContext *context,
5495 GLint location,
5496 GLint x,
5497 GLint y,
5498 GLint z,
5499 GLint w)
5500{
5501 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5502}
5503
5504bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5505{
5506 return ValidateUniform(context, GL_INT_VEC4, location, count);
5507}
5508
5509bool ValidateUniformMatrix2fv(ValidationContext *context,
5510 GLint location,
5511 GLsizei count,
5512 GLboolean transpose,
5513 const GLfloat *value)
5514{
5515 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5516}
5517
5518bool ValidateUniformMatrix3fv(ValidationContext *context,
5519 GLint location,
5520 GLsizei count,
5521 GLboolean transpose,
5522 const GLfloat *value)
5523{
5524 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5525}
5526
5527bool ValidateUniformMatrix4fv(ValidationContext *context,
5528 GLint location,
5529 GLsizei count,
5530 GLboolean transpose,
5531 const GLfloat *value)
5532{
5533 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5534}
5535
5536bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5537{
5538 Program *programObject = GetValidProgram(context, program);
5539
5540 if (!programObject)
5541 {
5542 return false;
5543 }
5544
5545 return true;
5546}
5547
5548bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5549{
5550 if (index >= MAX_VERTEX_ATTRIBS)
5551 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005552 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005553 return false;
5554 }
5555
5556 return true;
5557}
5558
5559bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5560{
5561 return ValidateVertexAttribIndex(context, index);
5562}
5563
5564bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5565{
5566 return ValidateVertexAttribIndex(context, index);
5567}
5568
5569bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5570{
5571 return ValidateVertexAttribIndex(context, index);
5572}
5573
5574bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5575{
5576 return ValidateVertexAttribIndex(context, index);
5577}
5578
5579bool ValidateVertexAttrib3f(ValidationContext *context,
5580 GLuint index,
5581 GLfloat x,
5582 GLfloat y,
5583 GLfloat z)
5584{
5585 return ValidateVertexAttribIndex(context, index);
5586}
5587
5588bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5589{
5590 return ValidateVertexAttribIndex(context, index);
5591}
5592
5593bool ValidateVertexAttrib4f(ValidationContext *context,
5594 GLuint index,
5595 GLfloat x,
5596 GLfloat y,
5597 GLfloat z,
5598 GLfloat w)
5599{
5600 return ValidateVertexAttribIndex(context, index);
5601}
5602
5603bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5604{
5605 return ValidateVertexAttribIndex(context, index);
5606}
5607
5608bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5609{
5610 if (width < 0 || height < 0)
5611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005612 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005613 return false;
5614 }
5615
5616 return true;
5617}
5618
5619bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5620{
5621 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5622}
5623
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005624bool ValidateDrawElements(ValidationContext *context,
5625 GLenum mode,
5626 GLsizei count,
5627 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005628 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005629{
5630 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5631}
5632
Jamie Madillbe849e42017-05-02 15:49:00 -04005633bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5634 GLenum target,
5635 GLenum attachment,
5636 GLenum pname,
5637 GLint *params)
5638{
5639 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5640 nullptr);
5641}
5642
5643bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5644{
5645 return ValidateGetProgramivBase(context, program, pname, nullptr);
5646}
5647
5648bool ValidateCopyTexImage2D(ValidationContext *context,
5649 GLenum target,
5650 GLint level,
5651 GLenum internalformat,
5652 GLint x,
5653 GLint y,
5654 GLsizei width,
5655 GLsizei height,
5656 GLint border)
5657{
5658 if (context->getClientMajorVersion() < 3)
5659 {
5660 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5661 0, x, y, width, height, border);
5662 }
5663
5664 ASSERT(context->getClientMajorVersion() == 3);
5665 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5666 0, x, y, width, height, border);
5667}
5668
5669bool ValidateCopyTexSubImage2D(Context *context,
5670 GLenum target,
5671 GLint level,
5672 GLint xoffset,
5673 GLint yoffset,
5674 GLint x,
5675 GLint y,
5676 GLsizei width,
5677 GLsizei height)
5678{
5679 if (context->getClientMajorVersion() < 3)
5680 {
5681 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5682 yoffset, x, y, width, height, 0);
5683 }
5684
5685 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5686 yoffset, 0, x, y, width, height, 0);
5687}
5688
5689bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5690{
5691 return ValidateGenOrDelete(context, n);
5692}
5693
5694bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5695{
5696 return ValidateGenOrDelete(context, n);
5697}
5698
5699bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5700{
5701 return ValidateGenOrDelete(context, n);
5702}
5703
5704bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5705{
5706 return ValidateGenOrDelete(context, n);
5707}
5708
5709bool ValidateDisable(Context *context, GLenum cap)
5710{
5711 if (!ValidCap(context, cap, false))
5712 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005713 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005714 return false;
5715 }
5716
5717 return true;
5718}
5719
5720bool ValidateEnable(Context *context, GLenum cap)
5721{
5722 if (!ValidCap(context, cap, false))
5723 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005724 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005725 return false;
5726 }
5727
5728 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5729 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5730 {
5731 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005732 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005733
5734 // We also output an error message to the debugger window if tracing is active, so that
5735 // developers can see the error message.
5736 ERR() << errorMessage;
5737 return false;
5738 }
5739
5740 return true;
5741}
5742
5743bool ValidateFramebufferRenderbuffer(Context *context,
5744 GLenum target,
5745 GLenum attachment,
5746 GLenum renderbuffertarget,
5747 GLuint renderbuffer)
5748{
Brandon Jones6cad5662017-06-14 13:25:13 -07005749 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5752 return false;
5753 }
5754
5755 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5756 {
5757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 return false;
5759 }
5760
5761 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5762 renderbuffertarget, renderbuffer);
5763}
5764
5765bool ValidateFramebufferTexture2D(Context *context,
5766 GLenum target,
5767 GLenum attachment,
5768 GLenum textarget,
5769 GLuint texture,
5770 GLint level)
5771{
5772 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5773 // extension
5774 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5775 level != 0)
5776 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005777 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 return false;
5779 }
5780
5781 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5782 {
5783 return false;
5784 }
5785
5786 if (texture != 0)
5787 {
5788 gl::Texture *tex = context->getTexture(texture);
5789 ASSERT(tex);
5790
5791 const gl::Caps &caps = context->getCaps();
5792
5793 switch (textarget)
5794 {
5795 case GL_TEXTURE_2D:
5796 {
5797 if (level > gl::log2(caps.max2DTextureSize))
5798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005799 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005800 return false;
5801 }
5802 if (tex->getTarget() != GL_TEXTURE_2D)
5803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807 }
5808 break;
5809
5810 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5811 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5812 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5813 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5814 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5815 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5816 {
5817 if (level > gl::log2(caps.maxCubeMapTextureSize))
5818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005819 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 return false;
5821 }
5822 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005824 context->handleError(InvalidOperation()
5825 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005826 return false;
5827 }
5828 }
5829 break;
5830
5831 case GL_TEXTURE_2D_MULTISAMPLE:
5832 {
5833 if (context->getClientVersion() < ES_3_1)
5834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005835 context->handleError(InvalidOperation()
5836 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005837 return false;
5838 }
5839
5840 if (level != 0)
5841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005842 context->handleError(InvalidValue()
5843 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005844 return false;
5845 }
5846 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005848 context->handleError(InvalidOperation()
5849 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 return false;
5851 }
5852 }
5853 break;
5854
5855 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005857 return false;
5858 }
5859
5860 const Format &format = tex->getFormat(textarget, level);
5861 if (format.info->compressed)
5862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005863 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005864 return false;
5865 }
5866 }
5867
5868 return true;
5869}
5870
5871bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5872{
5873 return ValidateGenOrDelete(context, n);
5874}
5875
5876bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5877{
5878 return ValidateGenOrDelete(context, n);
5879}
5880
5881bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5882{
5883 return ValidateGenOrDelete(context, n);
5884}
5885
5886bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5887{
5888 return ValidateGenOrDelete(context, n);
5889}
5890
5891bool ValidateGenerateMipmap(Context *context, GLenum target)
5892{
5893 if (!ValidTextureTarget(context, target))
5894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005896 return false;
5897 }
5898
5899 Texture *texture = context->getTargetTexture(target);
5900
5901 if (texture == nullptr)
5902 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005904 return false;
5905 }
5906
5907 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5908
5909 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5910 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5911 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005913 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005914 return false;
5915 }
5916
5917 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5918 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5919 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5920
Brandon Jones6cad5662017-06-14 13:25:13 -07005921 if (format.info->compressed)
5922 {
5923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
5924 return false;
5925 }
5926
Jamie Madillbe849e42017-05-02 15:49:00 -04005927 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
Brandon Jones6cad5662017-06-14 13:25:13 -07005928 // unsized formats or that are color renderable and filterable. Since we do not track if
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 // the texture was created with sized or unsized format (only sized formats are stored),
5930 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5931 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5932 // textures since they're the only texture format that can be created with unsized formats
5933 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5934 // was the last version to use add them.
5935 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
Brandon Jones6cad5662017-06-14 13:25:13 -07005936 (!formatCaps.renderable && !format.info->isLUMA()))
Jamie Madillbe849e42017-05-02 15:49:00 -04005937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005938 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 return false;
5940 }
5941
Geoff Lang65ac5b92017-05-01 13:16:30 -04005942 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5943 bool supportsSRGBMipmapGeneration =
5944 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5945 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005947 context->handleError(InvalidOperation()
5948 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005949 return false;
5950 }
5951
5952 // Non-power of 2 ES2 check
5953 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5954 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5955 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5956 {
5957 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07005958 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04005959 return false;
5960 }
5961
5962 // Cube completeness check
5963 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04005966 return false;
5967 }
5968
5969 return true;
5970}
5971
5972bool ValidateGetBufferParameteriv(ValidationContext *context,
5973 GLenum target,
5974 GLenum pname,
5975 GLint *params)
5976{
5977 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5978}
5979
5980bool ValidateGetRenderbufferParameteriv(Context *context,
5981 GLenum target,
5982 GLenum pname,
5983 GLint *params)
5984{
5985 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5986}
5987
5988bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5989{
5990 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5991}
5992
5993bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5994{
5995 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5996}
5997
5998bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5999{
6000 return ValidateGetTexParameterBase(context, target, pname, nullptr);
6001}
6002
6003bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
6004{
6005 return ValidateGetUniformBase(context, program, location);
6006}
6007
6008bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
6009{
6010 return ValidateGetUniformBase(context, program, location);
6011}
6012
6013bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6014{
6015 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6016}
6017
6018bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6019{
6020 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6021}
6022
6023bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6024{
6025 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6026}
6027
6028bool ValidateIsEnabled(Context *context, GLenum cap)
6029{
6030 if (!ValidCap(context, cap, true))
6031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006032 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006033 return false;
6034 }
6035
6036 return true;
6037}
6038
6039bool ValidateLinkProgram(Context *context, GLuint program)
6040{
6041 if (context->hasActiveTransformFeedback(program))
6042 {
6043 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006044 context->handleError(InvalidOperation() << "Cannot link program while program is "
6045 "associated with an active transform "
6046 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006047 return false;
6048 }
6049
6050 Program *programObject = GetValidProgram(context, program);
6051 if (!programObject)
6052 {
6053 return false;
6054 }
6055
6056 return true;
6057}
6058
Jamie Madill4928b7c2017-06-20 12:57:39 -04006059bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04006060 GLint x,
6061 GLint y,
6062 GLsizei width,
6063 GLsizei height,
6064 GLenum format,
6065 GLenum type,
6066 void *pixels)
6067{
6068 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
6069 nullptr, pixels);
6070}
6071
6072bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
6073{
6074 return ValidateTexParameterBase(context, target, pname, -1, &param);
6075}
6076
6077bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
6078{
6079 return ValidateTexParameterBase(context, target, pname, -1, params);
6080}
6081
6082bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
6083{
6084 return ValidateTexParameterBase(context, target, pname, -1, &param);
6085}
6086
6087bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
6088{
6089 return ValidateTexParameterBase(context, target, pname, -1, params);
6090}
6091
6092bool ValidateUseProgram(Context *context, GLuint program)
6093{
6094 if (program != 0)
6095 {
6096 Program *programObject = context->getProgram(program);
6097 if (!programObject)
6098 {
6099 // ES 3.1.0 section 7.3 page 72
6100 if (context->getShader(program))
6101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006103 return false;
6104 }
6105 else
6106 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006107 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04006108 return false;
6109 }
6110 }
6111 if (!programObject->isLinked())
6112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04006114 return false;
6115 }
6116 }
6117 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6118 {
6119 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006120 context
6121 ->handleError(InvalidOperation()
6122 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006123 return false;
6124 }
6125
6126 return true;
6127}
6128
Jamie Madillc29968b2016-01-20 11:17:23 -05006129} // namespace gl