blob: 9907e2a4191b9e2ae3606b92d6b58f56c93f454b [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:
271 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700272
273 default:
274 return false;
275 }
276}
277
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400278bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
279{
280 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
281}
282
Geoff Lang97073d12016-04-20 10:42:34 -0700283bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
284{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400285 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700286 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400287 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700288 }
289
Geoff Lang4f0e0032017-05-01 16:04:35 -0400290 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
291 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700292 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400293 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700294 }
295
296 return true;
297}
298
Geoff Lang4f0e0032017-05-01 16:04:35 -0400299bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700300{
301 switch (target)
302 {
303 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400304 return textureType == GL_TEXTURE_2D;
305
306 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
307 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
308 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
309 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
310 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
311 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
312 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700313
314 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
315 // supported
316
317 default:
318 return false;
319 }
320}
321
322bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
323{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400324 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700325 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400326 case GL_TEXTURE_2D:
327 return true;
328
329 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
330 // supported
331
332 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
333 // supported
334
335 default:
336 return false;
337 }
338}
339
340bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
341{
342 if (level < 0)
343 {
344 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700345 }
346
Geoff Lang4f0e0032017-05-01 16:04:35 -0400347 if (level > 0 && context->getClientVersion() < ES_3_0)
348 {
349 return false;
350 }
Geoff Lang97073d12016-04-20 10:42:34 -0700351
Geoff Lang4f0e0032017-05-01 16:04:35 -0400352 return true;
353}
354
355bool IsValidCopyTextureDestinationLevel(Context *context,
356 GLenum target,
357 GLint level,
358 GLsizei width,
359 GLsizei height)
360{
361 if (level < 0)
362 {
363 return false;
364 }
365
Geoff Lang4f0e0032017-05-01 16:04:35 -0400366 const Caps &caps = context->getCaps();
367 if (target == GL_TEXTURE_2D)
368 {
369 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
370 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
371 {
372 return false;
373 }
374 }
375 else if (IsCubeMapTextureTarget(target))
376 {
377 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
378 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
379 {
380 return false;
381 }
382 }
383
384 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700385}
386
Jamie Madillc1d770e2017-04-13 17:31:24 -0400387bool IsValidStencilFunc(GLenum func)
388{
389 switch (func)
390 {
391 case GL_NEVER:
392 case GL_ALWAYS:
393 case GL_LESS:
394 case GL_LEQUAL:
395 case GL_EQUAL:
396 case GL_GEQUAL:
397 case GL_GREATER:
398 case GL_NOTEQUAL:
399 return true;
400
401 default:
402 return false;
403 }
404}
405
406bool IsValidStencilFace(GLenum face)
407{
408 switch (face)
409 {
410 case GL_FRONT:
411 case GL_BACK:
412 case GL_FRONT_AND_BACK:
413 return true;
414
415 default:
416 return false;
417 }
418}
419
420bool IsValidStencilOp(GLenum op)
421{
422 switch (op)
423 {
424 case GL_ZERO:
425 case GL_KEEP:
426 case GL_REPLACE:
427 case GL_INCR:
428 case GL_DECR:
429 case GL_INVERT:
430 case GL_INCR_WRAP:
431 case GL_DECR_WRAP:
432 return true;
433
434 default:
435 return false;
436 }
437}
438
Jamie Madillbe849e42017-05-02 15:49:00 -0400439bool ValidateES2CopyTexImageParameters(ValidationContext *context,
440 GLenum target,
441 GLint level,
442 GLenum internalformat,
443 bool isSubImage,
444 GLint xoffset,
445 GLint yoffset,
446 GLint x,
447 GLint y,
448 GLsizei width,
449 GLsizei height,
450 GLint border)
451{
452 if (!ValidTexture2DDestinationTarget(context, target))
453 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400455 return false;
456 }
457
458 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500460 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400461 return false;
462 }
463
464 Format textureFormat = Format::Invalid();
465 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
466 xoffset, yoffset, 0, x, y, width, height, border,
467 &textureFormat))
468 {
469 return false;
470 }
471
472 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
473 GLenum colorbufferFormat =
474 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
475 const auto &formatInfo = *textureFormat.info;
476
477 // [OpenGL ES 2.0.24] table 3.9
478 if (isSubImage)
479 {
480 switch (formatInfo.format)
481 {
482 case GL_ALPHA:
483 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400484 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
485 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400486 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400488 return false;
489 }
490 break;
491 case GL_LUMINANCE:
492 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
493 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
494 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400495 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
496 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400497 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700498 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400499 return false;
500 }
501 break;
502 case GL_RED_EXT:
503 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
504 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
505 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
506 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
507 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400508 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
509 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400510 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700511 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400512 return false;
513 }
514 break;
515 case GL_RG_EXT:
516 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
517 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
518 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
519 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400520 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
521 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400522 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400524 return false;
525 }
526 break;
527 case GL_RGB:
528 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
529 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
530 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400531 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
532 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400533 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700534 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400535 return false;
536 }
537 break;
538 case GL_LUMINANCE_ALPHA:
539 case GL_RGBA:
540 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400541 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
542 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400543 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700544 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400545 return false;
546 }
547 break;
548 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
549 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
550 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
551 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
552 case GL_ETC1_RGB8_OES:
553 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
554 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
555 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
556 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
557 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400559 return false;
560 case GL_DEPTH_COMPONENT:
561 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400563 return false;
564 default:
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 }
568
569 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
570 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700571 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400572 return false;
573 }
574 }
575 else
576 {
577 switch (internalformat)
578 {
579 case GL_ALPHA:
580 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
581 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
582 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
583 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700584 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400585 return false;
586 }
587 break;
588 case GL_LUMINANCE:
589 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
590 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
591 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
592 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
593 colorbufferFormat != GL_BGR5_A1_ANGLEX)
594 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400596 return false;
597 }
598 break;
599 case GL_RED_EXT:
600 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
601 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
602 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
603 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
604 colorbufferFormat != GL_BGR5_A1_ANGLEX)
605 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700606 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400607 return false;
608 }
609 break;
610 case GL_RG_EXT:
611 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
612 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
613 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
614 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
615 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400617 return false;
618 }
619 break;
620 case GL_RGB:
621 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
622 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
623 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
624 colorbufferFormat != GL_BGR5_A1_ANGLEX)
625 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400627 return false;
628 }
629 break;
630 case GL_LUMINANCE_ALPHA:
631 case GL_RGBA:
632 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
633 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
634 colorbufferFormat != GL_BGR5_A1_ANGLEX)
635 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400637 return false;
638 }
639 break;
640 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
641 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
642 if (context->getExtensions().textureCompressionDXT1)
643 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400645 return false;
646 }
647 else
648 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400650 return false;
651 }
652 break;
653 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
654 if (context->getExtensions().textureCompressionDXT3)
655 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400657 return false;
658 }
659 else
660 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400662 return false;
663 }
664 break;
665 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
666 if (context->getExtensions().textureCompressionDXT5)
667 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400669 return false;
670 }
671 else
672 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700673 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400674 return false;
675 }
676 break;
677 case GL_ETC1_RGB8_OES:
678 if (context->getExtensions().compressedETC1RGB8Texture)
679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500680 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400681 return false;
682 }
683 else
684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500685 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400686 return false;
687 }
688 break;
689 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
690 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
691 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
692 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
693 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
694 if (context->getExtensions().lossyETCDecode)
695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500696 context->handleError(InvalidOperation()
697 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400698 return false;
699 }
700 else
701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500702 context->handleError(InvalidEnum()
703 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400704 return false;
705 }
706 break;
707 case GL_DEPTH_COMPONENT:
708 case GL_DEPTH_COMPONENT16:
709 case GL_DEPTH_COMPONENT32_OES:
710 case GL_DEPTH_STENCIL_OES:
711 case GL_DEPTH24_STENCIL8_OES:
712 if (context->getExtensions().depthTextures)
713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500714 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400715 return false;
716 }
717 else
718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500719 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400720 return false;
721 }
722 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500723 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400724 return false;
725 }
726 }
727
728 // If width or height is zero, it is a no-op. Return false without setting an error.
729 return (width > 0 && height > 0);
730}
731
732bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
733{
734 switch (cap)
735 {
736 // EXT_multisample_compatibility
737 case GL_MULTISAMPLE_EXT:
738 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
739 return context->getExtensions().multisampleCompatibility;
740
741 case GL_CULL_FACE:
742 case GL_POLYGON_OFFSET_FILL:
743 case GL_SAMPLE_ALPHA_TO_COVERAGE:
744 case GL_SAMPLE_COVERAGE:
745 case GL_SCISSOR_TEST:
746 case GL_STENCIL_TEST:
747 case GL_DEPTH_TEST:
748 case GL_BLEND:
749 case GL_DITHER:
750 return true;
751
752 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
753 case GL_RASTERIZER_DISCARD:
754 return (context->getClientMajorVersion() >= 3);
755
756 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
757 case GL_DEBUG_OUTPUT:
758 return context->getExtensions().debug;
759
760 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
761 return queryOnly && context->getExtensions().bindGeneratesResource;
762
763 case GL_CLIENT_ARRAYS_ANGLE:
764 return queryOnly && context->getExtensions().clientArrays;
765
766 case GL_FRAMEBUFFER_SRGB_EXT:
767 return context->getExtensions().sRGBWriteControl;
768
769 case GL_SAMPLE_MASK:
770 return context->getClientVersion() >= Version(3, 1);
771
772 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
773 return queryOnly && context->getExtensions().robustResourceInitialization;
774
775 default:
776 return false;
777 }
778}
779
Geoff Langfc32e8b2017-05-31 14:16:59 -0400780// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
781// 3.1.
Geoff Langa71a98e2017-06-19 15:15:00 -0400782bool IsValidESSLCharacter(unsigned char c, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400783{
784 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langa71a98e2017-06-19 15:15:00 -0400785 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' &&
786 (allowBackslash || c != '\\') && c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400787 {
788 return true;
789 }
790
791 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
792 if (c >= 9 && c <= 13)
793 {
794 return true;
795 }
796
797 return false;
798}
799
Geoff Langa71a98e2017-06-19 15:15:00 -0400800bool IsValidESSLString(const char *str, size_t len, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400801{
Geoff Langa71a98e2017-06-19 15:15:00 -0400802 for (size_t i = 0; i < len; i++)
803 {
804 if (!IsValidESSLCharacter(str[i], allowBackslash))
805 {
806 return false;
807 }
808 }
809
810 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400811}
812
Jamie Madillc29968b2016-01-20 11:17:23 -0500813} // anonymous namespace
814
Geoff Langff5b2d52016-09-07 11:32:23 -0400815bool ValidateES2TexImageParameters(Context *context,
816 GLenum target,
817 GLint level,
818 GLenum internalformat,
819 bool isCompressed,
820 bool isSubImage,
821 GLint xoffset,
822 GLint yoffset,
823 GLsizei width,
824 GLsizei height,
825 GLint border,
826 GLenum format,
827 GLenum type,
828 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400829 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830{
Jamie Madill6f38f822014-06-06 17:12:20 -0400831 if (!ValidTexture2DDestinationTarget(context, target))
832 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -0400834 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400835 }
836
Austin Kinross08528e12015-10-07 16:24:40 -0700837 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500839 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 }
842
Brandon Jones6cad5662017-06-14 13:25:13 -0700843 if (!ValidMipLevel(context, target, level))
844 {
845 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
846 return false;
847 }
848
849 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 std::numeric_limits<GLsizei>::max() - yoffset < height)
851 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700852 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -0400853 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400854 }
855
Geoff Lang6e898aa2017-06-02 11:17:26 -0400856 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
857 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
858 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
859 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
860 // case.
861 bool nonEqualFormatsAllowed =
862 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
863 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
864
865 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500867 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400868 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 }
870
Geoff Langaae65a42014-05-26 12:43:44 -0400871 const gl::Caps &caps = context->getCaps();
872
Geoff Langa9be0dc2014-12-17 12:34:40 -0500873 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500875 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
876 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500879 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400880 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500881 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500882 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500883 {
884 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400885 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700886 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500887 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400888 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400889
Geoff Langa9be0dc2014-12-17 12:34:40 -0500890 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
891 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500893 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500894 return false;
895 }
896 }
897 else
898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500899 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400900 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901 }
902
He Yunchaoced53ae2016-11-29 15:00:51 +0800903 gl::Texture *texture =
904 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905 if (!texture)
906 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -0400908 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 }
910
Geoff Langa9be0dc2014-12-17 12:34:40 -0500911 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 {
Geoff Langca271392017-04-05 12:30:00 -0400913 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
914 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500917 return false;
918 }
919
Geoff Langa9be0dc2014-12-17 12:34:40 -0500920 if (format != GL_NONE)
921 {
Geoff Langca271392017-04-05 12:30:00 -0400922 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
923 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500924 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500926 return false;
927 }
928 }
929
930 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
931 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500933 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500934 return false;
935 }
936 }
937 else
938 {
Geoff Lang69cce582015-09-17 13:20:36 -0400939 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500942 return false;
943 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944 }
945
946 // Verify zero border
947 if (border != 0)
948 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700949 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 if (isCompressed)
954 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400955 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400956 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
957 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 switch (actualInternalFormat)
959 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800960 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
961 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
962 if (!context->getExtensions().textureCompressionDXT1)
963 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800965 return false;
966 }
967 break;
968 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
969 if (!context->getExtensions().textureCompressionDXT1)
970 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800972 return false;
973 }
974 break;
975 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
976 if (!context->getExtensions().textureCompressionDXT5)
977 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800979 return false;
980 }
981 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800982 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
983 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
984 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
985 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
986 if (!context->getExtensions().textureCompressionS3TCsRGB)
987 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700988 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800989 return false;
990 }
991 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 case GL_ETC1_RGB8_OES:
993 if (!context->getExtensions().compressedETC1RGB8Texture)
994 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700995 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 return false;
997 }
998 break;
999 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001000 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1001 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1002 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1003 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001004 if (!context->getExtensions().lossyETCDecode)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidEnum()
1007 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001008 return false;
1009 }
1010 break;
1011 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001012 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001013 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001014 }
Geoff Lang966c9402017-04-18 12:38:27 -04001015
1016 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001017 {
Geoff Lang966c9402017-04-18 12:38:27 -04001018 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1019 height, texture->getWidth(target, level),
1020 texture->getHeight(target, level)))
1021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001022 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001023 return false;
1024 }
1025
1026 if (format != actualInternalFormat)
1027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001029 return false;
1030 }
1031 }
1032 else
1033 {
1034 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001036 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001037 return false;
1038 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 }
1040 }
1041 else
1042 {
1043 // validate <type> by itself (used as secondary key below)
1044 switch (type)
1045 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001046 case GL_UNSIGNED_BYTE:
1047 case GL_UNSIGNED_SHORT_5_6_5:
1048 case GL_UNSIGNED_SHORT_4_4_4_4:
1049 case GL_UNSIGNED_SHORT_5_5_5_1:
1050 case GL_UNSIGNED_SHORT:
1051 case GL_UNSIGNED_INT:
1052 case GL_UNSIGNED_INT_24_8_OES:
1053 case GL_HALF_FLOAT_OES:
1054 case GL_FLOAT:
1055 break;
1056 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001057 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 }
1060
1061 // validate <format> + <type> combinations
1062 // - invalid <format> -> sets INVALID_ENUM
1063 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1064 switch (format)
1065 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001066 case GL_ALPHA:
1067 case GL_LUMINANCE:
1068 case GL_LUMINANCE_ALPHA:
1069 switch (type)
1070 {
1071 case GL_UNSIGNED_BYTE:
1072 case GL_FLOAT:
1073 case GL_HALF_FLOAT_OES:
1074 break;
1075 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001080 case GL_RED:
1081 case GL_RG:
1082 if (!context->getExtensions().textureRG)
1083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001084 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001085 return false;
1086 }
1087 switch (type)
1088 {
1089 case GL_UNSIGNED_BYTE:
1090 case GL_FLOAT:
1091 case GL_HALF_FLOAT_OES:
1092 break;
1093 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 return false;
1096 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 case GL_RGB:
1099 switch (type)
1100 {
1101 case GL_UNSIGNED_BYTE:
1102 case GL_UNSIGNED_SHORT_5_6_5:
1103 case GL_FLOAT:
1104 case GL_HALF_FLOAT_OES:
1105 break;
1106 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001107 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001108 return false;
1109 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 case GL_RGBA:
1112 switch (type)
1113 {
1114 case GL_UNSIGNED_BYTE:
1115 case GL_UNSIGNED_SHORT_4_4_4_4:
1116 case GL_UNSIGNED_SHORT_5_5_5_1:
1117 case GL_FLOAT:
1118 case GL_HALF_FLOAT_OES:
1119 break;
1120 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001122 return false;
1123 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001125 case GL_BGRA_EXT:
1126 switch (type)
1127 {
1128 case GL_UNSIGNED_BYTE:
1129 break;
1130 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001132 return false;
1133 }
1134 break;
1135 case GL_SRGB_EXT:
1136 case GL_SRGB_ALPHA_EXT:
1137 if (!context->getExtensions().sRGB)
1138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001139 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
1141 }
1142 switch (type)
1143 {
1144 case GL_UNSIGNED_BYTE:
1145 break;
1146 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001148 return false;
1149 }
1150 break;
1151 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1152 // handled below
1153 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1154 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1155 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1156 break;
1157 case GL_DEPTH_COMPONENT:
1158 switch (type)
1159 {
1160 case GL_UNSIGNED_SHORT:
1161 case GL_UNSIGNED_INT:
1162 break;
1163 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001165 return false;
1166 }
1167 break;
1168 case GL_DEPTH_STENCIL_OES:
1169 switch (type)
1170 {
1171 case GL_UNSIGNED_INT_24_8_OES:
1172 break;
1173 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001174 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001175 return false;
1176 }
1177 break;
1178 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001179 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 }
1182
1183 switch (format)
1184 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001185 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1186 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1187 if (context->getExtensions().textureCompressionDXT1)
1188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001189 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 return false;
1191 }
1192 else
1193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001194 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001195 return false;
1196 }
1197 break;
1198 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1199 if (context->getExtensions().textureCompressionDXT3)
1200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001201 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 return false;
1203 }
1204 else
1205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001206 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001207 return false;
1208 }
1209 break;
1210 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1211 if (context->getExtensions().textureCompressionDXT5)
1212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001213 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 return false;
1215 }
1216 else
1217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001218 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001219 return false;
1220 }
1221 break;
1222 case GL_ETC1_RGB8_OES:
1223 if (context->getExtensions().compressedETC1RGB8Texture)
1224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001225 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001226 return false;
1227 }
1228 else
1229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001231 return false;
1232 }
1233 break;
1234 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001235 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1236 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1237 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1238 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001239 if (context->getExtensions().lossyETCDecode)
1240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001241 context->handleError(InvalidOperation()
1242 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001243 return false;
1244 }
1245 else
1246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidEnum()
1248 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001249 return false;
1250 }
1251 break;
1252 case GL_DEPTH_COMPONENT:
1253 case GL_DEPTH_STENCIL_OES:
1254 if (!context->getExtensions().depthTextures)
1255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001256 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001257 return false;
1258 }
1259 if (target != GL_TEXTURE_2D)
1260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001262 return false;
1263 }
1264 // OES_depth_texture supports loading depth data and multiple levels,
1265 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001266 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001268 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001269 return false;
1270 }
1271 break;
1272 default:
1273 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 }
1275
Geoff Lang6e898aa2017-06-02 11:17:26 -04001276 if (!isSubImage)
1277 {
1278 switch (internalformat)
1279 {
1280 case GL_RGBA32F:
1281 if (!context->getExtensions().colorBufferFloatRGBA)
1282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001283 context->handleError(InvalidValue()
1284 << "Sized GL_RGBA32F internal format requires "
1285 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001286 return false;
1287 }
1288 if (type != GL_FLOAT)
1289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001291 return false;
1292 }
1293 if (format != GL_RGBA)
1294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001296 return false;
1297 }
1298 break;
1299
1300 case GL_RGB32F:
1301 if (!context->getExtensions().colorBufferFloatRGB)
1302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 context->handleError(InvalidValue()
1304 << "Sized GL_RGB32F internal format requires "
1305 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001306 return false;
1307 }
1308 if (type != GL_FLOAT)
1309 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001310 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001311 return false;
1312 }
1313 if (format != GL_RGB)
1314 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001315 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001316 return false;
1317 }
1318 break;
1319
1320 default:
1321 break;
1322 }
1323 }
1324
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 if (type == GL_FLOAT)
1326 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001327 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001329 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001330 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 }
1332 }
1333 else if (type == GL_HALF_FLOAT_OES)
1334 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001335 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 }
1340 }
1341 }
1342
Geoff Langdbcced82017-06-06 15:55:54 -04001343 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1344 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001345 imageSize))
1346 {
1347 return false;
1348 }
1349
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 return true;
1351}
1352
He Yunchaoced53ae2016-11-29 15:00:51 +08001353bool ValidateES2TexStorageParameters(Context *context,
1354 GLenum target,
1355 GLsizei levels,
1356 GLenum internalformat,
1357 GLsizei width,
1358 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359{
1360 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001362 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 }
1365
1366 if (width < 1 || height < 1 || levels < 1)
1367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
1371
1372 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 }
1377
1378 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001380 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001381 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 }
1383
Geoff Langca271392017-04-05 12:30:00 -04001384 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001385 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001388 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390
Geoff Langaae65a42014-05-26 12:43:44 -04001391 const gl::Caps &caps = context->getCaps();
1392
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 switch (target)
1394 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001395 case GL_TEXTURE_2D:
1396 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1397 static_cast<GLuint>(height) > caps.max2DTextureSize)
1398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 return false;
1401 }
1402 break;
1403 case GL_TEXTURE_CUBE_MAP:
1404 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1405 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 return false;
1409 }
1410 break;
1411 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 }
1415
Geoff Langc0b9ef42014-07-02 10:02:37 -04001416 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
1418 if (!gl::isPow2(width) || !gl::isPow2(height))
1419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001420 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423 }
1424
1425 switch (internalformat)
1426 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001427 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1428 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1429 if (!context->getExtensions().textureCompressionDXT1)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001432 return false;
1433 }
1434 break;
1435 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1436 if (!context->getExtensions().textureCompressionDXT3)
1437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001439 return false;
1440 }
1441 break;
1442 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1443 if (!context->getExtensions().textureCompressionDXT5)
1444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001446 return false;
1447 }
1448 break;
1449 case GL_ETC1_RGB8_OES:
1450 if (!context->getExtensions().compressedETC1RGB8Texture)
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001453 return false;
1454 }
1455 break;
1456 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001457 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1458 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1459 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1460 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 if (!context->getExtensions().lossyETCDecode)
1462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidEnum()
1464 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001465 return false;
1466 }
1467 break;
1468 case GL_RGBA32F_EXT:
1469 case GL_RGB32F_EXT:
1470 case GL_ALPHA32F_EXT:
1471 case GL_LUMINANCE32F_EXT:
1472 case GL_LUMINANCE_ALPHA32F_EXT:
1473 if (!context->getExtensions().textureFloat)
1474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001475 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 return false;
1477 }
1478 break;
1479 case GL_RGBA16F_EXT:
1480 case GL_RGB16F_EXT:
1481 case GL_ALPHA16F_EXT:
1482 case GL_LUMINANCE16F_EXT:
1483 case GL_LUMINANCE_ALPHA16F_EXT:
1484 if (!context->getExtensions().textureHalfFloat)
1485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001486 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001487 return false;
1488 }
1489 break;
1490 case GL_R8_EXT:
1491 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001492 if (!context->getExtensions().textureRG)
1493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001494 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001495 return false;
1496 }
1497 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 case GL_R16F_EXT:
1499 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001500 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001502 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001503 return false;
1504 }
1505 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 case GL_R32F_EXT:
1507 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001508 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001511 return false;
1512 }
1513 break;
1514 case GL_DEPTH_COMPONENT16:
1515 case GL_DEPTH_COMPONENT32_OES:
1516 case GL_DEPTH24_STENCIL8_OES:
1517 if (!context->getExtensions().depthTextures)
1518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001520 return false;
1521 }
1522 if (target != GL_TEXTURE_2D)
1523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001524 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001525 return false;
1526 }
1527 // ANGLE_depth_texture only supports 1-level textures
1528 if (levels != 1)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001531 return false;
1532 }
1533 break;
1534 default:
1535 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001536 }
1537
Geoff Lang691e58c2014-12-19 17:03:25 -05001538 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 if (!texture || texture->id() == 0)
1540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001542 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001543 }
1544
Geoff Lang69cce582015-09-17 13:20:36 -04001545 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001548 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001549 }
1550
1551 return true;
1552}
1553
He Yunchaoced53ae2016-11-29 15:00:51 +08001554bool ValidateDiscardFramebufferEXT(Context *context,
1555 GLenum target,
1556 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001557 const GLenum *attachments)
1558{
Jamie Madillc29968b2016-01-20 11:17:23 -05001559 if (!context->getExtensions().discardFramebuffer)
1560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001562 return false;
1563 }
1564
Austin Kinross08332632015-05-05 13:35:47 -07001565 bool defaultFramebuffer = false;
1566
1567 switch (target)
1568 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001569 case GL_FRAMEBUFFER:
1570 defaultFramebuffer =
1571 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1572 break;
1573 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001574 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001575 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001576 }
1577
He Yunchaoced53ae2016-11-29 15:00:51 +08001578 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1579 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001580}
1581
Austin Kinrossbc781f32015-10-26 09:27:38 -07001582bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1583{
1584 if (!context->getExtensions().vertexArrayObject)
1585 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001586 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001587 return false;
1588 }
1589
1590 return ValidateBindVertexArrayBase(context, array);
1591}
1592
1593bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1594{
1595 if (!context->getExtensions().vertexArrayObject)
1596 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001598 return false;
1599 }
1600
Olli Etuaho41997e72016-03-10 13:38:39 +02001601 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001602}
1603
1604bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1605{
1606 if (!context->getExtensions().vertexArrayObject)
1607 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001609 return false;
1610 }
1611
Olli Etuaho41997e72016-03-10 13:38:39 +02001612 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001613}
1614
1615bool ValidateIsVertexArrayOES(Context *context)
1616{
1617 if (!context->getExtensions().vertexArrayObject)
1618 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001620 return false;
1621 }
1622
1623 return true;
1624}
Geoff Langc5629752015-12-07 16:29:04 -05001625
1626bool ValidateProgramBinaryOES(Context *context,
1627 GLuint program,
1628 GLenum binaryFormat,
1629 const void *binary,
1630 GLint length)
1631{
1632 if (!context->getExtensions().getProgramBinary)
1633 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001635 return false;
1636 }
1637
1638 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1639}
1640
1641bool ValidateGetProgramBinaryOES(Context *context,
1642 GLuint program,
1643 GLsizei bufSize,
1644 GLsizei *length,
1645 GLenum *binaryFormat,
1646 void *binary)
1647{
1648 if (!context->getExtensions().getProgramBinary)
1649 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001651 return false;
1652 }
1653
1654 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1655}
Geoff Lange102fee2015-12-10 11:23:30 -05001656
Geoff Lang70d0f492015-12-10 17:45:46 -05001657static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1658{
1659 switch (source)
1660 {
1661 case GL_DEBUG_SOURCE_API:
1662 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1663 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1664 case GL_DEBUG_SOURCE_OTHER:
1665 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1666 return !mustBeThirdPartyOrApplication;
1667
1668 case GL_DEBUG_SOURCE_THIRD_PARTY:
1669 case GL_DEBUG_SOURCE_APPLICATION:
1670 return true;
1671
1672 default:
1673 return false;
1674 }
1675}
1676
1677static bool ValidDebugType(GLenum type)
1678{
1679 switch (type)
1680 {
1681 case GL_DEBUG_TYPE_ERROR:
1682 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1683 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1684 case GL_DEBUG_TYPE_PERFORMANCE:
1685 case GL_DEBUG_TYPE_PORTABILITY:
1686 case GL_DEBUG_TYPE_OTHER:
1687 case GL_DEBUG_TYPE_MARKER:
1688 case GL_DEBUG_TYPE_PUSH_GROUP:
1689 case GL_DEBUG_TYPE_POP_GROUP:
1690 return true;
1691
1692 default:
1693 return false;
1694 }
1695}
1696
1697static bool ValidDebugSeverity(GLenum severity)
1698{
1699 switch (severity)
1700 {
1701 case GL_DEBUG_SEVERITY_HIGH:
1702 case GL_DEBUG_SEVERITY_MEDIUM:
1703 case GL_DEBUG_SEVERITY_LOW:
1704 case GL_DEBUG_SEVERITY_NOTIFICATION:
1705 return true;
1706
1707 default:
1708 return false;
1709 }
1710}
1711
Geoff Lange102fee2015-12-10 11:23:30 -05001712bool ValidateDebugMessageControlKHR(Context *context,
1713 GLenum source,
1714 GLenum type,
1715 GLenum severity,
1716 GLsizei count,
1717 const GLuint *ids,
1718 GLboolean enabled)
1719{
1720 if (!context->getExtensions().debug)
1721 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001723 return false;
1724 }
1725
Geoff Lang70d0f492015-12-10 17:45:46 -05001726 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001728 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001729 return false;
1730 }
1731
1732 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001734 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001735 return false;
1736 }
1737
1738 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001741 return false;
1742 }
1743
1744 if (count > 0)
1745 {
1746 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001748 context->handleError(
1749 InvalidOperation()
1750 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001751 return false;
1752 }
1753
1754 if (severity != GL_DONT_CARE)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001757 InvalidOperation()
1758 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001759 return false;
1760 }
1761 }
1762
Geoff Lange102fee2015-12-10 11:23:30 -05001763 return true;
1764}
1765
1766bool ValidateDebugMessageInsertKHR(Context *context,
1767 GLenum source,
1768 GLenum type,
1769 GLuint id,
1770 GLenum severity,
1771 GLsizei length,
1772 const GLchar *buf)
1773{
1774 if (!context->getExtensions().debug)
1775 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001777 return false;
1778 }
1779
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001780 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001781 {
1782 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1783 // not generate an error.
1784 return false;
1785 }
1786
1787 if (!ValidDebugSeverity(severity))
1788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001790 return false;
1791 }
1792
1793 if (!ValidDebugType(type))
1794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001795 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001796 return false;
1797 }
1798
1799 if (!ValidDebugSource(source, true))
1800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001801 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001802 return false;
1803 }
1804
1805 size_t messageLength = (length < 0) ? strlen(buf) : length;
1806 if (messageLength > context->getExtensions().maxDebugMessageLength)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidValue()
1809 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001810 return false;
1811 }
1812
Geoff Lange102fee2015-12-10 11:23:30 -05001813 return true;
1814}
1815
1816bool ValidateDebugMessageCallbackKHR(Context *context,
1817 GLDEBUGPROCKHR callback,
1818 const void *userParam)
1819{
1820 if (!context->getExtensions().debug)
1821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001823 return false;
1824 }
1825
Geoff Lange102fee2015-12-10 11:23:30 -05001826 return true;
1827}
1828
1829bool ValidateGetDebugMessageLogKHR(Context *context,
1830 GLuint count,
1831 GLsizei bufSize,
1832 GLenum *sources,
1833 GLenum *types,
1834 GLuint *ids,
1835 GLenum *severities,
1836 GLsizei *lengths,
1837 GLchar *messageLog)
1838{
1839 if (!context->getExtensions().debug)
1840 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001842 return false;
1843 }
1844
Geoff Lang70d0f492015-12-10 17:45:46 -05001845 if (bufSize < 0 && messageLog != nullptr)
1846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001847 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05001848 return false;
1849 }
1850
Geoff Lange102fee2015-12-10 11:23:30 -05001851 return true;
1852}
1853
1854bool ValidatePushDebugGroupKHR(Context *context,
1855 GLenum source,
1856 GLuint id,
1857 GLsizei length,
1858 const GLchar *message)
1859{
1860 if (!context->getExtensions().debug)
1861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001862 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001863 return false;
1864 }
1865
Geoff Lang70d0f492015-12-10 17:45:46 -05001866 if (!ValidDebugSource(source, true))
1867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001868 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001869 return false;
1870 }
1871
1872 size_t messageLength = (length < 0) ? strlen(message) : length;
1873 if (messageLength > context->getExtensions().maxDebugMessageLength)
1874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001875 context->handleError(InvalidValue()
1876 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001877 return false;
1878 }
1879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001880 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001881 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001883 context
1884 ->handleError(StackOverflow()
1885 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001886 return false;
1887 }
1888
Geoff Lange102fee2015-12-10 11:23:30 -05001889 return true;
1890}
1891
1892bool ValidatePopDebugGroupKHR(Context *context)
1893{
1894 if (!context->getExtensions().debug)
1895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001897 return false;
1898 }
1899
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001900 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001901 if (currentStackSize <= 1)
1902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001903 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 return false;
1905 }
1906
1907 return true;
1908}
1909
1910static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1911{
1912 switch (identifier)
1913 {
1914 case GL_BUFFER:
1915 if (context->getBuffer(name) == nullptr)
1916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001917 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001918 return false;
1919 }
1920 return true;
1921
1922 case GL_SHADER:
1923 if (context->getShader(name) == nullptr)
1924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001925 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001926 return false;
1927 }
1928 return true;
1929
1930 case GL_PROGRAM:
1931 if (context->getProgram(name) == nullptr)
1932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001933 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001934 return false;
1935 }
1936 return true;
1937
1938 case GL_VERTEX_ARRAY:
1939 if (context->getVertexArray(name) == nullptr)
1940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001941 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001942 return false;
1943 }
1944 return true;
1945
1946 case GL_QUERY:
1947 if (context->getQuery(name) == nullptr)
1948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001949 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001950 return false;
1951 }
1952 return true;
1953
1954 case GL_TRANSFORM_FEEDBACK:
1955 if (context->getTransformFeedback(name) == nullptr)
1956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001957 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001958 return false;
1959 }
1960 return true;
1961
1962 case GL_SAMPLER:
1963 if (context->getSampler(name) == nullptr)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001966 return false;
1967 }
1968 return true;
1969
1970 case GL_TEXTURE:
1971 if (context->getTexture(name) == nullptr)
1972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001973 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001974 return false;
1975 }
1976 return true;
1977
1978 case GL_RENDERBUFFER:
1979 if (context->getRenderbuffer(name) == nullptr)
1980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001981 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001982 return false;
1983 }
1984 return true;
1985
1986 case GL_FRAMEBUFFER:
1987 if (context->getFramebuffer(name) == nullptr)
1988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001989 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001990 return false;
1991 }
1992 return true;
1993
1994 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001995 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001996 return false;
1997 }
Geoff Lange102fee2015-12-10 11:23:30 -05001998}
1999
Martin Radev9d901792016-07-15 15:58:58 +03002000static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2001{
2002 size_t labelLength = 0;
2003
2004 if (length < 0)
2005 {
2006 if (label != nullptr)
2007 {
2008 labelLength = strlen(label);
2009 }
2010 }
2011 else
2012 {
2013 labelLength = static_cast<size_t>(length);
2014 }
2015
2016 if (labelLength > context->getExtensions().maxLabelLength)
2017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002018 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002019 return false;
2020 }
2021
2022 return true;
2023}
2024
Geoff Lange102fee2015-12-10 11:23:30 -05002025bool ValidateObjectLabelKHR(Context *context,
2026 GLenum identifier,
2027 GLuint name,
2028 GLsizei length,
2029 const GLchar *label)
2030{
2031 if (!context->getExtensions().debug)
2032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002034 return false;
2035 }
2036
Geoff Lang70d0f492015-12-10 17:45:46 -05002037 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2038 {
2039 return false;
2040 }
2041
Martin Radev9d901792016-07-15 15:58:58 +03002042 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002043 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002044 return false;
2045 }
2046
Geoff Lange102fee2015-12-10 11:23:30 -05002047 return true;
2048}
2049
2050bool ValidateGetObjectLabelKHR(Context *context,
2051 GLenum identifier,
2052 GLuint name,
2053 GLsizei bufSize,
2054 GLsizei *length,
2055 GLchar *label)
2056{
2057 if (!context->getExtensions().debug)
2058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002060 return false;
2061 }
2062
Geoff Lang70d0f492015-12-10 17:45:46 -05002063 if (bufSize < 0)
2064 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002065 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002066 return false;
2067 }
2068
2069 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2070 {
2071 return false;
2072 }
2073
Martin Radev9d901792016-07-15 15:58:58 +03002074 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002075}
2076
2077static bool ValidateObjectPtrName(Context *context, const void *ptr)
2078{
2079 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002081 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002082 return false;
2083 }
2084
Geoff Lange102fee2015-12-10 11:23:30 -05002085 return true;
2086}
2087
2088bool ValidateObjectPtrLabelKHR(Context *context,
2089 const void *ptr,
2090 GLsizei length,
2091 const GLchar *label)
2092{
2093 if (!context->getExtensions().debug)
2094 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002096 return false;
2097 }
2098
Geoff Lang70d0f492015-12-10 17:45:46 -05002099 if (!ValidateObjectPtrName(context, ptr))
2100 {
2101 return false;
2102 }
2103
Martin Radev9d901792016-07-15 15:58:58 +03002104 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002105 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002106 return false;
2107 }
2108
Geoff Lange102fee2015-12-10 11:23:30 -05002109 return true;
2110}
2111
2112bool ValidateGetObjectPtrLabelKHR(Context *context,
2113 const void *ptr,
2114 GLsizei bufSize,
2115 GLsizei *length,
2116 GLchar *label)
2117{
2118 if (!context->getExtensions().debug)
2119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002121 return false;
2122 }
2123
Geoff Lang70d0f492015-12-10 17:45:46 -05002124 if (bufSize < 0)
2125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002126 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002127 return false;
2128 }
2129
2130 if (!ValidateObjectPtrName(context, ptr))
2131 {
2132 return false;
2133 }
2134
Martin Radev9d901792016-07-15 15:58:58 +03002135 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002136}
2137
2138bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2139{
2140 if (!context->getExtensions().debug)
2141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002143 return false;
2144 }
2145
Geoff Lang70d0f492015-12-10 17:45:46 -05002146 // TODO: represent this in Context::getQueryParameterInfo.
2147 switch (pname)
2148 {
2149 case GL_DEBUG_CALLBACK_FUNCTION:
2150 case GL_DEBUG_CALLBACK_USER_PARAM:
2151 break;
2152
2153 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002154 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002155 return false;
2156 }
2157
Geoff Lange102fee2015-12-10 11:23:30 -05002158 return true;
2159}
Jamie Madillc29968b2016-01-20 11:17:23 -05002160
2161bool ValidateBlitFramebufferANGLE(Context *context,
2162 GLint srcX0,
2163 GLint srcY0,
2164 GLint srcX1,
2165 GLint srcY1,
2166 GLint dstX0,
2167 GLint dstY0,
2168 GLint dstX1,
2169 GLint dstY1,
2170 GLbitfield mask,
2171 GLenum filter)
2172{
2173 if (!context->getExtensions().framebufferBlit)
2174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002175 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002176 return false;
2177 }
2178
2179 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2180 {
2181 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002182 context->handleError(InvalidOperation() << "Scaling and flipping in "
2183 "BlitFramebufferANGLE not supported by this "
2184 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002185 return false;
2186 }
2187
2188 if (filter == GL_LINEAR)
2189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002190 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002191 return false;
2192 }
2193
Jamie Madill51f40ec2016-06-15 14:06:00 -04002194 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2195 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002196
2197 if (mask & GL_COLOR_BUFFER_BIT)
2198 {
2199 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2200 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2201
2202 if (readColorAttachment && drawColorAttachment)
2203 {
2204 if (!(readColorAttachment->type() == GL_TEXTURE &&
2205 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2206 readColorAttachment->type() != GL_RENDERBUFFER &&
2207 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002210 return false;
2211 }
2212
Geoff Langa15472a2015-08-11 11:48:03 -04002213 for (size_t drawbufferIdx = 0;
2214 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002215 {
Geoff Langa15472a2015-08-11 11:48:03 -04002216 const FramebufferAttachment *attachment =
2217 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2218 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002219 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002220 if (!(attachment->type() == GL_TEXTURE &&
2221 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2222 attachment->type() != GL_RENDERBUFFER &&
2223 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002225 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002226 return false;
2227 }
2228
2229 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002230 if (!Format::SameSized(attachment->getFormat(),
2231 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002233 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002234 return false;
2235 }
2236 }
2237 }
2238
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002239 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002240 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2241 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002244 return false;
2245 }
2246 }
2247 }
2248
2249 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2250 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2251 for (size_t i = 0; i < 2; i++)
2252 {
2253 if (mask & masks[i])
2254 {
2255 const FramebufferAttachment *readBuffer =
2256 readFramebuffer->getAttachment(attachments[i]);
2257 const FramebufferAttachment *drawBuffer =
2258 drawFramebuffer->getAttachment(attachments[i]);
2259
2260 if (readBuffer && drawBuffer)
2261 {
2262 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2263 dstX0, dstY0, dstX1, dstY1))
2264 {
2265 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002266 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2267 "stencil blits are supported by "
2268 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002269 return false;
2270 }
2271
2272 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002275 return false;
2276 }
2277 }
2278 }
2279 }
2280
2281 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2282 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002283}
Jamie Madillc29968b2016-01-20 11:17:23 -05002284
2285bool ValidateClear(ValidationContext *context, GLbitfield mask)
2286{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002287 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002288 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002290 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002291 return false;
2292 }
2293
2294 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002296 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002297 return false;
2298 }
2299
Geoff Lang76e65652017-03-27 14:58:02 -04002300 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2301 {
2302 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2303 GL_SIGNED_NORMALIZED};
2304
2305 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2306 drawBufferIdx++)
2307 {
2308 if (!ValidateWebGLFramebufferAttachmentClearType(
2309 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2310 {
2311 return false;
2312 }
2313 }
2314 }
2315
Jamie Madillc29968b2016-01-20 11:17:23 -05002316 return true;
2317}
2318
2319bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2320{
2321 if (!context->getExtensions().drawBuffers)
2322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002324 return false;
2325 }
2326
2327 return ValidateDrawBuffersBase(context, n, bufs);
2328}
2329
Jamie Madill73a84962016-02-12 09:27:23 -05002330bool ValidateTexImage2D(Context *context,
2331 GLenum target,
2332 GLint level,
2333 GLint internalformat,
2334 GLsizei width,
2335 GLsizei height,
2336 GLint border,
2337 GLenum format,
2338 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002339 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002340{
Martin Radev1be913c2016-07-11 17:59:16 +03002341 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002342 {
2343 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002344 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002345 }
2346
Martin Radev1be913c2016-07-11 17:59:16 +03002347 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002348 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002349 0, 0, width, height, 1, border, format, type, -1,
2350 pixels);
2351}
2352
2353bool ValidateTexImage2DRobust(Context *context,
2354 GLenum target,
2355 GLint level,
2356 GLint internalformat,
2357 GLsizei width,
2358 GLsizei height,
2359 GLint border,
2360 GLenum format,
2361 GLenum type,
2362 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002363 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002364{
2365 if (!ValidateRobustEntryPoint(context, bufSize))
2366 {
2367 return false;
2368 }
2369
2370 if (context->getClientMajorVersion() < 3)
2371 {
2372 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2373 0, 0, width, height, border, format, type, bufSize,
2374 pixels);
2375 }
2376
2377 ASSERT(context->getClientMajorVersion() >= 3);
2378 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2379 0, 0, width, height, 1, border, format, type, bufSize,
2380 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002381}
2382
2383bool ValidateTexSubImage2D(Context *context,
2384 GLenum target,
2385 GLint level,
2386 GLint xoffset,
2387 GLint yoffset,
2388 GLsizei width,
2389 GLsizei height,
2390 GLenum format,
2391 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002392 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002393{
2394
Martin Radev1be913c2016-07-11 17:59:16 +03002395 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002396 {
2397 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002398 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002399 }
2400
Martin Radev1be913c2016-07-11 17:59:16 +03002401 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002402 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002403 yoffset, 0, width, height, 1, 0, format, type, -1,
2404 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002405}
2406
Geoff Langc52f6f12016-10-14 10:18:00 -04002407bool ValidateTexSubImage2DRobustANGLE(Context *context,
2408 GLenum target,
2409 GLint level,
2410 GLint xoffset,
2411 GLint yoffset,
2412 GLsizei width,
2413 GLsizei height,
2414 GLenum format,
2415 GLenum type,
2416 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002417 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002418{
2419 if (!ValidateRobustEntryPoint(context, bufSize))
2420 {
2421 return false;
2422 }
2423
2424 if (context->getClientMajorVersion() < 3)
2425 {
2426 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2427 yoffset, width, height, 0, format, type, bufSize,
2428 pixels);
2429 }
2430
2431 ASSERT(context->getClientMajorVersion() >= 3);
2432 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2433 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2434 pixels);
2435}
2436
Jamie Madill73a84962016-02-12 09:27:23 -05002437bool ValidateCompressedTexImage2D(Context *context,
2438 GLenum target,
2439 GLint level,
2440 GLenum internalformat,
2441 GLsizei width,
2442 GLsizei height,
2443 GLint border,
2444 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002445 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002446{
Martin Radev1be913c2016-07-11 17:59:16 +03002447 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002448 {
2449 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002450 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002451 {
2452 return false;
2453 }
2454 }
2455 else
2456 {
Martin Radev1be913c2016-07-11 17:59:16 +03002457 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002458 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002459 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002460 data))
2461 {
2462 return false;
2463 }
2464 }
2465
Geoff Langca271392017-04-05 12:30:00 -04002466 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002467 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002468 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002469 if (blockSizeOrErr.isError())
2470 {
2471 context->handleError(blockSizeOrErr.getError());
2472 return false;
2473 }
2474
2475 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002477 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002478 return false;
2479 }
2480
2481 return true;
2482}
2483
Corentin Wallezb2931602017-04-11 15:58:57 -04002484bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2485 GLenum target,
2486 GLint level,
2487 GLenum internalformat,
2488 GLsizei width,
2489 GLsizei height,
2490 GLint border,
2491 GLsizei imageSize,
2492 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002493 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002494{
2495 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2496 {
2497 return false;
2498 }
2499
2500 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2501 border, imageSize, data);
2502}
2503bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2504 GLenum target,
2505 GLint level,
2506 GLint xoffset,
2507 GLint yoffset,
2508 GLsizei width,
2509 GLsizei height,
2510 GLenum format,
2511 GLsizei imageSize,
2512 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002513 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002514{
2515 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2516 {
2517 return false;
2518 }
2519
2520 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2521 format, imageSize, data);
2522}
2523
Jamie Madill73a84962016-02-12 09:27:23 -05002524bool ValidateCompressedTexSubImage2D(Context *context,
2525 GLenum target,
2526 GLint level,
2527 GLint xoffset,
2528 GLint yoffset,
2529 GLsizei width,
2530 GLsizei height,
2531 GLenum format,
2532 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002533 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002534{
Martin Radev1be913c2016-07-11 17:59:16 +03002535 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002536 {
2537 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002538 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002539 {
2540 return false;
2541 }
2542 }
2543 else
2544 {
Martin Radev1be913c2016-07-11 17:59:16 +03002545 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002546 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002547 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002548 data))
2549 {
2550 return false;
2551 }
2552 }
2553
Geoff Langca271392017-04-05 12:30:00 -04002554 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002555 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002556 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002557 if (blockSizeOrErr.isError())
2558 {
2559 context->handleError(blockSizeOrErr.getError());
2560 return false;
2561 }
2562
2563 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002566 return false;
2567 }
2568
2569 return true;
2570}
2571
Olli Etuaho4f667482016-03-30 15:56:35 +03002572bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2573{
Geoff Lang496c02d2016-10-20 11:38:11 -07002574 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002575}
2576
2577bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2578{
2579 if (!context->getExtensions().mapBuffer)
2580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002581 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002582 return false;
2583 }
2584
2585 if (!ValidBufferTarget(context, target))
2586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002588 return false;
2589 }
2590
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002591 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002592
2593 if (buffer == nullptr)
2594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002595 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002596 return false;
2597 }
2598
2599 if (access != GL_WRITE_ONLY_OES)
2600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002601 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002602 return false;
2603 }
2604
2605 if (buffer->isMapped())
2606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002607 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002608 return false;
2609 }
2610
2611 return true;
2612}
2613
2614bool ValidateUnmapBufferOES(Context *context, GLenum target)
2615{
2616 if (!context->getExtensions().mapBuffer)
2617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002618 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002619 return false;
2620 }
2621
2622 return ValidateUnmapBufferBase(context, target);
2623}
2624
2625bool ValidateMapBufferRangeEXT(Context *context,
2626 GLenum target,
2627 GLintptr offset,
2628 GLsizeiptr length,
2629 GLbitfield access)
2630{
2631 if (!context->getExtensions().mapBufferRange)
2632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002633 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002634 return false;
2635 }
2636
2637 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2638}
2639
2640bool ValidateFlushMappedBufferRangeEXT(Context *context,
2641 GLenum target,
2642 GLintptr offset,
2643 GLsizeiptr length)
2644{
2645 if (!context->getExtensions().mapBufferRange)
2646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002647 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002648 return false;
2649 }
2650
2651 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2652}
2653
Ian Ewell54f87462016-03-10 13:47:21 -05002654bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2655{
2656 Texture *textureObject = context->getTexture(texture);
2657 if (textureObject && textureObject->getTarget() != target && texture != 0)
2658 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Ian Ewell54f87462016-03-10 13:47:21 -05002660 return false;
2661 }
2662
Geoff Langf41a7152016-09-19 15:11:17 -04002663 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2664 !context->isTextureGenerated(texture))
2665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002666 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002667 return false;
2668 }
2669
Ian Ewell54f87462016-03-10 13:47:21 -05002670 switch (target)
2671 {
2672 case GL_TEXTURE_2D:
2673 case GL_TEXTURE_CUBE_MAP:
2674 break;
2675
2676 case GL_TEXTURE_3D:
2677 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002678 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002680 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002681 return false;
2682 }
2683 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002684
2685 case GL_TEXTURE_2D_MULTISAMPLE:
2686 if (context->getClientVersion() < Version(3, 1))
2687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002688 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002689 return false;
2690 }
Geoff Lang3b573612016-10-31 14:08:10 -04002691 break;
2692
Ian Ewell54f87462016-03-10 13:47:21 -05002693 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002694 if (!context->getExtensions().eglImageExternal &&
2695 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002697 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002698 return false;
2699 }
2700 break;
2701 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002702 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002703 return false;
2704 }
2705
2706 return true;
2707}
2708
Geoff Langd8605522016-04-13 10:19:12 -04002709bool ValidateBindUniformLocationCHROMIUM(Context *context,
2710 GLuint program,
2711 GLint location,
2712 const GLchar *name)
2713{
2714 if (!context->getExtensions().bindUniformLocation)
2715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002716 context->handleError(InvalidOperation()
2717 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002718 return false;
2719 }
2720
2721 Program *programObject = GetValidProgram(context, program);
2722 if (!programObject)
2723 {
2724 return false;
2725 }
2726
2727 if (location < 0)
2728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002729 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002730 return false;
2731 }
2732
2733 const Caps &caps = context->getCaps();
2734 if (static_cast<size_t>(location) >=
2735 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002737 context->handleError(InvalidValue() << "Location must be less than "
2738 "(MAX_VERTEX_UNIFORM_VECTORS + "
2739 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002740 return false;
2741 }
2742
Geoff Langfc32e8b2017-05-31 14:16:59 -04002743 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2744 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04002745 if (context->getExtensions().webglCompatibility &&
2746 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002747 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002748 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04002749 return false;
2750 }
2751
Geoff Langd8605522016-04-13 10:19:12 -04002752 if (strncmp(name, "gl_", 3) == 0)
2753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002754 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04002755 return false;
2756 }
2757
2758 return true;
2759}
2760
Jamie Madille2e406c2016-06-02 13:04:10 -04002761bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002762{
2763 if (!context->getExtensions().framebufferMixedSamples)
2764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002765 context->handleError(InvalidOperation()
2766 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002767 return false;
2768 }
2769 switch (components)
2770 {
2771 case GL_RGB:
2772 case GL_RGBA:
2773 case GL_ALPHA:
2774 case GL_NONE:
2775 break;
2776 default:
2777 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002778 InvalidEnum()
2779 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002780 return false;
2781 }
2782
2783 return true;
2784}
2785
Sami Väisänene45e53b2016-05-25 10:36:04 +03002786// CHROMIUM_path_rendering
2787
2788bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2789{
2790 if (!context->getExtensions().pathRendering)
2791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002792 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002793 return false;
2794 }
2795 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002797 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002798 return false;
2799 }
2800 if (matrix == nullptr)
2801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002802 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002803 return false;
2804 }
2805 return true;
2806}
2807
2808bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2809{
2810 if (!context->getExtensions().pathRendering)
2811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002812 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002813 return false;
2814 }
2815 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002817 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002818 return false;
2819 }
2820 return true;
2821}
2822
2823bool ValidateGenPaths(Context *context, GLsizei range)
2824{
2825 if (!context->getExtensions().pathRendering)
2826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002827 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002828 return false;
2829 }
2830
2831 // range = 0 is undefined in NV_path_rendering.
2832 // we add stricter semantic check here and require a non zero positive range.
2833 if (range <= 0)
2834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002835 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002836 return false;
2837 }
2838
2839 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2840 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002842 return false;
2843 }
2844
2845 return true;
2846}
2847
2848bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2849{
2850 if (!context->getExtensions().pathRendering)
2851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002852 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002853 return false;
2854 }
2855
2856 // range = 0 is undefined in NV_path_rendering.
2857 // we add stricter semantic check here and require a non zero positive range.
2858 if (range <= 0)
2859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002860 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002861 return false;
2862 }
2863
2864 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2865 checkedRange += range;
2866
2867 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2868 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002869 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002870 return false;
2871 }
2872 return true;
2873}
2874
2875bool ValidatePathCommands(Context *context,
2876 GLuint path,
2877 GLsizei numCommands,
2878 const GLubyte *commands,
2879 GLsizei numCoords,
2880 GLenum coordType,
2881 const void *coords)
2882{
2883 if (!context->getExtensions().pathRendering)
2884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002885 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002886 return false;
2887 }
2888 if (!context->hasPath(path))
2889 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002890 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002891 return false;
2892 }
2893
2894 if (numCommands < 0)
2895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002896 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002897 return false;
2898 }
2899 else if (numCommands > 0)
2900 {
2901 if (!commands)
2902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002903 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002904 return false;
2905 }
2906 }
2907
2908 if (numCoords < 0)
2909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002910 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002911 return false;
2912 }
2913 else if (numCoords > 0)
2914 {
2915 if (!coords)
2916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002917 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002918 return false;
2919 }
2920 }
2921
2922 std::uint32_t coordTypeSize = 0;
2923 switch (coordType)
2924 {
2925 case GL_BYTE:
2926 coordTypeSize = sizeof(GLbyte);
2927 break;
2928
2929 case GL_UNSIGNED_BYTE:
2930 coordTypeSize = sizeof(GLubyte);
2931 break;
2932
2933 case GL_SHORT:
2934 coordTypeSize = sizeof(GLshort);
2935 break;
2936
2937 case GL_UNSIGNED_SHORT:
2938 coordTypeSize = sizeof(GLushort);
2939 break;
2940
2941 case GL_FLOAT:
2942 coordTypeSize = sizeof(GLfloat);
2943 break;
2944
2945 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002946 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002947 return false;
2948 }
2949
2950 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2951 checkedSize += (coordTypeSize * numCoords);
2952 if (!checkedSize.IsValid())
2953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002955 return false;
2956 }
2957
2958 // early return skips command data validation when it doesn't exist.
2959 if (!commands)
2960 return true;
2961
2962 GLsizei expectedNumCoords = 0;
2963 for (GLsizei i = 0; i < numCommands; ++i)
2964 {
2965 switch (commands[i])
2966 {
2967 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2968 break;
2969 case GL_MOVE_TO_CHROMIUM:
2970 case GL_LINE_TO_CHROMIUM:
2971 expectedNumCoords += 2;
2972 break;
2973 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2974 expectedNumCoords += 4;
2975 break;
2976 case GL_CUBIC_CURVE_TO_CHROMIUM:
2977 expectedNumCoords += 6;
2978 break;
2979 case GL_CONIC_CURVE_TO_CHROMIUM:
2980 expectedNumCoords += 5;
2981 break;
2982 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002983 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002984 return false;
2985 }
2986 }
2987 if (expectedNumCoords != numCoords)
2988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002989 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002990 return false;
2991 }
2992
2993 return true;
2994}
2995
2996bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2997{
2998 if (!context->getExtensions().pathRendering)
2999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003000 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003001 return false;
3002 }
3003 if (!context->hasPath(path))
3004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003005 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003006 return false;
3007 }
3008
3009 switch (pname)
3010 {
3011 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3012 if (value < 0.0f)
3013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003014 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003015 return false;
3016 }
3017 break;
3018 case GL_PATH_END_CAPS_CHROMIUM:
3019 switch (static_cast<GLenum>(value))
3020 {
3021 case GL_FLAT_CHROMIUM:
3022 case GL_SQUARE_CHROMIUM:
3023 case GL_ROUND_CHROMIUM:
3024 break;
3025 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003026 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003027 return false;
3028 }
3029 break;
3030 case GL_PATH_JOIN_STYLE_CHROMIUM:
3031 switch (static_cast<GLenum>(value))
3032 {
3033 case GL_MITER_REVERT_CHROMIUM:
3034 case GL_BEVEL_CHROMIUM:
3035 case GL_ROUND_CHROMIUM:
3036 break;
3037 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003038 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003039 return false;
3040 }
3041 case GL_PATH_MITER_LIMIT_CHROMIUM:
3042 if (value < 0.0f)
3043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003044 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003045 return false;
3046 }
3047 break;
3048
3049 case GL_PATH_STROKE_BOUND_CHROMIUM:
3050 // no errors, only clamping.
3051 break;
3052
3053 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003054 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003055 return false;
3056 }
3057 return true;
3058}
3059
3060bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3061{
3062 if (!context->getExtensions().pathRendering)
3063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003064 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003065 return false;
3066 }
3067
3068 if (!context->hasPath(path))
3069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003070 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003071 return false;
3072 }
3073 if (!value)
3074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003075 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003076 return false;
3077 }
3078
3079 switch (pname)
3080 {
3081 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3082 case GL_PATH_END_CAPS_CHROMIUM:
3083 case GL_PATH_JOIN_STYLE_CHROMIUM:
3084 case GL_PATH_MITER_LIMIT_CHROMIUM:
3085 case GL_PATH_STROKE_BOUND_CHROMIUM:
3086 break;
3087
3088 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003089 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003090 return false;
3091 }
3092
3093 return true;
3094}
3095
3096bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3097{
3098 if (!context->getExtensions().pathRendering)
3099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003100 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003101 return false;
3102 }
3103
3104 switch (func)
3105 {
3106 case GL_NEVER:
3107 case GL_ALWAYS:
3108 case GL_LESS:
3109 case GL_LEQUAL:
3110 case GL_EQUAL:
3111 case GL_GEQUAL:
3112 case GL_GREATER:
3113 case GL_NOTEQUAL:
3114 break;
3115 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003117 return false;
3118 }
3119
3120 return true;
3121}
3122
3123// Note that the spec specifies that for the path drawing commands
3124// if the path object is not an existing path object the command
3125// does nothing and no error is generated.
3126// However if the path object exists but has not been specified any
3127// commands then an error is generated.
3128
3129bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3130{
3131 if (!context->getExtensions().pathRendering)
3132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003133 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003134 return false;
3135 }
3136 if (context->hasPath(path) && !context->hasPathData(path))
3137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003138 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003139 return false;
3140 }
3141
3142 switch (fillMode)
3143 {
3144 case GL_COUNT_UP_CHROMIUM:
3145 case GL_COUNT_DOWN_CHROMIUM:
3146 break;
3147 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003148 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003149 return false;
3150 }
3151
3152 if (!isPow2(mask + 1))
3153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003154 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003155 return false;
3156 }
3157
3158 return true;
3159}
3160
3161bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3162{
3163 if (!context->getExtensions().pathRendering)
3164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003165 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003166 return false;
3167 }
3168 if (context->hasPath(path) && !context->hasPathData(path))
3169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003170 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003171 return false;
3172 }
3173
3174 return true;
3175}
3176
3177bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3178{
3179 if (!context->getExtensions().pathRendering)
3180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003181 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003182 return false;
3183 }
3184 if (context->hasPath(path) && !context->hasPathData(path))
3185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003186 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003187 return false;
3188 }
3189
3190 switch (coverMode)
3191 {
3192 case GL_CONVEX_HULL_CHROMIUM:
3193 case GL_BOUNDING_BOX_CHROMIUM:
3194 break;
3195 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003196 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003197 return false;
3198 }
3199 return true;
3200}
3201
3202bool ValidateStencilThenCoverFillPath(Context *context,
3203 GLuint path,
3204 GLenum fillMode,
3205 GLuint mask,
3206 GLenum coverMode)
3207{
3208 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3209 ValidateCoverPath(context, path, coverMode);
3210}
3211
3212bool ValidateStencilThenCoverStrokePath(Context *context,
3213 GLuint path,
3214 GLint reference,
3215 GLuint mask,
3216 GLenum coverMode)
3217{
3218 return ValidateStencilStrokePath(context, path, reference, mask) &&
3219 ValidateCoverPath(context, path, coverMode);
3220}
3221
3222bool ValidateIsPath(Context *context)
3223{
3224 if (!context->getExtensions().pathRendering)
3225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003227 return false;
3228 }
3229 return true;
3230}
3231
Sami Väisänend59ca052016-06-21 16:10:00 +03003232bool ValidateCoverFillPathInstanced(Context *context,
3233 GLsizei numPaths,
3234 GLenum pathNameType,
3235 const void *paths,
3236 GLuint pathBase,
3237 GLenum coverMode,
3238 GLenum transformType,
3239 const GLfloat *transformValues)
3240{
3241 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3242 transformType, transformValues))
3243 return false;
3244
3245 switch (coverMode)
3246 {
3247 case GL_CONVEX_HULL_CHROMIUM:
3248 case GL_BOUNDING_BOX_CHROMIUM:
3249 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3250 break;
3251 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003253 return false;
3254 }
3255
3256 return true;
3257}
3258
3259bool ValidateCoverStrokePathInstanced(Context *context,
3260 GLsizei numPaths,
3261 GLenum pathNameType,
3262 const void *paths,
3263 GLuint pathBase,
3264 GLenum coverMode,
3265 GLenum transformType,
3266 const GLfloat *transformValues)
3267{
3268 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3269 transformType, transformValues))
3270 return false;
3271
3272 switch (coverMode)
3273 {
3274 case GL_CONVEX_HULL_CHROMIUM:
3275 case GL_BOUNDING_BOX_CHROMIUM:
3276 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3277 break;
3278 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003279 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003280 return false;
3281 }
3282
3283 return true;
3284}
3285
3286bool ValidateStencilFillPathInstanced(Context *context,
3287 GLsizei numPaths,
3288 GLenum pathNameType,
3289 const void *paths,
3290 GLuint pathBase,
3291 GLenum fillMode,
3292 GLuint mask,
3293 GLenum transformType,
3294 const GLfloat *transformValues)
3295{
3296
3297 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3298 transformType, transformValues))
3299 return false;
3300
3301 switch (fillMode)
3302 {
3303 case GL_COUNT_UP_CHROMIUM:
3304 case GL_COUNT_DOWN_CHROMIUM:
3305 break;
3306 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003308 return false;
3309 }
3310 if (!isPow2(mask + 1))
3311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003312 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003313 return false;
3314 }
3315 return true;
3316}
3317
3318bool ValidateStencilStrokePathInstanced(Context *context,
3319 GLsizei numPaths,
3320 GLenum pathNameType,
3321 const void *paths,
3322 GLuint pathBase,
3323 GLint reference,
3324 GLuint mask,
3325 GLenum transformType,
3326 const GLfloat *transformValues)
3327{
3328 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3329 transformType, transformValues))
3330 return false;
3331
3332 // no more validation here.
3333
3334 return true;
3335}
3336
3337bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3338 GLsizei numPaths,
3339 GLenum pathNameType,
3340 const void *paths,
3341 GLuint pathBase,
3342 GLenum fillMode,
3343 GLuint mask,
3344 GLenum coverMode,
3345 GLenum transformType,
3346 const GLfloat *transformValues)
3347{
3348 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3349 transformType, transformValues))
3350 return false;
3351
3352 switch (coverMode)
3353 {
3354 case GL_CONVEX_HULL_CHROMIUM:
3355 case GL_BOUNDING_BOX_CHROMIUM:
3356 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3357 break;
3358 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003359 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003360 return false;
3361 }
3362
3363 switch (fillMode)
3364 {
3365 case GL_COUNT_UP_CHROMIUM:
3366 case GL_COUNT_DOWN_CHROMIUM:
3367 break;
3368 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003369 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003370 return false;
3371 }
3372 if (!isPow2(mask + 1))
3373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003374 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003375 return false;
3376 }
3377
3378 return true;
3379}
3380
3381bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3382 GLsizei numPaths,
3383 GLenum pathNameType,
3384 const void *paths,
3385 GLuint pathBase,
3386 GLint reference,
3387 GLuint mask,
3388 GLenum coverMode,
3389 GLenum transformType,
3390 const GLfloat *transformValues)
3391{
3392 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3393 transformType, transformValues))
3394 return false;
3395
3396 switch (coverMode)
3397 {
3398 case GL_CONVEX_HULL_CHROMIUM:
3399 case GL_BOUNDING_BOX_CHROMIUM:
3400 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3401 break;
3402 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003403 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003404 return false;
3405 }
3406
3407 return true;
3408}
3409
Sami Väisänen46eaa942016-06-29 10:26:37 +03003410bool ValidateBindFragmentInputLocation(Context *context,
3411 GLuint program,
3412 GLint location,
3413 const GLchar *name)
3414{
3415 if (!context->getExtensions().pathRendering)
3416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003417 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003418 return false;
3419 }
3420
3421 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3422 if (location >= MaxLocation)
3423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003424 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003425 return false;
3426 }
3427
3428 const auto *programObject = context->getProgram(program);
3429 if (!programObject)
3430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003432 return false;
3433 }
3434
3435 if (!name)
3436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003438 return false;
3439 }
3440
3441 if (angle::BeginsWith(name, "gl_"))
3442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003443 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003444 return false;
3445 }
3446
3447 return true;
3448}
3449
3450bool ValidateProgramPathFragmentInputGen(Context *context,
3451 GLuint program,
3452 GLint location,
3453 GLenum genMode,
3454 GLint components,
3455 const GLfloat *coeffs)
3456{
3457 if (!context->getExtensions().pathRendering)
3458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003459 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003460 return false;
3461 }
3462
3463 const auto *programObject = context->getProgram(program);
3464 if (!programObject || programObject->isFlaggedForDeletion())
3465 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003467 return false;
3468 }
3469
3470 if (!programObject->isLinked())
3471 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003473 return false;
3474 }
3475
3476 switch (genMode)
3477 {
3478 case GL_NONE:
3479 if (components != 0)
3480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003481 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003482 return false;
3483 }
3484 break;
3485
3486 case GL_OBJECT_LINEAR_CHROMIUM:
3487 case GL_EYE_LINEAR_CHROMIUM:
3488 case GL_CONSTANT_CHROMIUM:
3489 if (components < 1 || components > 4)
3490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003492 return false;
3493 }
3494 if (!coeffs)
3495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003496 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003497 return false;
3498 }
3499 break;
3500
3501 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003502 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003503 return false;
3504 }
3505
3506 // If the location is -1 then the command is silently ignored
3507 // and no further validation is needed.
3508 if (location == -1)
3509 return true;
3510
Jamie Madillbd044ed2017-06-05 12:59:21 -04003511 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003512
3513 if (!binding.valid)
3514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003515 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003516 return false;
3517 }
3518
3519 if (binding.type != GL_NONE)
3520 {
3521 GLint expectedComponents = 0;
3522 switch (binding.type)
3523 {
3524 case GL_FLOAT:
3525 expectedComponents = 1;
3526 break;
3527 case GL_FLOAT_VEC2:
3528 expectedComponents = 2;
3529 break;
3530 case GL_FLOAT_VEC3:
3531 expectedComponents = 3;
3532 break;
3533 case GL_FLOAT_VEC4:
3534 expectedComponents = 4;
3535 break;
3536 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003537 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003538 InvalidOperation()
3539 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003540 return false;
3541 }
3542 if (expectedComponents != components && genMode != GL_NONE)
3543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003544 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003545 return false;
3546 }
3547 }
3548 return true;
3549}
3550
Geoff Lang97073d12016-04-20 10:42:34 -07003551bool ValidateCopyTextureCHROMIUM(Context *context,
3552 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003553 GLint sourceLevel,
3554 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003555 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003556 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003557 GLint internalFormat,
3558 GLenum destType,
3559 GLboolean unpackFlipY,
3560 GLboolean unpackPremultiplyAlpha,
3561 GLboolean unpackUnmultiplyAlpha)
3562{
3563 if (!context->getExtensions().copyTexture)
3564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidOperation()
3566 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003567 return false;
3568 }
3569
Geoff Lang4f0e0032017-05-01 16:04:35 -04003570 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003571 if (source == nullptr)
3572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003573 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003574 return false;
3575 }
3576
3577 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003580 return false;
3581 }
3582
3583 GLenum sourceTarget = source->getTarget();
3584 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003585
3586 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003588 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003589 return false;
3590 }
3591
Geoff Lang4f0e0032017-05-01 16:04:35 -04003592 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3593 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3594 if (sourceWidth == 0 || sourceHeight == 0)
3595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003597 return false;
3598 }
3599
3600 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3601 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003604 return false;
3605 }
3606
Geoff Lang4f0e0032017-05-01 16:04:35 -04003607 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003608 if (dest == nullptr)
3609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003610 context->handleError(InvalidValue()
3611 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003612 return false;
3613 }
3614
Geoff Lang4f0e0032017-05-01 16:04:35 -04003615 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003617 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003618 return false;
3619 }
3620
Geoff Lang4f0e0032017-05-01 16:04:35 -04003621 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3622 sourceHeight))
3623 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003624 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003625 return false;
3626 }
3627
Geoff Lang97073d12016-04-20 10:42:34 -07003628 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003631 return false;
3632 }
3633
Geoff Lang4f0e0032017-05-01 16:04:35 -04003634 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003636 context->handleError(
3637 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003638 return false;
3639 }
3640
Geoff Lang97073d12016-04-20 10:42:34 -07003641 if (dest->getImmutableFormat())
3642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003644 return false;
3645 }
3646
3647 return true;
3648}
3649
3650bool ValidateCopySubTextureCHROMIUM(Context *context,
3651 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003652 GLint sourceLevel,
3653 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003654 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003655 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003656 GLint xoffset,
3657 GLint yoffset,
3658 GLint x,
3659 GLint y,
3660 GLsizei width,
3661 GLsizei height,
3662 GLboolean unpackFlipY,
3663 GLboolean unpackPremultiplyAlpha,
3664 GLboolean unpackUnmultiplyAlpha)
3665{
3666 if (!context->getExtensions().copyTexture)
3667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003668 context->handleError(InvalidOperation()
3669 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003670 return false;
3671 }
3672
Geoff Lang4f0e0032017-05-01 16:04:35 -04003673 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003674 if (source == nullptr)
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003677 return false;
3678 }
3679
3680 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003682 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003683 return false;
3684 }
3685
3686 GLenum sourceTarget = source->getTarget();
3687 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003688
3689 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3690 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003691 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003692 return false;
3693 }
3694
3695 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3696 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003698 context->handleError(InvalidValue()
3699 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003700 return false;
3701 }
3702
3703 if (x < 0 || y < 0)
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003706 return false;
3707 }
3708
3709 if (width < 0 || height < 0)
3710 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003711 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003712 return false;
3713 }
3714
Geoff Lang4f0e0032017-05-01 16:04:35 -04003715 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3716 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003717 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003718 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003719 return false;
3720 }
3721
Geoff Lang4f0e0032017-05-01 16:04:35 -04003722 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3723 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003724 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003725 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
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, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003746 return false;
3747 }
3748
Geoff Lang4f0e0032017-05-01 16:04:35 -04003749 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3750 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003751 context
3752 ->handleError(InvalidOperation()
3753 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003754 return false;
3755 }
3756
3757 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3758 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(InvalidOperation()
3761 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003762 return false;
3763 }
3764
3765 if (xoffset < 0 || yoffset < 0)
3766 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003767 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07003768 return false;
3769 }
3770
Geoff Lang4f0e0032017-05-01 16:04:35 -04003771 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3772 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003774 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003775 return false;
3776 }
3777
3778 return true;
3779}
3780
Geoff Lang47110bf2016-04-20 11:13:22 -07003781bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3782{
3783 if (!context->getExtensions().copyCompressedTexture)
3784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003785 context->handleError(InvalidOperation()
3786 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003787 return false;
3788 }
3789
3790 const gl::Texture *source = context->getTexture(sourceId);
3791 if (source == nullptr)
3792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003794 return false;
3795 }
3796
3797 if (source->getTarget() != GL_TEXTURE_2D)
3798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003800 return false;
3801 }
3802
3803 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003806 return false;
3807 }
3808
3809 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3810 if (!sourceFormat.info->compressed)
3811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003812 context->handleError(InvalidOperation()
3813 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003814 return false;
3815 }
3816
3817 const gl::Texture *dest = context->getTexture(destId);
3818 if (dest == nullptr)
3819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003820 context->handleError(InvalidValue()
3821 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003822 return false;
3823 }
3824
3825 if (dest->getTarget() != GL_TEXTURE_2D)
3826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidValue()
3828 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003829 return false;
3830 }
3831
3832 if (dest->getImmutableFormat())
3833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003834 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003835 return false;
3836 }
3837
3838 return true;
3839}
3840
Martin Radev4c4c8e72016-08-04 12:25:34 +03003841bool ValidateCreateShader(Context *context, GLenum type)
3842{
3843 switch (type)
3844 {
3845 case GL_VERTEX_SHADER:
3846 case GL_FRAGMENT_SHADER:
3847 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003848
Martin Radev4c4c8e72016-08-04 12:25:34 +03003849 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003850 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003852 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003853 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003854 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003855 break;
3856
Martin Radev4c4c8e72016-08-04 12:25:34 +03003857 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003858 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03003859 return false;
3860 }
Jamie Madill29639852016-09-02 15:00:09 -04003861
3862 return true;
3863}
3864
3865bool ValidateBufferData(ValidationContext *context,
3866 GLenum target,
3867 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003868 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003869 GLenum usage)
3870{
3871 if (size < 0)
3872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003873 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04003874 return false;
3875 }
3876
3877 switch (usage)
3878 {
3879 case GL_STREAM_DRAW:
3880 case GL_STATIC_DRAW:
3881 case GL_DYNAMIC_DRAW:
3882 break;
3883
3884 case GL_STREAM_READ:
3885 case GL_STREAM_COPY:
3886 case GL_STATIC_READ:
3887 case GL_STATIC_COPY:
3888 case GL_DYNAMIC_READ:
3889 case GL_DYNAMIC_COPY:
3890 if (context->getClientMajorVersion() < 3)
3891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04003893 return false;
3894 }
3895 break;
3896
3897 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04003899 return false;
3900 }
3901
3902 if (!ValidBufferTarget(context, target))
3903 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04003905 return false;
3906 }
3907
3908 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3909
3910 if (!buffer)
3911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04003913 return false;
3914 }
3915
3916 return true;
3917}
3918
3919bool ValidateBufferSubData(ValidationContext *context,
3920 GLenum target,
3921 GLintptr offset,
3922 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003923 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003924{
Brandon Jones6cad5662017-06-14 13:25:13 -07003925 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04003926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003927 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
3928 return false;
3929 }
3930
3931 if (offset < 0)
3932 {
3933 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04003934 return false;
3935 }
3936
3937 if (!ValidBufferTarget(context, target))
3938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003939 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04003940 return false;
3941 }
3942
3943 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3944
3945 if (!buffer)
3946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04003948 return false;
3949 }
3950
3951 if (buffer->isMapped())
3952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003953 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003954 return false;
3955 }
3956
3957 // Check for possible overflow of size + offset
3958 angle::CheckedNumeric<size_t> checkedSize(size);
3959 checkedSize += offset;
3960 if (!checkedSize.IsValid())
3961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003962 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003963 return false;
3964 }
3965
3966 if (size + offset > buffer->getSize())
3967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003968 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04003969 return false;
3970 }
3971
Martin Radev4c4c8e72016-08-04 12:25:34 +03003972 return true;
3973}
3974
Geoff Langc339c4e2016-11-29 10:37:36 -05003975bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003976{
Geoff Langc339c4e2016-11-29 10:37:36 -05003977 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003979 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003980 return false;
3981 }
3982
3983 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3984 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003985 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003988 return false;
3989 }
3990
3991 return true;
3992}
3993
Jamie Madillef300b12016-10-07 15:12:09 -04003994bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3995{
3996 if (texture < GL_TEXTURE0 ||
3997 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003999 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004000 return false;
4001 }
4002
4003 return true;
4004}
4005
4006bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4007{
4008 Program *programObject = GetValidProgram(context, program);
4009 if (!programObject)
4010 {
4011 return false;
4012 }
4013
4014 Shader *shaderObject = GetValidShader(context, shader);
4015 if (!shaderObject)
4016 {
4017 return false;
4018 }
4019
4020 switch (shaderObject->getType())
4021 {
4022 case GL_VERTEX_SHADER:
4023 {
4024 if (programObject->getAttachedVertexShader())
4025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004027 return false;
4028 }
4029 break;
4030 }
4031 case GL_FRAGMENT_SHADER:
4032 {
4033 if (programObject->getAttachedFragmentShader())
4034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004035 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004036 return false;
4037 }
4038 break;
4039 }
4040 case GL_COMPUTE_SHADER:
4041 {
4042 if (programObject->getAttachedComputeShader())
4043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004044 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004045 return false;
4046 }
4047 break;
4048 }
4049 default:
4050 UNREACHABLE();
4051 break;
4052 }
4053
4054 return true;
4055}
4056
Jamie Madill01a80ee2016-11-07 12:06:18 -05004057bool ValidateBindAttribLocation(ValidationContext *context,
4058 GLuint program,
4059 GLuint index,
4060 const GLchar *name)
4061{
4062 if (index >= MAX_VERTEX_ATTRIBS)
4063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004064 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004065 return false;
4066 }
4067
4068 if (strncmp(name, "gl_", 3) == 0)
4069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004071 return false;
4072 }
4073
Geoff Langfc32e8b2017-05-31 14:16:59 -04004074 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4075 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004076 if (context->getExtensions().webglCompatibility &&
4077 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004079 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004080 return false;
4081 }
4082
Jamie Madill01a80ee2016-11-07 12:06:18 -05004083 return GetValidProgram(context, program) != nullptr;
4084}
4085
4086bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4087{
4088 if (!ValidBufferTarget(context, target))
4089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004091 return false;
4092 }
4093
4094 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4095 !context->isBufferGenerated(buffer))
4096 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004098 return false;
4099 }
4100
4101 return true;
4102}
4103
4104bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4105{
4106 if (!ValidFramebufferTarget(target))
4107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004108 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004109 return false;
4110 }
4111
4112 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4113 !context->isFramebufferGenerated(framebuffer))
4114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004116 return false;
4117 }
4118
4119 return true;
4120}
4121
4122bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4123{
4124 if (target != GL_RENDERBUFFER)
4125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004127 return false;
4128 }
4129
4130 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4131 !context->isRenderbufferGenerated(renderbuffer))
4132 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004134 return false;
4135 }
4136
4137 return true;
4138}
4139
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004140static bool ValidBlendEquationMode(GLenum mode)
4141{
4142 switch (mode)
4143 {
4144 case GL_FUNC_ADD:
4145 case GL_FUNC_SUBTRACT:
4146 case GL_FUNC_REVERSE_SUBTRACT:
4147 case GL_MIN:
4148 case GL_MAX:
4149 return true;
4150
4151 default:
4152 return false;
4153 }
4154}
4155
Jamie Madillc1d770e2017-04-13 17:31:24 -04004156bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004157 GLfloat red,
4158 GLfloat green,
4159 GLfloat blue,
4160 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004161{
4162 return true;
4163}
4164
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004165bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4166{
4167 if (!ValidBlendEquationMode(mode))
4168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004169 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004170 return false;
4171 }
4172
4173 return true;
4174}
4175
4176bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4177{
4178 if (!ValidBlendEquationMode(modeRGB))
4179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004181 return false;
4182 }
4183
4184 if (!ValidBlendEquationMode(modeAlpha))
4185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004187 return false;
4188 }
4189
4190 return true;
4191}
4192
4193bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4194{
4195 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4196}
4197
4198static bool ValidSrcBlendFunc(GLenum srcBlend)
4199{
4200 switch (srcBlend)
4201 {
4202 case GL_ZERO:
4203 case GL_ONE:
4204 case GL_SRC_COLOR:
4205 case GL_ONE_MINUS_SRC_COLOR:
4206 case GL_DST_COLOR:
4207 case GL_ONE_MINUS_DST_COLOR:
4208 case GL_SRC_ALPHA:
4209 case GL_ONE_MINUS_SRC_ALPHA:
4210 case GL_DST_ALPHA:
4211 case GL_ONE_MINUS_DST_ALPHA:
4212 case GL_CONSTANT_COLOR:
4213 case GL_ONE_MINUS_CONSTANT_COLOR:
4214 case GL_CONSTANT_ALPHA:
4215 case GL_ONE_MINUS_CONSTANT_ALPHA:
4216 case GL_SRC_ALPHA_SATURATE:
4217 return true;
4218
4219 default:
4220 return false;
4221 }
4222}
4223
4224static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4225{
4226 switch (dstBlend)
4227 {
4228 case GL_ZERO:
4229 case GL_ONE:
4230 case GL_SRC_COLOR:
4231 case GL_ONE_MINUS_SRC_COLOR:
4232 case GL_DST_COLOR:
4233 case GL_ONE_MINUS_DST_COLOR:
4234 case GL_SRC_ALPHA:
4235 case GL_ONE_MINUS_SRC_ALPHA:
4236 case GL_DST_ALPHA:
4237 case GL_ONE_MINUS_DST_ALPHA:
4238 case GL_CONSTANT_COLOR:
4239 case GL_ONE_MINUS_CONSTANT_COLOR:
4240 case GL_CONSTANT_ALPHA:
4241 case GL_ONE_MINUS_CONSTANT_ALPHA:
4242 return true;
4243
4244 case GL_SRC_ALPHA_SATURATE:
4245 return (contextMajorVersion >= 3);
4246
4247 default:
4248 return false;
4249 }
4250}
4251
4252bool ValidateBlendFuncSeparate(ValidationContext *context,
4253 GLenum srcRGB,
4254 GLenum dstRGB,
4255 GLenum srcAlpha,
4256 GLenum dstAlpha)
4257{
4258 if (!ValidSrcBlendFunc(srcRGB))
4259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004260 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004261 return false;
4262 }
4263
4264 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004267 return false;
4268 }
4269
4270 if (!ValidSrcBlendFunc(srcAlpha))
4271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004273 return false;
4274 }
4275
4276 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004279 return false;
4280 }
4281
Frank Henigman146e8a12017-03-02 23:22:37 -05004282 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4283 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004284 {
4285 bool constantColorUsed =
4286 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4287 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4288
4289 bool constantAlphaUsed =
4290 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4291 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4292
4293 if (constantColorUsed && constantAlphaUsed)
4294 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004295 const char *msg;
4296 if (context->getExtensions().webglCompatibility)
4297 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004298 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004299 }
4300 else
4301 {
4302 msg =
4303 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4304 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4305 "implementation.";
4306 ERR() << msg;
4307 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004308 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004309 return false;
4310 }
4311 }
4312
4313 return true;
4314}
4315
Geoff Langc339c4e2016-11-29 10:37:36 -05004316bool ValidateGetString(Context *context, GLenum name)
4317{
4318 switch (name)
4319 {
4320 case GL_VENDOR:
4321 case GL_RENDERER:
4322 case GL_VERSION:
4323 case GL_SHADING_LANGUAGE_VERSION:
4324 case GL_EXTENSIONS:
4325 break;
4326
4327 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4328 if (!context->getExtensions().requestExtension)
4329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004330 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004331 return false;
4332 }
4333 break;
4334
4335 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004336 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004337 return false;
4338 }
4339
4340 return true;
4341}
4342
Geoff Lang47c48082016-12-07 15:38:13 -05004343bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4344{
4345 if (width <= 0.0f || isNaN(width))
4346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004347 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004348 return false;
4349 }
4350
4351 return true;
4352}
4353
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004354bool ValidateVertexAttribPointer(ValidationContext *context,
4355 GLuint index,
4356 GLint size,
4357 GLenum type,
4358 GLboolean normalized,
4359 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004360 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004361{
Shao80957d92017-02-20 21:25:59 +08004362 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004363 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004364 return false;
4365 }
4366
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004367 if (stride < 0)
4368 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004369 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004370 return false;
4371 }
4372
Shao80957d92017-02-20 21:25:59 +08004373 const Caps &caps = context->getCaps();
4374 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004375 {
Shao80957d92017-02-20 21:25:59 +08004376 if (stride > caps.maxVertexAttribStride)
4377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004378 context->handleError(InvalidValue()
4379 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004380 return false;
4381 }
4382
4383 if (index >= caps.maxVertexAttribBindings)
4384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004385 context->handleError(InvalidValue()
4386 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004387 return false;
4388 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004389 }
4390
4391 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4392 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4393 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4394 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004395 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4396 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004397 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004399 context
4400 ->handleError(InvalidOperation()
4401 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004402 return false;
4403 }
4404
4405 if (context->getExtensions().webglCompatibility)
4406 {
4407 // WebGL 1.0 [Section 6.14] Fixed point support
4408 // The WebGL API does not support the GL_FIXED data type.
4409 if (type == GL_FIXED)
4410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004411 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004412 return false;
4413 }
4414
Geoff Lang2d62ab72017-03-23 16:54:40 -04004415 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004416 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004417 return false;
4418 }
4419 }
4420
4421 return true;
4422}
4423
Jamie Madill876429b2017-04-20 15:46:24 -04004424bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004425{
4426 if (context->getExtensions().webglCompatibility && zNear > zFar)
4427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004429 return false;
4430 }
4431
4432 return true;
4433}
4434
Jamie Madille8fb6402017-02-14 17:56:40 -05004435bool ValidateRenderbufferStorage(ValidationContext *context,
4436 GLenum target,
4437 GLenum internalformat,
4438 GLsizei width,
4439 GLsizei height)
4440{
4441 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4442 height);
4443}
4444
4445bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4446 GLenum target,
4447 GLsizei samples,
4448 GLenum internalformat,
4449 GLsizei width,
4450 GLsizei height)
4451{
4452 if (!context->getExtensions().framebufferMultisample)
4453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004454 context->handleError(InvalidOperation()
4455 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004456 return false;
4457 }
4458
4459 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4460 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4461 // generated.
4462 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004464 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004465 return false;
4466 }
4467
4468 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4469 // the specified storage. This is different than ES 3.0 in which a sample number higher
4470 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4471 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4472 if (context->getClientMajorVersion() >= 3)
4473 {
4474 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4475 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004477 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004478 return false;
4479 }
4480 }
4481
4482 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4483 width, height);
4484}
4485
Jamie Madillc1d770e2017-04-13 17:31:24 -04004486bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4487{
4488 if (!ValidFramebufferTarget(target))
4489 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004491 return false;
4492 }
4493
4494 return true;
4495}
4496
4497bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004498 GLfloat red,
4499 GLfloat green,
4500 GLfloat blue,
4501 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004502{
4503 return true;
4504}
4505
Jamie Madill876429b2017-04-20 15:46:24 -04004506bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004507{
4508 return true;
4509}
4510
4511bool ValidateClearStencil(ValidationContext *context, GLint s)
4512{
4513 return true;
4514}
4515
4516bool ValidateColorMask(ValidationContext *context,
4517 GLboolean red,
4518 GLboolean green,
4519 GLboolean blue,
4520 GLboolean alpha)
4521{
4522 return true;
4523}
4524
4525bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4526{
4527 return true;
4528}
4529
4530bool ValidateCreateProgram(ValidationContext *context)
4531{
4532 return true;
4533}
4534
4535bool ValidateCullFace(ValidationContext *context, GLenum mode)
4536{
4537 switch (mode)
4538 {
4539 case GL_FRONT:
4540 case GL_BACK:
4541 case GL_FRONT_AND_BACK:
4542 break;
4543
4544 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004546 return false;
4547 }
4548
4549 return true;
4550}
4551
4552bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4553{
4554 if (program == 0)
4555 {
4556 return false;
4557 }
4558
4559 if (!context->getProgram(program))
4560 {
4561 if (context->getShader(program))
4562 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004563 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004564 return false;
4565 }
4566 else
4567 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004568 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004569 return false;
4570 }
4571 }
4572
4573 return true;
4574}
4575
4576bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4577{
4578 if (shader == 0)
4579 {
4580 return false;
4581 }
4582
4583 if (!context->getShader(shader))
4584 {
4585 if (context->getProgram(shader))
4586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004588 return false;
4589 }
4590 else
4591 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004592 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004593 return false;
4594 }
4595 }
4596
4597 return true;
4598}
4599
4600bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4601{
4602 switch (func)
4603 {
4604 case GL_NEVER:
4605 case GL_ALWAYS:
4606 case GL_LESS:
4607 case GL_LEQUAL:
4608 case GL_EQUAL:
4609 case GL_GREATER:
4610 case GL_GEQUAL:
4611 case GL_NOTEQUAL:
4612 break;
4613
4614 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004616 return false;
4617 }
4618
4619 return true;
4620}
4621
4622bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4623{
4624 return true;
4625}
4626
4627bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4628{
4629 Program *programObject = GetValidProgram(context, program);
4630 if (!programObject)
4631 {
4632 return false;
4633 }
4634
4635 Shader *shaderObject = GetValidShader(context, shader);
4636 if (!shaderObject)
4637 {
4638 return false;
4639 }
4640
4641 const Shader *attachedShader = nullptr;
4642
4643 switch (shaderObject->getType())
4644 {
4645 case GL_VERTEX_SHADER:
4646 {
4647 attachedShader = programObject->getAttachedVertexShader();
4648 break;
4649 }
4650 case GL_FRAGMENT_SHADER:
4651 {
4652 attachedShader = programObject->getAttachedFragmentShader();
4653 break;
4654 }
4655 case GL_COMPUTE_SHADER:
4656 {
4657 attachedShader = programObject->getAttachedComputeShader();
4658 break;
4659 }
4660 default:
4661 UNREACHABLE();
4662 return false;
4663 }
4664
4665 if (attachedShader != shaderObject)
4666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004668 return false;
4669 }
4670
4671 return true;
4672}
4673
4674bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4675{
4676 if (index >= MAX_VERTEX_ATTRIBS)
4677 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004678 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004679 return false;
4680 }
4681
4682 return true;
4683}
4684
4685bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4686{
4687 if (index >= MAX_VERTEX_ATTRIBS)
4688 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004689 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004690 return false;
4691 }
4692
4693 return true;
4694}
4695
4696bool ValidateFinish(ValidationContext *context)
4697{
4698 return true;
4699}
4700
4701bool ValidateFlush(ValidationContext *context)
4702{
4703 return true;
4704}
4705
4706bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4707{
4708 switch (mode)
4709 {
4710 case GL_CW:
4711 case GL_CCW:
4712 break;
4713 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004714 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004715 return false;
4716 }
4717
4718 return true;
4719}
4720
4721bool ValidateGetActiveAttrib(ValidationContext *context,
4722 GLuint program,
4723 GLuint index,
4724 GLsizei bufsize,
4725 GLsizei *length,
4726 GLint *size,
4727 GLenum *type,
4728 GLchar *name)
4729{
4730 if (bufsize < 0)
4731 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004732 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004733 return false;
4734 }
4735
4736 Program *programObject = GetValidProgram(context, program);
4737
4738 if (!programObject)
4739 {
4740 return false;
4741 }
4742
4743 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004745 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004746 return false;
4747 }
4748
4749 return true;
4750}
4751
4752bool ValidateGetActiveUniform(ValidationContext *context,
4753 GLuint program,
4754 GLuint index,
4755 GLsizei bufsize,
4756 GLsizei *length,
4757 GLint *size,
4758 GLenum *type,
4759 GLchar *name)
4760{
4761 if (bufsize < 0)
4762 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004763 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004764 return false;
4765 }
4766
4767 Program *programObject = GetValidProgram(context, program);
4768
4769 if (!programObject)
4770 {
4771 return false;
4772 }
4773
4774 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004776 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004777 return false;
4778 }
4779
4780 return true;
4781}
4782
4783bool ValidateGetAttachedShaders(ValidationContext *context,
4784 GLuint program,
4785 GLsizei maxcount,
4786 GLsizei *count,
4787 GLuint *shaders)
4788{
4789 if (maxcount < 0)
4790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004791 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004792 return false;
4793 }
4794
4795 Program *programObject = GetValidProgram(context, program);
4796
4797 if (!programObject)
4798 {
4799 return false;
4800 }
4801
4802 return true;
4803}
4804
4805bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4806{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004807 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4808 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004809 if (context->getExtensions().webglCompatibility &&
4810 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004811 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004812 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004813 return false;
4814 }
4815
Jamie Madillc1d770e2017-04-13 17:31:24 -04004816 Program *programObject = GetValidProgram(context, program);
4817
4818 if (!programObject)
4819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004820 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004821 return false;
4822 }
4823
4824 if (!programObject->isLinked())
4825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004827 return false;
4828 }
4829
4830 return true;
4831}
4832
4833bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4834{
4835 GLenum nativeType;
4836 unsigned int numParams = 0;
4837 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4838}
4839
4840bool ValidateGetError(ValidationContext *context)
4841{
4842 return true;
4843}
4844
4845bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4846{
4847 GLenum nativeType;
4848 unsigned int numParams = 0;
4849 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4850}
4851
4852bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4853{
4854 GLenum nativeType;
4855 unsigned int numParams = 0;
4856 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4857}
4858
4859bool ValidateGetProgramInfoLog(ValidationContext *context,
4860 GLuint program,
4861 GLsizei bufsize,
4862 GLsizei *length,
4863 GLchar *infolog)
4864{
4865 if (bufsize < 0)
4866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004867 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004868 return false;
4869 }
4870
4871 Program *programObject = GetValidProgram(context, program);
4872 if (!programObject)
4873 {
4874 return false;
4875 }
4876
4877 return true;
4878}
4879
4880bool ValidateGetShaderInfoLog(ValidationContext *context,
4881 GLuint shader,
4882 GLsizei bufsize,
4883 GLsizei *length,
4884 GLchar *infolog)
4885{
4886 if (bufsize < 0)
4887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004888 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004889 return false;
4890 }
4891
4892 Shader *shaderObject = GetValidShader(context, shader);
4893 if (!shaderObject)
4894 {
4895 return false;
4896 }
4897
4898 return true;
4899}
4900
4901bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4902 GLenum shadertype,
4903 GLenum precisiontype,
4904 GLint *range,
4905 GLint *precision)
4906{
4907 switch (shadertype)
4908 {
4909 case GL_VERTEX_SHADER:
4910 case GL_FRAGMENT_SHADER:
4911 break;
4912 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004913 context->handleError(InvalidOperation()
4914 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004915 return false;
4916 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004918 return false;
4919 }
4920
4921 switch (precisiontype)
4922 {
4923 case GL_LOW_FLOAT:
4924 case GL_MEDIUM_FLOAT:
4925 case GL_HIGH_FLOAT:
4926 case GL_LOW_INT:
4927 case GL_MEDIUM_INT:
4928 case GL_HIGH_INT:
4929 break;
4930
4931 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004933 return false;
4934 }
4935
4936 return true;
4937}
4938
4939bool ValidateGetShaderSource(ValidationContext *context,
4940 GLuint shader,
4941 GLsizei bufsize,
4942 GLsizei *length,
4943 GLchar *source)
4944{
4945 if (bufsize < 0)
4946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004947 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004948 return false;
4949 }
4950
4951 Shader *shaderObject = GetValidShader(context, shader);
4952 if (!shaderObject)
4953 {
4954 return false;
4955 }
4956
4957 return true;
4958}
4959
4960bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4961{
4962 if (strstr(name, "gl_") == name)
4963 {
4964 return false;
4965 }
4966
Geoff Langfc32e8b2017-05-31 14:16:59 -04004967 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4968 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004969 if (context->getExtensions().webglCompatibility &&
4970 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004972 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004973 return false;
4974 }
4975
Jamie Madillc1d770e2017-04-13 17:31:24 -04004976 Program *programObject = GetValidProgram(context, program);
4977
4978 if (!programObject)
4979 {
4980 return false;
4981 }
4982
4983 if (!programObject->isLinked())
4984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004986 return false;
4987 }
4988
4989 return true;
4990}
4991
4992bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4993{
4994 switch (mode)
4995 {
4996 case GL_FASTEST:
4997 case GL_NICEST:
4998 case GL_DONT_CARE:
4999 break;
5000
5001 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005002 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005003 return false;
5004 }
5005
5006 switch (target)
5007 {
5008 case GL_GENERATE_MIPMAP_HINT:
5009 break;
5010
Geoff Lange7bd2182017-06-16 16:13:13 -04005011 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5012 if (context->getClientVersion() < ES_3_0 &&
5013 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005015 context->handleError(InvalidOperation()
5016 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005017 return false;
5018 }
5019 break;
5020
5021 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005023 return false;
5024 }
5025
5026 return true;
5027}
5028
5029bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5030{
5031 return true;
5032}
5033
5034bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5035{
5036 return true;
5037}
5038
5039bool ValidateIsProgram(ValidationContext *context, GLuint program)
5040{
5041 return true;
5042}
5043
5044bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5045{
5046 return true;
5047}
5048
5049bool ValidateIsShader(ValidationContext *context, GLuint shader)
5050{
5051 return true;
5052}
5053
5054bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5055{
5056 return true;
5057}
5058
5059bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5060{
5061 if (context->getClientMajorVersion() < 3)
5062 {
5063 switch (pname)
5064 {
5065 case GL_UNPACK_IMAGE_HEIGHT:
5066 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005067 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005068 return false;
5069
5070 case GL_UNPACK_ROW_LENGTH:
5071 case GL_UNPACK_SKIP_ROWS:
5072 case GL_UNPACK_SKIP_PIXELS:
5073 if (!context->getExtensions().unpackSubimage)
5074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005075 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005076 return false;
5077 }
5078 break;
5079
5080 case GL_PACK_ROW_LENGTH:
5081 case GL_PACK_SKIP_ROWS:
5082 case GL_PACK_SKIP_PIXELS:
5083 if (!context->getExtensions().packSubimage)
5084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005085 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005086 return false;
5087 }
5088 break;
5089 }
5090 }
5091
5092 if (param < 0)
5093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005094 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005095 return false;
5096 }
5097
5098 switch (pname)
5099 {
5100 case GL_UNPACK_ALIGNMENT:
5101 if (param != 1 && param != 2 && param != 4 && param != 8)
5102 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005103 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005104 return false;
5105 }
5106 break;
5107
5108 case GL_PACK_ALIGNMENT:
5109 if (param != 1 && param != 2 && param != 4 && param != 8)
5110 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005111 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005112 return false;
5113 }
5114 break;
5115
5116 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5117 case GL_UNPACK_ROW_LENGTH:
5118 case GL_UNPACK_IMAGE_HEIGHT:
5119 case GL_UNPACK_SKIP_IMAGES:
5120 case GL_UNPACK_SKIP_ROWS:
5121 case GL_UNPACK_SKIP_PIXELS:
5122 case GL_PACK_ROW_LENGTH:
5123 case GL_PACK_SKIP_ROWS:
5124 case GL_PACK_SKIP_PIXELS:
5125 break;
5126
5127 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005129 return false;
5130 }
5131
5132 return true;
5133}
5134
5135bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5136{
5137 return true;
5138}
5139
5140bool ValidateReleaseShaderCompiler(ValidationContext *context)
5141{
5142 return true;
5143}
5144
Jamie Madill876429b2017-04-20 15:46:24 -04005145bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005146{
5147 return true;
5148}
5149
5150bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5151{
5152 if (width < 0 || height < 0)
5153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005154 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005155 return false;
5156 }
5157
5158 return true;
5159}
5160
5161bool ValidateShaderBinary(ValidationContext *context,
5162 GLsizei n,
5163 const GLuint *shaders,
5164 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005165 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005166 GLsizei length)
5167{
5168 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5169 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5170 shaderBinaryFormats.end())
5171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005172 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005173 return false;
5174 }
5175
5176 return true;
5177}
5178
5179bool ValidateShaderSource(ValidationContext *context,
5180 GLuint shader,
5181 GLsizei count,
5182 const GLchar *const *string,
5183 const GLint *length)
5184{
5185 if (count < 0)
5186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005187 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005188 return false;
5189 }
5190
Geoff Langfc32e8b2017-05-31 14:16:59 -04005191 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5192 // shader-related entry points
5193 if (context->getExtensions().webglCompatibility)
5194 {
5195 for (GLsizei i = 0; i < count; i++)
5196 {
5197 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005198
5199 // Backslash as line-continuation is allowed in WebGL 2.0.
5200 if (!IsValidESSLString(string[i], len, context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005202 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005203 return false;
5204 }
5205 }
5206 }
5207
Jamie Madillc1d770e2017-04-13 17:31:24 -04005208 Shader *shaderObject = GetValidShader(context, shader);
5209 if (!shaderObject)
5210 {
5211 return false;
5212 }
5213
5214 return true;
5215}
5216
5217bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5218{
5219 if (!IsValidStencilFunc(func))
5220 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005222 return false;
5223 }
5224
5225 return true;
5226}
5227
5228bool ValidateStencilFuncSeparate(ValidationContext *context,
5229 GLenum face,
5230 GLenum func,
5231 GLint ref,
5232 GLuint mask)
5233{
5234 if (!IsValidStencilFace(face))
5235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005236 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005237 return false;
5238 }
5239
5240 if (!IsValidStencilFunc(func))
5241 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005242 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005243 return false;
5244 }
5245
5246 return true;
5247}
5248
5249bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5250{
5251 return true;
5252}
5253
5254bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5255{
5256 if (!IsValidStencilFace(face))
5257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005258 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005259 return false;
5260 }
5261
5262 return true;
5263}
5264
5265bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5266{
5267 if (!IsValidStencilOp(fail))
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005270 return false;
5271 }
5272
5273 if (!IsValidStencilOp(zfail))
5274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005276 return false;
5277 }
5278
5279 if (!IsValidStencilOp(zpass))
5280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005282 return false;
5283 }
5284
5285 return true;
5286}
5287
5288bool ValidateStencilOpSeparate(ValidationContext *context,
5289 GLenum face,
5290 GLenum fail,
5291 GLenum zfail,
5292 GLenum zpass)
5293{
5294 if (!IsValidStencilFace(face))
5295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005297 return false;
5298 }
5299
5300 return ValidateStencilOp(context, fail, zfail, zpass);
5301}
5302
5303bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5304{
5305 return ValidateUniform(context, GL_FLOAT, location, 1);
5306}
5307
5308bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5309{
5310 return ValidateUniform(context, GL_FLOAT, location, count);
5311}
5312
Jamie Madillbe849e42017-05-02 15:49:00 -04005313bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5314{
5315 return ValidateUniform1iv(context, location, 1, &x);
5316}
5317
Jamie Madillc1d770e2017-04-13 17:31:24 -04005318bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5319{
5320 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5321}
5322
5323bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5324{
5325 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5326}
5327
5328bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5329{
5330 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5331}
5332
5333bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5334{
5335 return ValidateUniform(context, GL_INT_VEC2, location, count);
5336}
5337
5338bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5339{
5340 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5341}
5342
5343bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5344{
5345 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5346}
5347
5348bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5349{
5350 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5351}
5352
5353bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5354{
5355 return ValidateUniform(context, GL_INT_VEC3, location, count);
5356}
5357
5358bool ValidateUniform4f(ValidationContext *context,
5359 GLint location,
5360 GLfloat x,
5361 GLfloat y,
5362 GLfloat z,
5363 GLfloat w)
5364{
5365 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5366}
5367
5368bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5369{
5370 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5371}
5372
5373bool ValidateUniform4i(ValidationContext *context,
5374 GLint location,
5375 GLint x,
5376 GLint y,
5377 GLint z,
5378 GLint w)
5379{
5380 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5381}
5382
5383bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5384{
5385 return ValidateUniform(context, GL_INT_VEC4, location, count);
5386}
5387
5388bool ValidateUniformMatrix2fv(ValidationContext *context,
5389 GLint location,
5390 GLsizei count,
5391 GLboolean transpose,
5392 const GLfloat *value)
5393{
5394 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5395}
5396
5397bool ValidateUniformMatrix3fv(ValidationContext *context,
5398 GLint location,
5399 GLsizei count,
5400 GLboolean transpose,
5401 const GLfloat *value)
5402{
5403 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5404}
5405
5406bool ValidateUniformMatrix4fv(ValidationContext *context,
5407 GLint location,
5408 GLsizei count,
5409 GLboolean transpose,
5410 const GLfloat *value)
5411{
5412 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5413}
5414
5415bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5416{
5417 Program *programObject = GetValidProgram(context, program);
5418
5419 if (!programObject)
5420 {
5421 return false;
5422 }
5423
5424 return true;
5425}
5426
5427bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5428{
5429 if (index >= MAX_VERTEX_ATTRIBS)
5430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005431 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005432 return false;
5433 }
5434
5435 return true;
5436}
5437
5438bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5439{
5440 return ValidateVertexAttribIndex(context, index);
5441}
5442
5443bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5444{
5445 return ValidateVertexAttribIndex(context, index);
5446}
5447
5448bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5449{
5450 return ValidateVertexAttribIndex(context, index);
5451}
5452
5453bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5454{
5455 return ValidateVertexAttribIndex(context, index);
5456}
5457
5458bool ValidateVertexAttrib3f(ValidationContext *context,
5459 GLuint index,
5460 GLfloat x,
5461 GLfloat y,
5462 GLfloat z)
5463{
5464 return ValidateVertexAttribIndex(context, index);
5465}
5466
5467bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5468{
5469 return ValidateVertexAttribIndex(context, index);
5470}
5471
5472bool ValidateVertexAttrib4f(ValidationContext *context,
5473 GLuint index,
5474 GLfloat x,
5475 GLfloat y,
5476 GLfloat z,
5477 GLfloat w)
5478{
5479 return ValidateVertexAttribIndex(context, index);
5480}
5481
5482bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5483{
5484 return ValidateVertexAttribIndex(context, index);
5485}
5486
5487bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5488{
5489 if (width < 0 || height < 0)
5490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005492 return false;
5493 }
5494
5495 return true;
5496}
5497
5498bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5499{
5500 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5501}
5502
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005503bool ValidateDrawElements(ValidationContext *context,
5504 GLenum mode,
5505 GLsizei count,
5506 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005507 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005508{
5509 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5510}
5511
Jamie Madillbe849e42017-05-02 15:49:00 -04005512bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5513 GLenum target,
5514 GLenum attachment,
5515 GLenum pname,
5516 GLint *params)
5517{
5518 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5519 nullptr);
5520}
5521
5522bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5523{
5524 return ValidateGetProgramivBase(context, program, pname, nullptr);
5525}
5526
5527bool ValidateCopyTexImage2D(ValidationContext *context,
5528 GLenum target,
5529 GLint level,
5530 GLenum internalformat,
5531 GLint x,
5532 GLint y,
5533 GLsizei width,
5534 GLsizei height,
5535 GLint border)
5536{
5537 if (context->getClientMajorVersion() < 3)
5538 {
5539 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5540 0, x, y, width, height, border);
5541 }
5542
5543 ASSERT(context->getClientMajorVersion() == 3);
5544 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5545 0, x, y, width, height, border);
5546}
5547
5548bool ValidateCopyTexSubImage2D(Context *context,
5549 GLenum target,
5550 GLint level,
5551 GLint xoffset,
5552 GLint yoffset,
5553 GLint x,
5554 GLint y,
5555 GLsizei width,
5556 GLsizei height)
5557{
5558 if (context->getClientMajorVersion() < 3)
5559 {
5560 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5561 yoffset, x, y, width, height, 0);
5562 }
5563
5564 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5565 yoffset, 0, x, y, width, height, 0);
5566}
5567
5568bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5569{
5570 return ValidateGenOrDelete(context, n);
5571}
5572
5573bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5574{
5575 return ValidateGenOrDelete(context, n);
5576}
5577
5578bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5579{
5580 return ValidateGenOrDelete(context, n);
5581}
5582
5583bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5584{
5585 return ValidateGenOrDelete(context, n);
5586}
5587
5588bool ValidateDisable(Context *context, GLenum cap)
5589{
5590 if (!ValidCap(context, cap, false))
5591 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005592 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
5595
5596 return true;
5597}
5598
5599bool ValidateEnable(Context *context, GLenum cap)
5600{
5601 if (!ValidCap(context, cap, false))
5602 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005603 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005604 return false;
5605 }
5606
5607 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5608 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5609 {
5610 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005611 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005612
5613 // We also output an error message to the debugger window if tracing is active, so that
5614 // developers can see the error message.
5615 ERR() << errorMessage;
5616 return false;
5617 }
5618
5619 return true;
5620}
5621
5622bool ValidateFramebufferRenderbuffer(Context *context,
5623 GLenum target,
5624 GLenum attachment,
5625 GLenum renderbuffertarget,
5626 GLuint renderbuffer)
5627{
Brandon Jones6cad5662017-06-14 13:25:13 -07005628 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5631 return false;
5632 }
5633
5634 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5635 {
5636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 return false;
5638 }
5639
5640 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5641 renderbuffertarget, renderbuffer);
5642}
5643
5644bool ValidateFramebufferTexture2D(Context *context,
5645 GLenum target,
5646 GLenum attachment,
5647 GLenum textarget,
5648 GLuint texture,
5649 GLint level)
5650{
5651 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5652 // extension
5653 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5654 level != 0)
5655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005656 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005657 return false;
5658 }
5659
5660 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5661 {
5662 return false;
5663 }
5664
5665 if (texture != 0)
5666 {
5667 gl::Texture *tex = context->getTexture(texture);
5668 ASSERT(tex);
5669
5670 const gl::Caps &caps = context->getCaps();
5671
5672 switch (textarget)
5673 {
5674 case GL_TEXTURE_2D:
5675 {
5676 if (level > gl::log2(caps.max2DTextureSize))
5677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005678 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005679 return false;
5680 }
5681 if (tex->getTarget() != GL_TEXTURE_2D)
5682 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 return false;
5685 }
5686 }
5687 break;
5688
5689 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5690 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5691 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5692 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5693 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5694 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5695 {
5696 if (level > gl::log2(caps.maxCubeMapTextureSize))
5697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005698 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005699 return false;
5700 }
5701 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005703 context->handleError(InvalidOperation()
5704 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005705 return false;
5706 }
5707 }
5708 break;
5709
5710 case GL_TEXTURE_2D_MULTISAMPLE:
5711 {
5712 if (context->getClientVersion() < ES_3_1)
5713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005714 context->handleError(InvalidOperation()
5715 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005716 return false;
5717 }
5718
5719 if (level != 0)
5720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005721 context->handleError(InvalidValue()
5722 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005723 return false;
5724 }
5725 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005727 context->handleError(InvalidOperation()
5728 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005729 return false;
5730 }
5731 }
5732 break;
5733
5734 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005736 return false;
5737 }
5738
5739 const Format &format = tex->getFormat(textarget, level);
5740 if (format.info->compressed)
5741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005742 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005743 return false;
5744 }
5745 }
5746
5747 return true;
5748}
5749
5750bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5751{
5752 return ValidateGenOrDelete(context, n);
5753}
5754
5755bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5756{
5757 return ValidateGenOrDelete(context, n);
5758}
5759
5760bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5761{
5762 return ValidateGenOrDelete(context, n);
5763}
5764
5765bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5766{
5767 return ValidateGenOrDelete(context, n);
5768}
5769
5770bool ValidateGenerateMipmap(Context *context, GLenum target)
5771{
5772 if (!ValidTextureTarget(context, target))
5773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005774 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005775 return false;
5776 }
5777
5778 Texture *texture = context->getTargetTexture(target);
5779
5780 if (texture == nullptr)
5781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005783 return false;
5784 }
5785
5786 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5787
5788 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5789 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5790 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005792 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 return false;
5794 }
5795
5796 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5797 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5798 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5799
Brandon Jones6cad5662017-06-14 13:25:13 -07005800 if (format.info->compressed)
5801 {
5802 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
5803 return false;
5804 }
5805
Jamie Madillbe849e42017-05-02 15:49:00 -04005806 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
Brandon Jones6cad5662017-06-14 13:25:13 -07005807 // unsized formats or that are color renderable and filterable. Since we do not track if
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 // the texture was created with sized or unsized format (only sized formats are stored),
5809 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5810 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5811 // textures since they're the only texture format that can be created with unsized formats
5812 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5813 // was the last version to use add them.
5814 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
Brandon Jones6cad5662017-06-14 13:25:13 -07005815 (!formatCaps.renderable && !format.info->isLUMA()))
Jamie Madillbe849e42017-05-02 15:49:00 -04005816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005817 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 return false;
5819 }
5820
Geoff Lang65ac5b92017-05-01 13:16:30 -04005821 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5822 bool supportsSRGBMipmapGeneration =
5823 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5824 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005826 context->handleError(InvalidOperation()
5827 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005828 return false;
5829 }
5830
5831 // Non-power of 2 ES2 check
5832 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5833 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5834 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5835 {
5836 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07005837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 return false;
5839 }
5840
5841 // Cube completeness check
5842 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04005845 return false;
5846 }
5847
5848 return true;
5849}
5850
5851bool ValidateGetBufferParameteriv(ValidationContext *context,
5852 GLenum target,
5853 GLenum pname,
5854 GLint *params)
5855{
5856 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5857}
5858
5859bool ValidateGetRenderbufferParameteriv(Context *context,
5860 GLenum target,
5861 GLenum pname,
5862 GLint *params)
5863{
5864 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5865}
5866
5867bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5868{
5869 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5870}
5871
5872bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5873{
5874 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5875}
5876
5877bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5878{
5879 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5880}
5881
5882bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5883{
5884 return ValidateGetUniformBase(context, program, location);
5885}
5886
5887bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5888{
5889 return ValidateGetUniformBase(context, program, location);
5890}
5891
5892bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5893{
5894 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5895}
5896
5897bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5898{
5899 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5900}
5901
5902bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5903{
5904 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5905}
5906
5907bool ValidateIsEnabled(Context *context, GLenum cap)
5908{
5909 if (!ValidCap(context, cap, true))
5910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005912 return false;
5913 }
5914
5915 return true;
5916}
5917
5918bool ValidateLinkProgram(Context *context, GLuint program)
5919{
5920 if (context->hasActiveTransformFeedback(program))
5921 {
5922 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005923 context->handleError(InvalidOperation() << "Cannot link program while program is "
5924 "associated with an active transform "
5925 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 return false;
5927 }
5928
5929 Program *programObject = GetValidProgram(context, program);
5930 if (!programObject)
5931 {
5932 return false;
5933 }
5934
5935 return true;
5936}
5937
Jamie Madill4928b7c2017-06-20 12:57:39 -04005938bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 GLint x,
5940 GLint y,
5941 GLsizei width,
5942 GLsizei height,
5943 GLenum format,
5944 GLenum type,
5945 void *pixels)
5946{
5947 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5948 nullptr, pixels);
5949}
5950
5951bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5952{
5953 return ValidateTexParameterBase(context, target, pname, -1, &param);
5954}
5955
5956bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5957{
5958 return ValidateTexParameterBase(context, target, pname, -1, params);
5959}
5960
5961bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5962{
5963 return ValidateTexParameterBase(context, target, pname, -1, &param);
5964}
5965
5966bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5967{
5968 return ValidateTexParameterBase(context, target, pname, -1, params);
5969}
5970
5971bool ValidateUseProgram(Context *context, GLuint program)
5972{
5973 if (program != 0)
5974 {
5975 Program *programObject = context->getProgram(program);
5976 if (!programObject)
5977 {
5978 // ES 3.1.0 section 7.3 page 72
5979 if (context->getShader(program))
5980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005981 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04005982 return false;
5983 }
5984 else
5985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005986 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 return false;
5988 }
5989 }
5990 if (!programObject->isLinked())
5991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04005993 return false;
5994 }
5995 }
5996 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5997 {
5998 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005999 context
6000 ->handleError(InvalidOperation()
6001 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006002 return false;
6003 }
6004
6005 return true;
6006}
6007
Jamie Madillc29968b2016-01-20 11:17:23 -05006008} // namespace gl