blob: 5d7d23002c840500835d6de24464271af7859567 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070017#include "libANGLE/ErrorStrings.h"
Jamie Madillef300b12016-10-07 15:12:09 -040018#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/Texture.h"
Jamie Madillef300b12016-10-07 15:12:09 -040023#include "libANGLE/Uniform.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/VertexArray.h"
Jamie Madillef300b12016-10-07 15:12:09 -040025#include "libANGLE/formatutils.h"
26#include "libANGLE/validationES.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29namespace gl
30{
31
Jamie Madillc29968b2016-01-20 11:17:23 -050032namespace
33{
34
35bool IsPartialBlit(gl::Context *context,
36 const FramebufferAttachment *readBuffer,
37 const FramebufferAttachment *writeBuffer,
38 GLint srcX0,
39 GLint srcY0,
40 GLint srcX1,
41 GLint srcY1,
42 GLint dstX0,
43 GLint dstY0,
44 GLint dstX1,
45 GLint dstY1)
46{
47 const Extents &writeSize = writeBuffer->getSize();
48 const Extents &readSize = readBuffer->getSize();
49
50 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
51 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
52 {
53 return true;
54 }
55
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050057 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070058 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050059 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
60 scissor.height < writeSize.height;
61 }
62
63 return false;
64}
65
Sami Väisänend59ca052016-06-21 16:10:00 +030066template <typename T>
67bool ValidatePathInstances(gl::Context *context,
68 GLsizei numPaths,
69 const void *paths,
70 GLuint pathBase)
71{
72 const auto *array = static_cast<const T *>(paths);
73
74 for (GLsizei i = 0; i < numPaths; ++i)
75 {
76 const GLuint pathName = array[i] + pathBase;
77 if (context->hasPath(pathName) && !context->hasPathData(pathName))
78 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050079 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänend59ca052016-06-21 16:10:00 +030080 return false;
81 }
82 }
83 return true;
84}
85
86bool ValidateInstancedPathParameters(gl::Context *context,
87 GLsizei numPaths,
88 GLenum pathNameType,
89 const void *paths,
90 GLuint pathBase,
91 GLenum transformType,
92 const GLfloat *transformValues)
93{
94 if (!context->getExtensions().pathRendering)
95 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050096 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänend59ca052016-06-21 16:10:00 +030097 return false;
98 }
99
100 if (paths == nullptr)
101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500102 context->handleError(InvalidValue() << "No path name array.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300103 return false;
104 }
105
106 if (numPaths < 0)
107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500108 context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500160 context->handleError(InvalidEnum() << "Invalid path name type.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500188 context->handleError(InvalidEnum() << "Invalid transformation.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidValue() << "No transform array given.");
Sami Väisänend59ca052016-06-21 16:10:00 +0300194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänend59ca052016-06-21 16:10:00 +0300203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang4f0e0032017-05-01 16:04:35 -0400209bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
Geoff Lang97073d12016-04-20 10:42:34 -0700210{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400211 // Table 1.1 from the CHROMIUM_copy_texture spec
Geoff Langca271392017-04-05 12:30:00 -0400212 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700213 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400214 case GL_RED:
Geoff Lang97073d12016-04-20 10:42:34 -0700215 case GL_ALPHA:
216 case GL_LUMINANCE:
217 case GL_LUMINANCE_ALPHA:
218 case GL_RGB:
219 case GL_RGBA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400220 case GL_RGB8:
221 case GL_RGBA8:
222 case GL_BGRA_EXT:
223 case GL_BGRA8_EXT:
Geoff Lang97073d12016-04-20 10:42:34 -0700224 return true;
225
Geoff Lang4f0e0032017-05-01 16:04:35 -0400226 default:
227 return false;
228 }
229}
Geoff Lang97073d12016-04-20 10:42:34 -0700230
Geoff Lang4f0e0032017-05-01 16:04:35 -0400231bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
232{
233 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
234}
235
Geoff Lang4f0e0032017-05-01 16:04:35 -0400236bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
237{
238 // Table 1.0 from the CHROMIUM_copy_texture spec
239 switch (internalFormat)
240 {
241 case GL_RGB:
242 case GL_RGBA:
243 case GL_RGB8:
244 case GL_RGBA8:
Geoff Lang97073d12016-04-20 10:42:34 -0700245 case GL_BGRA_EXT:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400246 case GL_BGRA8_EXT:
247 case GL_SRGB_EXT:
248 case GL_SRGB_ALPHA_EXT:
249 case GL_R8:
250 case GL_R8UI:
251 case GL_RG8:
252 case GL_RG8UI:
253 case GL_SRGB8:
254 case GL_RGB565:
255 case GL_RGB8UI:
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400256 case GL_RGB10_A2:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400257 case GL_SRGB8_ALPHA8:
258 case GL_RGB5_A1:
259 case GL_RGBA4:
260 case GL_RGBA8UI:
261 case GL_RGB9_E5:
262 case GL_R16F:
263 case GL_R32F:
264 case GL_RG16F:
265 case GL_RG32F:
266 case GL_RGB16F:
267 case GL_RGB32F:
268 case GL_RGBA16F:
269 case GL_RGBA32F:
270 case GL_R11F_G11F_B10F:
Brandon Jones340b7b82017-06-26 13:02:31 -0700271 case GL_LUMINANCE:
272 case GL_LUMINANCE_ALPHA:
273 case GL_ALPHA:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400274 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700275
276 default:
277 return false;
278 }
279}
280
Geoff Lang6be3d4c2017-06-16 15:54:15 -0400281bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
282{
283 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
284}
285
Geoff Lang97073d12016-04-20 10:42:34 -0700286bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
287{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400288 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700289 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400290 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700291 }
292
Geoff Lang4f0e0032017-05-01 16:04:35 -0400293 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
294 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang97073d12016-04-20 10:42:34 -0700295 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400296 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700297 }
298
299 return true;
300}
301
Geoff Lang4f0e0032017-05-01 16:04:35 -0400302bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
Geoff Lang97073d12016-04-20 10:42:34 -0700303{
304 switch (target)
305 {
306 case GL_TEXTURE_2D:
Geoff Lang4f0e0032017-05-01 16:04:35 -0400307 return textureType == GL_TEXTURE_2D;
308
309 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
310 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
311 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
312 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
313 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
314 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
315 return textureType == GL_TEXTURE_CUBE_MAP;
Geoff Lang97073d12016-04-20 10:42:34 -0700316
317 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
318 // supported
319
320 default:
321 return false;
322 }
323}
324
325bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
326{
Geoff Lang4f0e0032017-05-01 16:04:35 -0400327 switch (target)
Geoff Lang97073d12016-04-20 10:42:34 -0700328 {
Geoff Lang4f0e0032017-05-01 16:04:35 -0400329 case GL_TEXTURE_2D:
330 return true;
331
332 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
333 // supported
334
335 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
336 // supported
337
338 default:
339 return false;
340 }
341}
342
343bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
344{
345 if (level < 0)
346 {
347 return false;
Geoff Lang97073d12016-04-20 10:42:34 -0700348 }
349
Geoff Lang4f0e0032017-05-01 16:04:35 -0400350 if (level > 0 && context->getClientVersion() < ES_3_0)
351 {
352 return false;
353 }
Geoff Lang97073d12016-04-20 10:42:34 -0700354
Geoff Lang4f0e0032017-05-01 16:04:35 -0400355 return true;
356}
357
358bool IsValidCopyTextureDestinationLevel(Context *context,
359 GLenum target,
360 GLint level,
361 GLsizei width,
362 GLsizei height)
363{
364 if (level < 0)
365 {
366 return false;
367 }
368
Geoff Lang4f0e0032017-05-01 16:04:35 -0400369 const Caps &caps = context->getCaps();
370 if (target == GL_TEXTURE_2D)
371 {
372 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
373 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
374 {
375 return false;
376 }
377 }
378 else if (IsCubeMapTextureTarget(target))
379 {
380 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
381 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
382 {
383 return false;
384 }
385 }
386
387 return true;
Geoff Lang97073d12016-04-20 10:42:34 -0700388}
389
Jamie Madillc1d770e2017-04-13 17:31:24 -0400390bool IsValidStencilFunc(GLenum func)
391{
392 switch (func)
393 {
394 case GL_NEVER:
395 case GL_ALWAYS:
396 case GL_LESS:
397 case GL_LEQUAL:
398 case GL_EQUAL:
399 case GL_GEQUAL:
400 case GL_GREATER:
401 case GL_NOTEQUAL:
402 return true;
403
404 default:
405 return false;
406 }
407}
408
409bool IsValidStencilFace(GLenum face)
410{
411 switch (face)
412 {
413 case GL_FRONT:
414 case GL_BACK:
415 case GL_FRONT_AND_BACK:
416 return true;
417
418 default:
419 return false;
420 }
421}
422
423bool IsValidStencilOp(GLenum op)
424{
425 switch (op)
426 {
427 case GL_ZERO:
428 case GL_KEEP:
429 case GL_REPLACE:
430 case GL_INCR:
431 case GL_DECR:
432 case GL_INVERT:
433 case GL_INCR_WRAP:
434 case GL_DECR_WRAP:
435 return true;
436
437 default:
438 return false;
439 }
440}
441
Jamie Madillbe849e42017-05-02 15:49:00 -0400442bool ValidateES2CopyTexImageParameters(ValidationContext *context,
443 GLenum target,
444 GLint level,
445 GLenum internalformat,
446 bool isSubImage,
447 GLint xoffset,
448 GLint yoffset,
449 GLint x,
450 GLint y,
451 GLsizei width,
452 GLsizei height,
453 GLint border)
454{
455 if (!ValidTexture2DDestinationTarget(context, target))
456 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700457 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -0400458 return false;
459 }
460
461 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500463 context->handleError(InvalidValue() << "Invalid texture dimensions.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400464 return false;
465 }
466
467 Format textureFormat = Format::Invalid();
468 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
469 xoffset, yoffset, 0, x, y, width, height, border,
470 &textureFormat))
471 {
472 return false;
473 }
474
475 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
476 GLenum colorbufferFormat =
477 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
478 const auto &formatInfo = *textureFormat.info;
479
480 // [OpenGL ES 2.0.24] table 3.9
481 if (isSubImage)
482 {
483 switch (formatInfo.format)
484 {
485 case GL_ALPHA:
486 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400487 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
488 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400489 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400491 return false;
492 }
493 break;
494 case GL_LUMINANCE:
495 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
496 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
497 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400498 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
499 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400500 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700501 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400502 return false;
503 }
504 break;
505 case GL_RED_EXT:
506 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
507 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
508 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
509 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
510 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400511 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
512 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400513 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400515 return false;
516 }
517 break;
518 case GL_RG_EXT:
519 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
520 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
521 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
522 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400523 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
524 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400525 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700526 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400527 return false;
528 }
529 break;
530 case GL_RGB:
531 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
532 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
533 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400534 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
535 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400536 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400538 return false;
539 }
540 break;
541 case GL_LUMINANCE_ALPHA:
542 case GL_RGBA:
543 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400544 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
545 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400546 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700547 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400548 return false;
549 }
550 break;
551 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
552 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
553 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
554 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
555 case GL_ETC1_RGB8_OES:
556 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
557 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
558 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
559 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
560 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
Brandon Jones6cad5662017-06-14 13:25:13 -0700561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 case GL_DEPTH_COMPONENT:
564 case GL_DEPTH_STENCIL_OES:
Brandon Jones6cad5662017-06-14 13:25:13 -0700565 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400566 return false;
567 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400569 return false;
570 }
571
572 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
573 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700574 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400575 return false;
576 }
577 }
578 else
579 {
580 switch (internalformat)
581 {
582 case GL_ALPHA:
583 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
584 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
585 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
586 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400588 return false;
589 }
590 break;
591 case GL_LUMINANCE:
592 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
593 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
594 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
595 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
596 colorbufferFormat != GL_BGR5_A1_ANGLEX)
597 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400599 return false;
600 }
601 break;
602 case GL_RED_EXT:
603 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
604 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
605 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
606 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
607 colorbufferFormat != GL_BGR5_A1_ANGLEX)
608 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400610 return false;
611 }
612 break;
613 case GL_RG_EXT:
614 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
615 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
616 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
617 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
618 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400620 return false;
621 }
622 break;
623 case GL_RGB:
624 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
625 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
626 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
627 colorbufferFormat != GL_BGR5_A1_ANGLEX)
628 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400630 return false;
631 }
632 break;
633 case GL_LUMINANCE_ALPHA:
634 case GL_RGBA:
635 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
636 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
637 colorbufferFormat != GL_BGR5_A1_ANGLEX)
638 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400640 return false;
641 }
642 break;
643 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
644 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
645 if (context->getExtensions().textureCompressionDXT1)
646 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400648 return false;
649 }
650 else
651 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400653 return false;
654 }
655 break;
656 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
657 if (context->getExtensions().textureCompressionDXT3)
658 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 return false;
661 }
662 else
663 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666 }
667 break;
668 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
669 if (context->getExtensions().textureCompressionDXT5)
670 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 return false;
673 }
674 else
675 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -0400677 return false;
678 }
679 break;
680 case GL_ETC1_RGB8_OES:
681 if (context->getExtensions().compressedETC1RGB8Texture)
682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500683 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400684 return false;
685 }
686 else
687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500688 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 return false;
690 }
691 break;
692 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
693 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
694 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
695 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
696 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
697 if (context->getExtensions().lossyETCDecode)
698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation()
700 << "ETC lossy decode formats can't be copied to.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400701 return false;
702 }
703 else
704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500705 context->handleError(InvalidEnum()
706 << "ANGLE_lossy_etc_decode extension is not supported.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400707 return false;
708 }
709 break;
710 case GL_DEPTH_COMPONENT:
711 case GL_DEPTH_COMPONENT16:
712 case GL_DEPTH_COMPONENT32_OES:
713 case GL_DEPTH_STENCIL_OES:
714 case GL_DEPTH24_STENCIL8_OES:
715 if (context->getExtensions().depthTextures)
716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500717 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -0400718 return false;
719 }
720 else
721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500722 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidEnum());
Jamie Madillbe849e42017-05-02 15:49:00 -0400727 return false;
728 }
729 }
730
731 // If width or height is zero, it is a no-op. Return false without setting an error.
732 return (width > 0 && height > 0);
733}
734
735bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
736{
737 switch (cap)
738 {
739 // EXT_multisample_compatibility
740 case GL_MULTISAMPLE_EXT:
741 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
742 return context->getExtensions().multisampleCompatibility;
743
744 case GL_CULL_FACE:
745 case GL_POLYGON_OFFSET_FILL:
746 case GL_SAMPLE_ALPHA_TO_COVERAGE:
747 case GL_SAMPLE_COVERAGE:
748 case GL_SCISSOR_TEST:
749 case GL_STENCIL_TEST:
750 case GL_DEPTH_TEST:
751 case GL_BLEND:
752 case GL_DITHER:
753 return true;
754
755 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
756 case GL_RASTERIZER_DISCARD:
757 return (context->getClientMajorVersion() >= 3);
758
759 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
760 case GL_DEBUG_OUTPUT:
761 return context->getExtensions().debug;
762
763 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
764 return queryOnly && context->getExtensions().bindGeneratesResource;
765
766 case GL_CLIENT_ARRAYS_ANGLE:
767 return queryOnly && context->getExtensions().clientArrays;
768
769 case GL_FRAMEBUFFER_SRGB_EXT:
770 return context->getExtensions().sRGBWriteControl;
771
772 case GL_SAMPLE_MASK:
773 return context->getClientVersion() >= Version(3, 1);
774
775 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
776 return queryOnly && context->getExtensions().robustResourceInitialization;
777
778 default:
779 return false;
780 }
781}
782
Geoff Langfc32e8b2017-05-31 14:16:59 -0400783// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
784// 3.1.
Geoff Langa71a98e2017-06-19 15:15:00 -0400785bool IsValidESSLCharacter(unsigned char c, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400786{
787 // Printing characters are valid except " $ ` @ \ ' DEL.
Geoff Langa71a98e2017-06-19 15:15:00 -0400788 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' &&
789 (allowBackslash || c != '\\') && c != '\'')
Geoff Langfc32e8b2017-05-31 14:16:59 -0400790 {
791 return true;
792 }
793
794 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
795 if (c >= 9 && c <= 13)
796 {
797 return true;
798 }
799
800 return false;
801}
802
Geoff Langa71a98e2017-06-19 15:15:00 -0400803bool IsValidESSLString(const char *str, size_t len, bool allowBackslash)
Geoff Langfc32e8b2017-05-31 14:16:59 -0400804{
Geoff Langa71a98e2017-06-19 15:15:00 -0400805 for (size_t i = 0; i < len; i++)
806 {
807 if (!IsValidESSLCharacter(str[i], allowBackslash))
808 {
809 return false;
810 }
811 }
812
813 return true;
Geoff Langfc32e8b2017-05-31 14:16:59 -0400814}
815
Jamie Madillc29968b2016-01-20 11:17:23 -0500816} // anonymous namespace
817
Geoff Langff5b2d52016-09-07 11:32:23 -0400818bool ValidateES2TexImageParameters(Context *context,
819 GLenum target,
820 GLint level,
821 GLenum internalformat,
822 bool isCompressed,
823 bool isSubImage,
824 GLint xoffset,
825 GLint yoffset,
826 GLsizei width,
827 GLsizei height,
828 GLint border,
829 GLenum format,
830 GLenum type,
831 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400832 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833{
Jamie Madill6f38f822014-06-06 17:12:20 -0400834 if (!ValidTexture2DDestinationTarget(context, target))
835 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langb1196682014-07-23 13:47:29 -0400837 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400838 }
839
Austin Kinross08528e12015-10-07 16:24:40 -0700840 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500842 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400844 }
845
Brandon Jones6cad5662017-06-14 13:25:13 -0700846 if (!ValidMipLevel(context, target, level))
847 {
848 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
849 return false;
850 }
851
852 if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 std::numeric_limits<GLsizei>::max() - yoffset < height)
854 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700855 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -0400856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858
Geoff Lang6e898aa2017-06-02 11:17:26 -0400859 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
860 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
861 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
862 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
863 // case.
864 bool nonEqualFormatsAllowed =
865 (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
866 (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
867
868 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500870 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400871 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400872 }
873
Geoff Langaae65a42014-05-26 12:43:44 -0400874 const gl::Caps &caps = context->getCaps();
875
Geoff Langa9be0dc2014-12-17 12:34:40 -0500876 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400877 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500878 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
879 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500881 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500882 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400883 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500884 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500885 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500886 {
887 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400888 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700889 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500890 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400891 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400892
Geoff Langa9be0dc2014-12-17 12:34:40 -0500893 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
894 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500897 return false;
898 }
899 }
900 else
901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500902 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -0400903 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400904 }
905
He Yunchaoced53ae2016-11-29 15:00:51 +0800906 gl::Texture *texture =
907 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 if (!texture)
909 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700910 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Geoff Langb1196682014-07-23 13:47:29 -0400911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 }
913
Geoff Langa9be0dc2014-12-17 12:34:40 -0500914 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 {
Geoff Langca271392017-04-05 12:30:00 -0400916 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
917 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500919 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500920 return false;
921 }
922
Geoff Langa9be0dc2014-12-17 12:34:40 -0500923 if (format != GL_NONE)
924 {
Geoff Langca271392017-04-05 12:30:00 -0400925 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
926 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500927 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Geoff Langa9be0dc2014-12-17 12:34:40 -0500929 return false;
930 }
931 }
932
933 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
934 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500936 context->handleError(InvalidValue());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500937 return false;
938 }
939 }
940 else
941 {
Geoff Lang69cce582015-09-17 13:20:36 -0400942 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500944 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -0500945 return false;
946 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 }
948
949 // Verify zero border
950 if (border != 0)
951 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700952 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -0400953 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 }
955
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 if (isCompressed)
957 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400958 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400959 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
960 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 switch (actualInternalFormat)
962 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800963 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
964 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
965 if (!context->getExtensions().textureCompressionDXT1)
966 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700967 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800968 return false;
969 }
970 break;
971 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
972 if (!context->getExtensions().textureCompressionDXT1)
973 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700974 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800975 return false;
976 }
977 break;
978 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
979 if (!context->getExtensions().textureCompressionDXT5)
980 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700981 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 return false;
983 }
984 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800985 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
986 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
987 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
988 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
989 if (!context->getExtensions().textureCompressionS3TCsRGB)
990 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700991 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800992 return false;
993 }
994 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800995 case GL_ETC1_RGB8_OES:
996 if (!context->getExtensions().compressedETC1RGB8Texture)
997 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700998 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +0800999 return false;
1000 }
1001 break;
1002 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001003 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1004 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1005 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1006 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001007 if (!context->getExtensions().lossyETCDecode)
1008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001009 context->handleError(InvalidEnum()
1010 << "ANGLE_lossy_etc_decode extension is not supported");
He Yunchaoced53ae2016-11-29 15:00:51 +08001011 return false;
1012 }
1013 break;
1014 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -04001017 }
Geoff Lang966c9402017-04-18 12:38:27 -04001018
1019 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -04001020 {
Geoff Lang966c9402017-04-18 12:38:27 -04001021 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
1022 height, texture->getWidth(target, level),
1023 texture->getHeight(target, level)))
1024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001025 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001026 return false;
1027 }
1028
1029 if (format != actualInternalFormat)
1030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
Geoff Lang966c9402017-04-18 12:38:27 -04001032 return false;
1033 }
1034 }
1035 else
1036 {
1037 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
1038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001039 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -04001040 return false;
1041 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001042 }
1043 }
1044 else
1045 {
1046 // validate <type> by itself (used as secondary key below)
1047 switch (type)
1048 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001049 case GL_UNSIGNED_BYTE:
1050 case GL_UNSIGNED_SHORT_5_6_5:
1051 case GL_UNSIGNED_SHORT_4_4_4_4:
1052 case GL_UNSIGNED_SHORT_5_5_5_1:
1053 case GL_UNSIGNED_SHORT:
1054 case GL_UNSIGNED_INT:
1055 case GL_UNSIGNED_INT_24_8_OES:
1056 case GL_HALF_FLOAT_OES:
1057 case GL_FLOAT:
1058 break;
1059 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001061 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 }
1063
1064 // validate <format> + <type> combinations
1065 // - invalid <format> -> sets INVALID_ENUM
1066 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1067 switch (format)
1068 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001069 case GL_ALPHA:
1070 case GL_LUMINANCE:
1071 case GL_LUMINANCE_ALPHA:
1072 switch (type)
1073 {
1074 case GL_UNSIGNED_BYTE:
1075 case GL_FLOAT:
1076 case GL_HALF_FLOAT_OES:
1077 break;
1078 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001080 return false;
1081 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 case GL_RED:
1084 case GL_RG:
1085 if (!context->getExtensions().textureRG)
1086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001087 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001088 return false;
1089 }
1090 switch (type)
1091 {
1092 case GL_UNSIGNED_BYTE:
1093 case GL_FLOAT:
1094 case GL_HALF_FLOAT_OES:
1095 break;
1096 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 return false;
1099 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001101 case GL_RGB:
1102 switch (type)
1103 {
1104 case GL_UNSIGNED_BYTE:
1105 case GL_UNSIGNED_SHORT_5_6_5:
1106 case GL_FLOAT:
1107 case GL_HALF_FLOAT_OES:
1108 break;
1109 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 return false;
1112 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 case GL_RGBA:
1115 switch (type)
1116 {
1117 case GL_UNSIGNED_BYTE:
1118 case GL_UNSIGNED_SHORT_4_4_4_4:
1119 case GL_UNSIGNED_SHORT_5_5_5_1:
1120 case GL_FLOAT:
1121 case GL_HALF_FLOAT_OES:
1122 break;
1123 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001125 return false;
1126 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 case GL_BGRA_EXT:
1129 switch (type)
1130 {
1131 case GL_UNSIGNED_BYTE:
1132 break;
1133 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001135 return false;
1136 }
1137 break;
1138 case GL_SRGB_EXT:
1139 case GL_SRGB_ALPHA_EXT:
1140 if (!context->getExtensions().sRGB)
1141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001142 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001143 return false;
1144 }
1145 switch (type)
1146 {
1147 case GL_UNSIGNED_BYTE:
1148 break;
1149 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001151 return false;
1152 }
1153 break;
1154 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1155 // handled below
1156 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1157 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1158 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1159 break;
1160 case GL_DEPTH_COMPONENT:
1161 switch (type)
1162 {
1163 case GL_UNSIGNED_SHORT:
1164 case GL_UNSIGNED_INT:
1165 break;
1166 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001168 return false;
1169 }
1170 break;
1171 case GL_DEPTH_STENCIL_OES:
1172 switch (type)
1173 {
1174 case GL_UNSIGNED_INT_24_8_OES:
1175 break;
1176 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 return false;
1179 }
1180 break;
1181 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001182 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 }
1185
1186 switch (format)
1187 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001188 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1189 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1190 if (context->getExtensions().textureCompressionDXT1)
1191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001192 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001193 return false;
1194 }
1195 else
1196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001197 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001198 return false;
1199 }
1200 break;
1201 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1202 if (context->getExtensions().textureCompressionDXT3)
1203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001204 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001205 return false;
1206 }
1207 else
1208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001209 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
1211 }
1212 break;
1213 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1214 if (context->getExtensions().textureCompressionDXT5)
1215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001216 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 return false;
1218 }
1219 else
1220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return false;
1223 }
1224 break;
1225 case GL_ETC1_RGB8_OES:
1226 if (context->getExtensions().compressedETC1RGB8Texture)
1227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001228 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001229 return false;
1230 }
1231 else
1232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 return false;
1235 }
1236 break;
1237 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001238 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1239 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1240 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1241 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001242 if (context->getExtensions().lossyETCDecode)
1243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001244 context->handleError(InvalidOperation()
1245 << "ETC lossy decode formats can't work with this type.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001246 return false;
1247 }
1248 else
1249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001250 context->handleError(InvalidEnum()
1251 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001252 return false;
1253 }
1254 break;
1255 case GL_DEPTH_COMPONENT:
1256 case GL_DEPTH_STENCIL_OES:
1257 if (!context->getExtensions().depthTextures)
1258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001259 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001260 return false;
1261 }
1262 if (target != GL_TEXTURE_2D)
1263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001264 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001265 return false;
1266 }
1267 // OES_depth_texture supports loading depth data and multiple levels,
1268 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001269 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001271 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001272 return false;
1273 }
1274 break;
1275 default:
1276 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 }
1278
Geoff Lang6e898aa2017-06-02 11:17:26 -04001279 if (!isSubImage)
1280 {
1281 switch (internalformat)
1282 {
1283 case GL_RGBA32F:
1284 if (!context->getExtensions().colorBufferFloatRGBA)
1285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001286 context->handleError(InvalidValue()
1287 << "Sized GL_RGBA32F internal format requires "
1288 "GL_CHROMIUM_color_buffer_float_rgba");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001289 return false;
1290 }
1291 if (type != GL_FLOAT)
1292 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001294 return false;
1295 }
1296 if (format != GL_RGBA)
1297 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001298 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001299 return false;
1300 }
1301 break;
1302
1303 case GL_RGB32F:
1304 if (!context->getExtensions().colorBufferFloatRGB)
1305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001306 context->handleError(InvalidValue()
1307 << "Sized GL_RGB32F internal format requires "
1308 "GL_CHROMIUM_color_buffer_float_rgb");
Geoff Lang6e898aa2017-06-02 11:17:26 -04001309 return false;
1310 }
1311 if (type != GL_FLOAT)
1312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001314 return false;
1315 }
1316 if (format != GL_RGB)
1317 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang6e898aa2017-06-02 11:17:26 -04001319 return false;
1320 }
1321 break;
1322
1323 default:
1324 break;
1325 }
1326 }
1327
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 if (type == GL_FLOAT)
1329 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001330 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335 }
1336 else if (type == GL_HALF_FLOAT_OES)
1337 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001338 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001340 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001341 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 }
1343 }
1344 }
1345
Geoff Langdbcced82017-06-06 15:55:54 -04001346 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1347 if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001348 imageSize))
1349 {
1350 return false;
1351 }
1352
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 return true;
1354}
1355
He Yunchaoced53ae2016-11-29 15:00:51 +08001356bool ValidateES2TexStorageParameters(Context *context,
1357 GLenum target,
1358 GLsizei levels,
1359 GLenum internalformat,
1360 GLsizei width,
1361 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362{
1363 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001365 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 }
1368
1369 if (width < 1 || height < 1 || levels < 1)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 }
1374
1375 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
1380
1381 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 }
1386
Geoff Langca271392017-04-05 12:30:00 -04001387 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001388 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001391 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 }
1393
Geoff Langaae65a42014-05-26 12:43:44 -04001394 const gl::Caps &caps = context->getCaps();
1395
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 switch (target)
1397 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 case GL_TEXTURE_2D:
1399 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1400 static_cast<GLuint>(height) > caps.max2DTextureSize)
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001403 return false;
1404 }
1405 break;
1406 case GL_TEXTURE_CUBE_MAP:
1407 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1408 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001410 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +08001411 return false;
1412 }
1413 break;
1414 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001416 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
1418
Geoff Langc0b9ef42014-07-02 10:02:37 -04001419 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 {
1421 if (!gl::isPow2(width) || !gl::isPow2(height))
1422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
1426 }
1427
1428 switch (internalformat)
1429 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001430 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1431 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1432 if (!context->getExtensions().textureCompressionDXT1)
1433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001435 return false;
1436 }
1437 break;
1438 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1439 if (!context->getExtensions().textureCompressionDXT3)
1440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001441 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001442 return false;
1443 }
1444 break;
1445 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1446 if (!context->getExtensions().textureCompressionDXT5)
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001449 return false;
1450 }
1451 break;
1452 case GL_ETC1_RGB8_OES:
1453 if (!context->getExtensions().compressedETC1RGB8Texture)
1454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001455 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001456 return false;
1457 }
1458 break;
1459 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001460 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1461 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1462 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1463 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001464 if (!context->getExtensions().lossyETCDecode)
1465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001466 context->handleError(InvalidEnum()
1467 << "ANGLE_lossy_etc_decode extension is not supported.");
He Yunchaoced53ae2016-11-29 15:00:51 +08001468 return false;
1469 }
1470 break;
1471 case GL_RGBA32F_EXT:
1472 case GL_RGB32F_EXT:
1473 case GL_ALPHA32F_EXT:
1474 case GL_LUMINANCE32F_EXT:
1475 case GL_LUMINANCE_ALPHA32F_EXT:
1476 if (!context->getExtensions().textureFloat)
1477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001478 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001479 return false;
1480 }
1481 break;
1482 case GL_RGBA16F_EXT:
1483 case GL_RGB16F_EXT:
1484 case GL_ALPHA16F_EXT:
1485 case GL_LUMINANCE16F_EXT:
1486 case GL_LUMINANCE_ALPHA16F_EXT:
1487 if (!context->getExtensions().textureHalfFloat)
1488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001490 return false;
1491 }
1492 break;
1493 case GL_R8_EXT:
1494 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001495 if (!context->getExtensions().textureRG)
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001498 return false;
1499 }
1500 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001501 case GL_R16F_EXT:
1502 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001503 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001505 context->handleError(InvalidEnum());
Geoff Lang677bb6f2017-04-05 12:40:40 -04001506 return false;
1507 }
1508 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 case GL_R32F_EXT:
1510 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001511 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001514 return false;
1515 }
1516 break;
1517 case GL_DEPTH_COMPONENT16:
1518 case GL_DEPTH_COMPONENT32_OES:
1519 case GL_DEPTH24_STENCIL8_OES:
1520 if (!context->getExtensions().depthTextures)
1521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001522 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001523 return false;
1524 }
1525 if (target != GL_TEXTURE_2D)
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001528 return false;
1529 }
1530 // ANGLE_depth_texture only supports 1-level textures
1531 if (levels != 1)
1532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(InvalidOperation());
He Yunchaoced53ae2016-11-29 15:00:51 +08001534 return false;
1535 }
1536 break;
1537 default:
1538 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 }
1540
Geoff Lang691e58c2014-12-19 17:03:25 -05001541 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001542 if (!texture || texture->id() == 0)
1543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001544 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001545 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001546 }
1547
Geoff Lang69cce582015-09-17 13:20:36 -04001548 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001550 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001551 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001552 }
1553
1554 return true;
1555}
1556
He Yunchaoced53ae2016-11-29 15:00:51 +08001557bool ValidateDiscardFramebufferEXT(Context *context,
1558 GLenum target,
1559 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001560 const GLenum *attachments)
1561{
Jamie Madillc29968b2016-01-20 11:17:23 -05001562 if (!context->getExtensions().discardFramebuffer)
1563 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Jamie Madillc29968b2016-01-20 11:17:23 -05001565 return false;
1566 }
1567
Austin Kinross08332632015-05-05 13:35:47 -07001568 bool defaultFramebuffer = false;
1569
1570 switch (target)
1571 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001572 case GL_FRAMEBUFFER:
1573 defaultFramebuffer =
1574 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1575 break;
1576 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001578 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001579 }
1580
He Yunchaoced53ae2016-11-29 15:00:51 +08001581 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1582 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001583}
1584
Austin Kinrossbc781f32015-10-26 09:27:38 -07001585bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1586{
1587 if (!context->getExtensions().vertexArrayObject)
1588 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001590 return false;
1591 }
1592
1593 return ValidateBindVertexArrayBase(context, array);
1594}
1595
1596bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1597{
1598 if (!context->getExtensions().vertexArrayObject)
1599 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001600 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001601 return false;
1602 }
1603
Olli Etuaho41997e72016-03-10 13:38:39 +02001604 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001605}
1606
1607bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1608{
1609 if (!context->getExtensions().vertexArrayObject)
1610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001612 return false;
1613 }
1614
Olli Etuaho41997e72016-03-10 13:38:39 +02001615 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001616}
1617
1618bool ValidateIsVertexArrayOES(Context *context)
1619{
1620 if (!context->getExtensions().vertexArrayObject)
1621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001623 return false;
1624 }
1625
1626 return true;
1627}
Geoff Langc5629752015-12-07 16:29:04 -05001628
1629bool ValidateProgramBinaryOES(Context *context,
1630 GLuint program,
1631 GLenum binaryFormat,
1632 const void *binary,
1633 GLint length)
1634{
1635 if (!context->getExtensions().getProgramBinary)
1636 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001638 return false;
1639 }
1640
1641 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1642}
1643
1644bool ValidateGetProgramBinaryOES(Context *context,
1645 GLuint program,
1646 GLsizei bufSize,
1647 GLsizei *length,
1648 GLenum *binaryFormat,
1649 void *binary)
1650{
1651 if (!context->getExtensions().getProgramBinary)
1652 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Langc5629752015-12-07 16:29:04 -05001654 return false;
1655 }
1656
1657 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1658}
Geoff Lange102fee2015-12-10 11:23:30 -05001659
Geoff Lang70d0f492015-12-10 17:45:46 -05001660static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1661{
1662 switch (source)
1663 {
1664 case GL_DEBUG_SOURCE_API:
1665 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1666 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1667 case GL_DEBUG_SOURCE_OTHER:
1668 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1669 return !mustBeThirdPartyOrApplication;
1670
1671 case GL_DEBUG_SOURCE_THIRD_PARTY:
1672 case GL_DEBUG_SOURCE_APPLICATION:
1673 return true;
1674
1675 default:
1676 return false;
1677 }
1678}
1679
1680static bool ValidDebugType(GLenum type)
1681{
1682 switch (type)
1683 {
1684 case GL_DEBUG_TYPE_ERROR:
1685 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1686 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1687 case GL_DEBUG_TYPE_PERFORMANCE:
1688 case GL_DEBUG_TYPE_PORTABILITY:
1689 case GL_DEBUG_TYPE_OTHER:
1690 case GL_DEBUG_TYPE_MARKER:
1691 case GL_DEBUG_TYPE_PUSH_GROUP:
1692 case GL_DEBUG_TYPE_POP_GROUP:
1693 return true;
1694
1695 default:
1696 return false;
1697 }
1698}
1699
1700static bool ValidDebugSeverity(GLenum severity)
1701{
1702 switch (severity)
1703 {
1704 case GL_DEBUG_SEVERITY_HIGH:
1705 case GL_DEBUG_SEVERITY_MEDIUM:
1706 case GL_DEBUG_SEVERITY_LOW:
1707 case GL_DEBUG_SEVERITY_NOTIFICATION:
1708 return true;
1709
1710 default:
1711 return false;
1712 }
1713}
1714
Geoff Lange102fee2015-12-10 11:23:30 -05001715bool ValidateDebugMessageControlKHR(Context *context,
1716 GLenum source,
1717 GLenum type,
1718 GLenum severity,
1719 GLsizei count,
1720 const GLuint *ids,
1721 GLboolean enabled)
1722{
1723 if (!context->getExtensions().debug)
1724 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001725 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001726 return false;
1727 }
1728
Geoff Lang70d0f492015-12-10 17:45:46 -05001729 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001732 return false;
1733 }
1734
1735 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001737 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001738 return false;
1739 }
1740
1741 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001744 return false;
1745 }
1746
1747 if (count > 0)
1748 {
1749 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001751 context->handleError(
1752 InvalidOperation()
1753 << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001754 return false;
1755 }
1756
1757 if (severity != GL_DONT_CARE)
1758 {
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 InvalidOperation()
1761 << "If count is greater than zero, severity must be GL_DONT_CARE.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001762 return false;
1763 }
1764 }
1765
Geoff Lange102fee2015-12-10 11:23:30 -05001766 return true;
1767}
1768
1769bool ValidateDebugMessageInsertKHR(Context *context,
1770 GLenum source,
1771 GLenum type,
1772 GLuint id,
1773 GLenum severity,
1774 GLsizei length,
1775 const GLchar *buf)
1776{
1777 if (!context->getExtensions().debug)
1778 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001780 return false;
1781 }
1782
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001783 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001784 {
1785 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1786 // not generate an error.
1787 return false;
1788 }
1789
1790 if (!ValidDebugSeverity(severity))
1791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001792 context->handleError(InvalidEnum() << "Invalid debug severity.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001793 return false;
1794 }
1795
1796 if (!ValidDebugType(type))
1797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001798 context->handleError(InvalidEnum() << "Invalid debug type.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001799 return false;
1800 }
1801
1802 if (!ValidDebugSource(source, true))
1803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001804 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001805 return false;
1806 }
1807
1808 size_t messageLength = (length < 0) ? strlen(buf) : length;
1809 if (messageLength > context->getExtensions().maxDebugMessageLength)
1810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001811 context->handleError(InvalidValue()
1812 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001813 return false;
1814 }
1815
Geoff Lange102fee2015-12-10 11:23:30 -05001816 return true;
1817}
1818
1819bool ValidateDebugMessageCallbackKHR(Context *context,
1820 GLDEBUGPROCKHR callback,
1821 const void *userParam)
1822{
1823 if (!context->getExtensions().debug)
1824 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001825 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001826 return false;
1827 }
1828
Geoff Lange102fee2015-12-10 11:23:30 -05001829 return true;
1830}
1831
1832bool ValidateGetDebugMessageLogKHR(Context *context,
1833 GLuint count,
1834 GLsizei bufSize,
1835 GLenum *sources,
1836 GLenum *types,
1837 GLuint *ids,
1838 GLenum *severities,
1839 GLsizei *lengths,
1840 GLchar *messageLog)
1841{
1842 if (!context->getExtensions().debug)
1843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001845 return false;
1846 }
1847
Geoff Lang70d0f492015-12-10 17:45:46 -05001848 if (bufSize < 0 && messageLog != nullptr)
1849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001850 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05001851 return false;
1852 }
1853
Geoff Lange102fee2015-12-10 11:23:30 -05001854 return true;
1855}
1856
1857bool ValidatePushDebugGroupKHR(Context *context,
1858 GLenum source,
1859 GLuint id,
1860 GLsizei length,
1861 const GLchar *message)
1862{
1863 if (!context->getExtensions().debug)
1864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001866 return false;
1867 }
1868
Geoff Lang70d0f492015-12-10 17:45:46 -05001869 if (!ValidDebugSource(source, true))
1870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001871 context->handleError(InvalidEnum() << "Invalid debug source.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001872 return false;
1873 }
1874
1875 size_t messageLength = (length < 0) ? strlen(message) : length;
1876 if (messageLength > context->getExtensions().maxDebugMessageLength)
1877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001878 context->handleError(InvalidValue()
1879 << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001880 return false;
1881 }
1882
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001883 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001884 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001886 context
1887 ->handleError(StackOverflow()
1888 << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001889 return false;
1890 }
1891
Geoff Lange102fee2015-12-10 11:23:30 -05001892 return true;
1893}
1894
1895bool ValidatePopDebugGroupKHR(Context *context)
1896{
1897 if (!context->getExtensions().debug)
1898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05001900 return false;
1901 }
1902
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001903 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001904 if (currentStackSize <= 1)
1905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001906 context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001907 return false;
1908 }
1909
1910 return true;
1911}
1912
1913static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1914{
1915 switch (identifier)
1916 {
1917 case GL_BUFFER:
1918 if (context->getBuffer(name) == nullptr)
1919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001920 context->handleError(InvalidValue() << "name is not a valid buffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001921 return false;
1922 }
1923 return true;
1924
1925 case GL_SHADER:
1926 if (context->getShader(name) == nullptr)
1927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001928 context->handleError(InvalidValue() << "name is not a valid shader.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001929 return false;
1930 }
1931 return true;
1932
1933 case GL_PROGRAM:
1934 if (context->getProgram(name) == nullptr)
1935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001936 context->handleError(InvalidValue() << "name is not a valid program.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001937 return false;
1938 }
1939 return true;
1940
1941 case GL_VERTEX_ARRAY:
1942 if (context->getVertexArray(name) == nullptr)
1943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001944 context->handleError(InvalidValue() << "name is not a valid vertex array.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001945 return false;
1946 }
1947 return true;
1948
1949 case GL_QUERY:
1950 if (context->getQuery(name) == nullptr)
1951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidValue() << "name is not a valid query.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001953 return false;
1954 }
1955 return true;
1956
1957 case GL_TRANSFORM_FEEDBACK:
1958 if (context->getTransformFeedback(name) == nullptr)
1959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001960 context->handleError(InvalidValue() << "name is not a valid transform feedback.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001961 return false;
1962 }
1963 return true;
1964
1965 case GL_SAMPLER:
1966 if (context->getSampler(name) == nullptr)
1967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001968 context->handleError(InvalidValue() << "name is not a valid sampler.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001969 return false;
1970 }
1971 return true;
1972
1973 case GL_TEXTURE:
1974 if (context->getTexture(name) == nullptr)
1975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001976 context->handleError(InvalidValue() << "name is not a valid texture.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001977 return false;
1978 }
1979 return true;
1980
1981 case GL_RENDERBUFFER:
1982 if (context->getRenderbuffer(name) == nullptr)
1983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001984 context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001985 return false;
1986 }
1987 return true;
1988
1989 case GL_FRAMEBUFFER:
1990 if (context->getFramebuffer(name) == nullptr)
1991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001992 context->handleError(InvalidValue() << "name is not a valid framebuffer.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001993 return false;
1994 }
1995 return true;
1996
1997 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001998 context->handleError(InvalidEnum() << "Invalid identifier.");
Geoff Lang70d0f492015-12-10 17:45:46 -05001999 return false;
2000 }
Geoff Lange102fee2015-12-10 11:23:30 -05002001}
2002
Martin Radev9d901792016-07-15 15:58:58 +03002003static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
2004{
2005 size_t labelLength = 0;
2006
2007 if (length < 0)
2008 {
2009 if (label != nullptr)
2010 {
2011 labelLength = strlen(label);
2012 }
2013 }
2014 else
2015 {
2016 labelLength = static_cast<size_t>(length);
2017 }
2018
2019 if (labelLength > context->getExtensions().maxLabelLength)
2020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002021 context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
Martin Radev9d901792016-07-15 15:58:58 +03002022 return false;
2023 }
2024
2025 return true;
2026}
2027
Geoff Lange102fee2015-12-10 11:23:30 -05002028bool ValidateObjectLabelKHR(Context *context,
2029 GLenum identifier,
2030 GLuint name,
2031 GLsizei length,
2032 const GLchar *label)
2033{
2034 if (!context->getExtensions().debug)
2035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002037 return false;
2038 }
2039
Geoff Lang70d0f492015-12-10 17:45:46 -05002040 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2041 {
2042 return false;
2043 }
2044
Martin Radev9d901792016-07-15 15:58:58 +03002045 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002046 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002047 return false;
2048 }
2049
Geoff Lange102fee2015-12-10 11:23:30 -05002050 return true;
2051}
2052
2053bool ValidateGetObjectLabelKHR(Context *context,
2054 GLenum identifier,
2055 GLuint name,
2056 GLsizei bufSize,
2057 GLsizei *length,
2058 GLchar *label)
2059{
2060 if (!context->getExtensions().debug)
2061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002063 return false;
2064 }
2065
Geoff Lang70d0f492015-12-10 17:45:46 -05002066 if (bufSize < 0)
2067 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002068 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002069 return false;
2070 }
2071
2072 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2073 {
2074 return false;
2075 }
2076
Martin Radev9d901792016-07-15 15:58:58 +03002077 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05002078}
2079
2080static bool ValidateObjectPtrName(Context *context, const void *ptr)
2081{
2082 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002084 context->handleError(InvalidValue() << "name is not a valid sync.");
Geoff Lang70d0f492015-12-10 17:45:46 -05002085 return false;
2086 }
2087
Geoff Lange102fee2015-12-10 11:23:30 -05002088 return true;
2089}
2090
2091bool ValidateObjectPtrLabelKHR(Context *context,
2092 const void *ptr,
2093 GLsizei length,
2094 const GLchar *label)
2095{
2096 if (!context->getExtensions().debug)
2097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002099 return false;
2100 }
2101
Geoff Lang70d0f492015-12-10 17:45:46 -05002102 if (!ValidateObjectPtrName(context, ptr))
2103 {
2104 return false;
2105 }
2106
Martin Radev9d901792016-07-15 15:58:58 +03002107 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05002108 {
Geoff Lang70d0f492015-12-10 17:45:46 -05002109 return false;
2110 }
2111
Geoff Lange102fee2015-12-10 11:23:30 -05002112 return true;
2113}
2114
2115bool ValidateGetObjectPtrLabelKHR(Context *context,
2116 const void *ptr,
2117 GLsizei bufSize,
2118 GLsizei *length,
2119 GLchar *label)
2120{
2121 if (!context->getExtensions().debug)
2122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002124 return false;
2125 }
2126
Geoff Lang70d0f492015-12-10 17:45:46 -05002127 if (bufSize < 0)
2128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002129 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang70d0f492015-12-10 17:45:46 -05002130 return false;
2131 }
2132
2133 if (!ValidateObjectPtrName(context, ptr))
2134 {
2135 return false;
2136 }
2137
Martin Radev9d901792016-07-15 15:58:58 +03002138 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05002139}
2140
2141bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
2142{
2143 if (!context->getExtensions().debug)
2144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lange102fee2015-12-10 11:23:30 -05002146 return false;
2147 }
2148
Geoff Lang70d0f492015-12-10 17:45:46 -05002149 // TODO: represent this in Context::getQueryParameterInfo.
2150 switch (pname)
2151 {
2152 case GL_DEBUG_CALLBACK_FUNCTION:
2153 case GL_DEBUG_CALLBACK_USER_PARAM:
2154 break;
2155
2156 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang70d0f492015-12-10 17:45:46 -05002158 return false;
2159 }
2160
Geoff Lange102fee2015-12-10 11:23:30 -05002161 return true;
2162}
Jamie Madillc29968b2016-01-20 11:17:23 -05002163
2164bool ValidateBlitFramebufferANGLE(Context *context,
2165 GLint srcX0,
2166 GLint srcY0,
2167 GLint srcX1,
2168 GLint srcY1,
2169 GLint dstX0,
2170 GLint dstY0,
2171 GLint dstX1,
2172 GLint dstY1,
2173 GLbitfield mask,
2174 GLenum filter)
2175{
2176 if (!context->getExtensions().framebufferBlit)
2177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002178 context->handleError(InvalidOperation() << "Blit extension not available.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002179 return false;
2180 }
2181
2182 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2183 {
2184 // TODO(jmadill): Determine if this should be available on other implementations.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002185 context->handleError(InvalidOperation() << "Scaling and flipping in "
2186 "BlitFramebufferANGLE not supported by this "
2187 "implementation.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002188 return false;
2189 }
2190
2191 if (filter == GL_LINEAR)
2192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002193 context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
Jamie Madillc29968b2016-01-20 11:17:23 -05002194 return false;
2195 }
2196
Jamie Madill51f40ec2016-06-15 14:06:00 -04002197 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2198 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002199
2200 if (mask & GL_COLOR_BUFFER_BIT)
2201 {
2202 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2203 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2204
2205 if (readColorAttachment && drawColorAttachment)
2206 {
2207 if (!(readColorAttachment->type() == GL_TEXTURE &&
2208 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2209 readColorAttachment->type() != GL_RENDERBUFFER &&
2210 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002212 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002213 return false;
2214 }
2215
Geoff Langa15472a2015-08-11 11:48:03 -04002216 for (size_t drawbufferIdx = 0;
2217 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002218 {
Geoff Langa15472a2015-08-11 11:48:03 -04002219 const FramebufferAttachment *attachment =
2220 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2221 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002222 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002223 if (!(attachment->type() == GL_TEXTURE &&
2224 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2225 attachment->type() != GL_RENDERBUFFER &&
2226 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002228 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002229 return false;
2230 }
2231
2232 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002233 if (!Format::SameSized(attachment->getFormat(),
2234 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002237 return false;
2238 }
2239 }
2240 }
2241
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002242 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002243 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2244 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002246 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002247 return false;
2248 }
2249 }
2250 }
2251
2252 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2253 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2254 for (size_t i = 0; i < 2; i++)
2255 {
2256 if (mask & masks[i])
2257 {
2258 const FramebufferAttachment *readBuffer =
2259 readFramebuffer->getAttachment(attachments[i]);
2260 const FramebufferAttachment *drawBuffer =
2261 drawFramebuffer->getAttachment(attachments[i]);
2262
2263 if (readBuffer && drawBuffer)
2264 {
2265 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2266 dstX0, dstY0, dstX1, dstY1))
2267 {
2268 // only whole-buffer copies are permitted
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002269 context->handleError(InvalidOperation() << "Only whole-buffer depth and "
2270 "stencil blits are supported by "
2271 "this extension.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002272 return false;
2273 }
2274
2275 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002277 context->handleError(InvalidOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002278 return false;
2279 }
2280 }
2281 }
2282 }
2283
2284 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2285 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002286}
Jamie Madillc29968b2016-01-20 11:17:23 -05002287
2288bool ValidateClear(ValidationContext *context, GLbitfield mask)
2289{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002290 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002291 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002293 context->handleError(InvalidFramebufferOperation());
Jamie Madillc29968b2016-01-20 11:17:23 -05002294 return false;
2295 }
2296
2297 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002299 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
Jamie Madillc29968b2016-01-20 11:17:23 -05002300 return false;
2301 }
2302
Geoff Lang76e65652017-03-27 14:58:02 -04002303 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2304 {
2305 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2306 GL_SIGNED_NORMALIZED};
2307
Corentin Wallez59c41592017-07-11 13:19:54 -04002308 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
Geoff Lang76e65652017-03-27 14:58:02 -04002309 drawBufferIdx++)
2310 {
2311 if (!ValidateWebGLFramebufferAttachmentClearType(
2312 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2313 {
2314 return false;
2315 }
2316 }
2317 }
2318
Jamie Madillc29968b2016-01-20 11:17:23 -05002319 return true;
2320}
2321
2322bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2323{
2324 if (!context->getExtensions().drawBuffers)
2325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002326 context->handleError(InvalidOperation() << "Extension not supported.");
Jamie Madillc29968b2016-01-20 11:17:23 -05002327 return false;
2328 }
2329
2330 return ValidateDrawBuffersBase(context, n, bufs);
2331}
2332
Jamie Madill73a84962016-02-12 09:27:23 -05002333bool ValidateTexImage2D(Context *context,
2334 GLenum target,
2335 GLint level,
2336 GLint internalformat,
2337 GLsizei width,
2338 GLsizei height,
2339 GLint border,
2340 GLenum format,
2341 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002342 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002343{
Martin Radev1be913c2016-07-11 17:59:16 +03002344 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002345 {
2346 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002347 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002348 }
2349
Martin Radev1be913c2016-07-11 17:59:16 +03002350 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002351 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002352 0, 0, width, height, 1, border, format, type, -1,
2353 pixels);
2354}
2355
2356bool ValidateTexImage2DRobust(Context *context,
2357 GLenum target,
2358 GLint level,
2359 GLint internalformat,
2360 GLsizei width,
2361 GLsizei height,
2362 GLint border,
2363 GLenum format,
2364 GLenum type,
2365 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002366 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002367{
2368 if (!ValidateRobustEntryPoint(context, bufSize))
2369 {
2370 return false;
2371 }
2372
2373 if (context->getClientMajorVersion() < 3)
2374 {
2375 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2376 0, 0, width, height, border, format, type, bufSize,
2377 pixels);
2378 }
2379
2380 ASSERT(context->getClientMajorVersion() >= 3);
2381 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2382 0, 0, width, height, 1, border, format, type, bufSize,
2383 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002384}
2385
2386bool ValidateTexSubImage2D(Context *context,
2387 GLenum target,
2388 GLint level,
2389 GLint xoffset,
2390 GLint yoffset,
2391 GLsizei width,
2392 GLsizei height,
2393 GLenum format,
2394 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002395 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002396{
2397
Martin Radev1be913c2016-07-11 17:59:16 +03002398 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002399 {
2400 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002401 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002402 }
2403
Martin Radev1be913c2016-07-11 17:59:16 +03002404 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002405 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002406 yoffset, 0, width, height, 1, 0, format, type, -1,
2407 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002408}
2409
Geoff Langc52f6f12016-10-14 10:18:00 -04002410bool ValidateTexSubImage2DRobustANGLE(Context *context,
2411 GLenum target,
2412 GLint level,
2413 GLint xoffset,
2414 GLint yoffset,
2415 GLsizei width,
2416 GLsizei height,
2417 GLenum format,
2418 GLenum type,
2419 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002420 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002421{
2422 if (!ValidateRobustEntryPoint(context, bufSize))
2423 {
2424 return false;
2425 }
2426
2427 if (context->getClientMajorVersion() < 3)
2428 {
2429 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2430 yoffset, width, height, 0, format, type, bufSize,
2431 pixels);
2432 }
2433
2434 ASSERT(context->getClientMajorVersion() >= 3);
2435 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2436 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2437 pixels);
2438}
2439
Jamie Madill73a84962016-02-12 09:27:23 -05002440bool ValidateCompressedTexImage2D(Context *context,
2441 GLenum target,
2442 GLint level,
2443 GLenum internalformat,
2444 GLsizei width,
2445 GLsizei height,
2446 GLint border,
2447 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002448 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002449{
Martin Radev1be913c2016-07-11 17:59:16 +03002450 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002451 {
2452 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002453 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002454 {
2455 return false;
2456 }
2457 }
2458 else
2459 {
Martin Radev1be913c2016-07-11 17:59:16 +03002460 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002461 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002462 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002463 data))
2464 {
2465 return false;
2466 }
2467 }
2468
Geoff Langca271392017-04-05 12:30:00 -04002469 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002470 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002471 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002472 if (blockSizeOrErr.isError())
2473 {
2474 context->handleError(blockSizeOrErr.getError());
2475 return false;
2476 }
2477
2478 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002480 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002481 return false;
2482 }
2483
2484 return true;
2485}
2486
Corentin Wallezb2931602017-04-11 15:58:57 -04002487bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2488 GLenum target,
2489 GLint level,
2490 GLenum internalformat,
2491 GLsizei width,
2492 GLsizei height,
2493 GLint border,
2494 GLsizei imageSize,
2495 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002496 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002497{
2498 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2499 {
2500 return false;
2501 }
2502
2503 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2504 border, imageSize, data);
2505}
2506bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2507 GLenum target,
2508 GLint level,
2509 GLint xoffset,
2510 GLint yoffset,
2511 GLsizei width,
2512 GLsizei height,
2513 GLenum format,
2514 GLsizei imageSize,
2515 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002516 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002517{
2518 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2519 {
2520 return false;
2521 }
2522
2523 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2524 format, imageSize, data);
2525}
2526
Jamie Madill73a84962016-02-12 09:27:23 -05002527bool ValidateCompressedTexSubImage2D(Context *context,
2528 GLenum target,
2529 GLint level,
2530 GLint xoffset,
2531 GLint yoffset,
2532 GLsizei width,
2533 GLsizei height,
2534 GLenum format,
2535 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002536 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002537{
Martin Radev1be913c2016-07-11 17:59:16 +03002538 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002539 {
2540 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002541 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002542 {
2543 return false;
2544 }
2545 }
2546 else
2547 {
Martin Radev1be913c2016-07-11 17:59:16 +03002548 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002549 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002550 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002551 data))
2552 {
2553 return false;
2554 }
2555 }
2556
Geoff Langca271392017-04-05 12:30:00 -04002557 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002558 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002559 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002560 if (blockSizeOrErr.isError())
2561 {
2562 context->handleError(blockSizeOrErr.getError());
2563 return false;
2564 }
2565
2566 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002569 return false;
2570 }
2571
2572 return true;
2573}
2574
Olli Etuaho4f667482016-03-30 15:56:35 +03002575bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2576{
Geoff Lang496c02d2016-10-20 11:38:11 -07002577 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002578}
2579
2580bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2581{
2582 if (!context->getExtensions().mapBuffer)
2583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002585 return false;
2586 }
2587
2588 if (!ValidBufferTarget(context, target))
2589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03002591 return false;
2592 }
2593
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002594 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002595
2596 if (buffer == nullptr)
2597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002599 return false;
2600 }
2601
2602 if (access != GL_WRITE_ONLY_OES)
2603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002604 context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002605 return false;
2606 }
2607
2608 if (buffer->isMapped())
2609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002610 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002611 return false;
2612 }
2613
2614 return true;
2615}
2616
2617bool ValidateUnmapBufferOES(Context *context, GLenum target)
2618{
2619 if (!context->getExtensions().mapBuffer)
2620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002621 context->handleError(InvalidOperation() << "Map buffer extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002622 return false;
2623 }
2624
2625 return ValidateUnmapBufferBase(context, target);
2626}
2627
2628bool ValidateMapBufferRangeEXT(Context *context,
2629 GLenum target,
2630 GLintptr offset,
2631 GLsizeiptr length,
2632 GLbitfield access)
2633{
2634 if (!context->getExtensions().mapBufferRange)
2635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002636 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002637 return false;
2638 }
2639
2640 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2641}
2642
2643bool ValidateFlushMappedBufferRangeEXT(Context *context,
2644 GLenum target,
2645 GLintptr offset,
2646 GLsizeiptr length)
2647{
2648 if (!context->getExtensions().mapBufferRange)
2649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002650 context->handleError(InvalidOperation() << "Map buffer range extension not available.");
Olli Etuaho4f667482016-03-30 15:56:35 +03002651 return false;
2652 }
2653
2654 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2655}
2656
Ian Ewell54f87462016-03-10 13:47:21 -05002657bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2658{
2659 Texture *textureObject = context->getTexture(texture);
2660 if (textureObject && textureObject->getTarget() != target && texture != 0)
2661 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMustMatchOriginalType);
Ian Ewell54f87462016-03-10 13:47:21 -05002663 return false;
2664 }
2665
Geoff Langf41a7152016-09-19 15:11:17 -04002666 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2667 !context->isTextureGenerated(texture))
2668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002669 context->handleError(InvalidOperation() << "Texture was not generated");
Geoff Langf41a7152016-09-19 15:11:17 -04002670 return false;
2671 }
2672
Ian Ewell54f87462016-03-10 13:47:21 -05002673 switch (target)
2674 {
2675 case GL_TEXTURE_2D:
2676 case GL_TEXTURE_CUBE_MAP:
2677 break;
2678
2679 case GL_TEXTURE_3D:
2680 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002681 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002683 context->handleError(InvalidEnum() << "GLES 3.0 disabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002684 return false;
2685 }
2686 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002687
2688 case GL_TEXTURE_2D_MULTISAMPLE:
2689 if (context->getClientVersion() < Version(3, 1))
2690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002691 context->handleError(InvalidEnum() << "Context does not support GLES3.1");
Geoff Lang3b573612016-10-31 14:08:10 -04002692 return false;
2693 }
Geoff Lang3b573612016-10-31 14:08:10 -04002694 break;
2695
Ian Ewell54f87462016-03-10 13:47:21 -05002696 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002697 if (!context->getExtensions().eglImageExternal &&
2698 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002700 context->handleError(InvalidEnum() << "External texture extension not enabled");
Ian Ewell54f87462016-03-10 13:47:21 -05002701 return false;
2702 }
2703 break;
2704 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002705 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Ian Ewell54f87462016-03-10 13:47:21 -05002706 return false;
2707 }
2708
2709 return true;
2710}
2711
Geoff Langd8605522016-04-13 10:19:12 -04002712bool ValidateBindUniformLocationCHROMIUM(Context *context,
2713 GLuint program,
2714 GLint location,
2715 const GLchar *name)
2716{
2717 if (!context->getExtensions().bindUniformLocation)
2718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002719 context->handleError(InvalidOperation()
2720 << "GL_CHROMIUM_bind_uniform_location is not available.");
Geoff Langd8605522016-04-13 10:19:12 -04002721 return false;
2722 }
2723
2724 Program *programObject = GetValidProgram(context, program);
2725 if (!programObject)
2726 {
2727 return false;
2728 }
2729
2730 if (location < 0)
2731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002732 context->handleError(InvalidValue() << "Location cannot be less than 0.");
Geoff Langd8605522016-04-13 10:19:12 -04002733 return false;
2734 }
2735
2736 const Caps &caps = context->getCaps();
2737 if (static_cast<size_t>(location) >=
2738 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002740 context->handleError(InvalidValue() << "Location must be less than "
2741 "(MAX_VERTEX_UNIFORM_VECTORS + "
2742 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
Geoff Langd8605522016-04-13 10:19:12 -04002743 return false;
2744 }
2745
Geoff Langfc32e8b2017-05-31 14:16:59 -04002746 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
2747 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04002748 if (context->getExtensions().webglCompatibility &&
2749 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04002750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002751 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04002752 return false;
2753 }
2754
Geoff Langd8605522016-04-13 10:19:12 -04002755 if (strncmp(name, "gl_", 3) == 0)
2756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002757 ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
Geoff Langd8605522016-04-13 10:19:12 -04002758 return false;
2759 }
2760
2761 return true;
2762}
2763
Jamie Madille2e406c2016-06-02 13:04:10 -04002764bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002765{
2766 if (!context->getExtensions().framebufferMixedSamples)
2767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002768 context->handleError(InvalidOperation()
2769 << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
Sami Väisänena797e062016-05-12 15:23:40 +03002770 return false;
2771 }
2772 switch (components)
2773 {
2774 case GL_RGB:
2775 case GL_RGBA:
2776 case GL_ALPHA:
2777 case GL_NONE:
2778 break;
2779 default:
2780 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002781 InvalidEnum()
2782 << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
Sami Väisänena797e062016-05-12 15:23:40 +03002783 return false;
2784 }
2785
2786 return true;
2787}
2788
Sami Väisänene45e53b2016-05-25 10:36:04 +03002789// CHROMIUM_path_rendering
2790
2791bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2792{
2793 if (!context->getExtensions().pathRendering)
2794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002795 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002796 return false;
2797 }
2798 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002800 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002801 return false;
2802 }
2803 if (matrix == nullptr)
2804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002805 context->handleError(InvalidOperation() << "Invalid matrix.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002806 return false;
2807 }
2808 return true;
2809}
2810
2811bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2812{
2813 if (!context->getExtensions().pathRendering)
2814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002815 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002816 return false;
2817 }
2818 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002820 context->handleError(InvalidEnum() << "Invalid matrix mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002821 return false;
2822 }
2823 return true;
2824}
2825
2826bool ValidateGenPaths(Context *context, GLsizei range)
2827{
2828 if (!context->getExtensions().pathRendering)
2829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002830 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002831 return false;
2832 }
2833
2834 // range = 0 is undefined in NV_path_rendering.
2835 // we add stricter semantic check here and require a non zero positive range.
2836 if (range <= 0)
2837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002838 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002839 return false;
2840 }
2841
2842 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002845 return false;
2846 }
2847
2848 return true;
2849}
2850
2851bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2852{
2853 if (!context->getExtensions().pathRendering)
2854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002855 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002856 return false;
2857 }
2858
2859 // range = 0 is undefined in NV_path_rendering.
2860 // we add stricter semantic check here and require a non zero positive range.
2861 if (range <= 0)
2862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002863 context->handleError(InvalidValue() << "Invalid range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002864 return false;
2865 }
2866
2867 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2868 checkedRange += range;
2869
2870 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002873 return false;
2874 }
2875 return true;
2876}
2877
2878bool ValidatePathCommands(Context *context,
2879 GLuint path,
2880 GLsizei numCommands,
2881 const GLubyte *commands,
2882 GLsizei numCoords,
2883 GLenum coordType,
2884 const void *coords)
2885{
2886 if (!context->getExtensions().pathRendering)
2887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002888 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002889 return false;
2890 }
2891 if (!context->hasPath(path))
2892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002893 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002894 return false;
2895 }
2896
2897 if (numCommands < 0)
2898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002899 context->handleError(InvalidValue() << "Invalid number of commands.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002900 return false;
2901 }
2902 else if (numCommands > 0)
2903 {
2904 if (!commands)
2905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002906 context->handleError(InvalidValue() << "No commands array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002907 return false;
2908 }
2909 }
2910
2911 if (numCoords < 0)
2912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002913 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002914 return false;
2915 }
2916 else if (numCoords > 0)
2917 {
2918 if (!coords)
2919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002920 context->handleError(InvalidValue() << "No coordinate array given.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002921 return false;
2922 }
2923 }
2924
2925 std::uint32_t coordTypeSize = 0;
2926 switch (coordType)
2927 {
2928 case GL_BYTE:
2929 coordTypeSize = sizeof(GLbyte);
2930 break;
2931
2932 case GL_UNSIGNED_BYTE:
2933 coordTypeSize = sizeof(GLubyte);
2934 break;
2935
2936 case GL_SHORT:
2937 coordTypeSize = sizeof(GLshort);
2938 break;
2939
2940 case GL_UNSIGNED_SHORT:
2941 coordTypeSize = sizeof(GLushort);
2942 break;
2943
2944 case GL_FLOAT:
2945 coordTypeSize = sizeof(GLfloat);
2946 break;
2947
2948 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002949 context->handleError(InvalidEnum() << "Invalid coordinate type.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002950 return false;
2951 }
2952
2953 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2954 checkedSize += (coordTypeSize * numCoords);
2955 if (!checkedSize.IsValid())
2956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Sami Väisänene45e53b2016-05-25 10:36:04 +03002958 return false;
2959 }
2960
2961 // early return skips command data validation when it doesn't exist.
2962 if (!commands)
2963 return true;
2964
2965 GLsizei expectedNumCoords = 0;
2966 for (GLsizei i = 0; i < numCommands; ++i)
2967 {
2968 switch (commands[i])
2969 {
2970 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2971 break;
2972 case GL_MOVE_TO_CHROMIUM:
2973 case GL_LINE_TO_CHROMIUM:
2974 expectedNumCoords += 2;
2975 break;
2976 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2977 expectedNumCoords += 4;
2978 break;
2979 case GL_CUBIC_CURVE_TO_CHROMIUM:
2980 expectedNumCoords += 6;
2981 break;
2982 case GL_CONIC_CURVE_TO_CHROMIUM:
2983 expectedNumCoords += 5;
2984 break;
2985 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002986 context->handleError(InvalidEnum() << "Invalid command.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002987 return false;
2988 }
2989 }
2990 if (expectedNumCoords != numCoords)
2991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002992 context->handleError(InvalidValue() << "Invalid number of coordinates.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03002993 return false;
2994 }
2995
2996 return true;
2997}
2998
2999bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
3000{
3001 if (!context->getExtensions().pathRendering)
3002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003003 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003004 return false;
3005 }
3006 if (!context->hasPath(path))
3007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003008 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003009 return false;
3010 }
3011
3012 switch (pname)
3013 {
3014 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3015 if (value < 0.0f)
3016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003017 context->handleError(InvalidValue() << "Invalid stroke width.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003018 return false;
3019 }
3020 break;
3021 case GL_PATH_END_CAPS_CHROMIUM:
3022 switch (static_cast<GLenum>(value))
3023 {
3024 case GL_FLAT_CHROMIUM:
3025 case GL_SQUARE_CHROMIUM:
3026 case GL_ROUND_CHROMIUM:
3027 break;
3028 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003029 context->handleError(InvalidEnum() << "Invalid end caps.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003030 return false;
3031 }
3032 break;
3033 case GL_PATH_JOIN_STYLE_CHROMIUM:
3034 switch (static_cast<GLenum>(value))
3035 {
3036 case GL_MITER_REVERT_CHROMIUM:
3037 case GL_BEVEL_CHROMIUM:
3038 case GL_ROUND_CHROMIUM:
3039 break;
3040 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003041 context->handleError(InvalidEnum() << "Invalid join style.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003042 return false;
3043 }
3044 case GL_PATH_MITER_LIMIT_CHROMIUM:
3045 if (value < 0.0f)
3046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003047 context->handleError(InvalidValue() << "Invalid miter limit.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003048 return false;
3049 }
3050 break;
3051
3052 case GL_PATH_STROKE_BOUND_CHROMIUM:
3053 // no errors, only clamping.
3054 break;
3055
3056 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003057 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003058 return false;
3059 }
3060 return true;
3061}
3062
3063bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
3064{
3065 if (!context->getExtensions().pathRendering)
3066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003067 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003068 return false;
3069 }
3070
3071 if (!context->hasPath(path))
3072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003073 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003074 return false;
3075 }
3076 if (!value)
3077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003078 context->handleError(InvalidValue() << "No value array.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003079 return false;
3080 }
3081
3082 switch (pname)
3083 {
3084 case GL_PATH_STROKE_WIDTH_CHROMIUM:
3085 case GL_PATH_END_CAPS_CHROMIUM:
3086 case GL_PATH_JOIN_STYLE_CHROMIUM:
3087 case GL_PATH_MITER_LIMIT_CHROMIUM:
3088 case GL_PATH_STROKE_BOUND_CHROMIUM:
3089 break;
3090
3091 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003092 context->handleError(InvalidEnum() << "Invalid path parameter.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003093 return false;
3094 }
3095
3096 return true;
3097}
3098
3099bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
3100{
3101 if (!context->getExtensions().pathRendering)
3102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003103 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003104 return false;
3105 }
3106
3107 switch (func)
3108 {
3109 case GL_NEVER:
3110 case GL_ALWAYS:
3111 case GL_LESS:
3112 case GL_LEQUAL:
3113 case GL_EQUAL:
3114 case GL_GEQUAL:
3115 case GL_GREATER:
3116 case GL_NOTEQUAL:
3117 break;
3118 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Sami Väisänene45e53b2016-05-25 10:36:04 +03003120 return false;
3121 }
3122
3123 return true;
3124}
3125
3126// Note that the spec specifies that for the path drawing commands
3127// if the path object is not an existing path object the command
3128// does nothing and no error is generated.
3129// However if the path object exists but has not been specified any
3130// commands then an error is generated.
3131
3132bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
3133{
3134 if (!context->getExtensions().pathRendering)
3135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003136 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003137 return false;
3138 }
3139 if (context->hasPath(path) && !context->hasPathData(path))
3140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003141 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003142 return false;
3143 }
3144
3145 switch (fillMode)
3146 {
3147 case GL_COUNT_UP_CHROMIUM:
3148 case GL_COUNT_DOWN_CHROMIUM:
3149 break;
3150 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003151 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003152 return false;
3153 }
3154
3155 if (!isPow2(mask + 1))
3156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003157 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003158 return false;
3159 }
3160
3161 return true;
3162}
3163
3164bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
3165{
3166 if (!context->getExtensions().pathRendering)
3167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003168 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003169 return false;
3170 }
3171 if (context->hasPath(path) && !context->hasPathData(path))
3172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003173 context->handleError(InvalidOperation() << "No such path or path has no data.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003174 return false;
3175 }
3176
3177 return true;
3178}
3179
3180bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
3181{
3182 if (!context->getExtensions().pathRendering)
3183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003184 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003185 return false;
3186 }
3187 if (context->hasPath(path) && !context->hasPathData(path))
3188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003189 context->handleError(InvalidOperation() << "No such path object.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003190 return false;
3191 }
3192
3193 switch (coverMode)
3194 {
3195 case GL_CONVEX_HULL_CHROMIUM:
3196 case GL_BOUNDING_BOX_CHROMIUM:
3197 break;
3198 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003199 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003200 return false;
3201 }
3202 return true;
3203}
3204
3205bool ValidateStencilThenCoverFillPath(Context *context,
3206 GLuint path,
3207 GLenum fillMode,
3208 GLuint mask,
3209 GLenum coverMode)
3210{
3211 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3212 ValidateCoverPath(context, path, coverMode);
3213}
3214
3215bool ValidateStencilThenCoverStrokePath(Context *context,
3216 GLuint path,
3217 GLint reference,
3218 GLuint mask,
3219 GLenum coverMode)
3220{
3221 return ValidateStencilStrokePath(context, path, reference, mask) &&
3222 ValidateCoverPath(context, path, coverMode);
3223}
3224
3225bool ValidateIsPath(Context *context)
3226{
3227 if (!context->getExtensions().pathRendering)
3228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003229 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänene45e53b2016-05-25 10:36:04 +03003230 return false;
3231 }
3232 return true;
3233}
3234
Sami Väisänend59ca052016-06-21 16:10:00 +03003235bool ValidateCoverFillPathInstanced(Context *context,
3236 GLsizei numPaths,
3237 GLenum pathNameType,
3238 const void *paths,
3239 GLuint pathBase,
3240 GLenum coverMode,
3241 GLenum transformType,
3242 const GLfloat *transformValues)
3243{
3244 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3245 transformType, transformValues))
3246 return false;
3247
3248 switch (coverMode)
3249 {
3250 case GL_CONVEX_HULL_CHROMIUM:
3251 case GL_BOUNDING_BOX_CHROMIUM:
3252 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3253 break;
3254 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003255 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003256 return false;
3257 }
3258
3259 return true;
3260}
3261
3262bool ValidateCoverStrokePathInstanced(Context *context,
3263 GLsizei numPaths,
3264 GLenum pathNameType,
3265 const void *paths,
3266 GLuint pathBase,
3267 GLenum coverMode,
3268 GLenum transformType,
3269 const GLfloat *transformValues)
3270{
3271 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3272 transformType, transformValues))
3273 return false;
3274
3275 switch (coverMode)
3276 {
3277 case GL_CONVEX_HULL_CHROMIUM:
3278 case GL_BOUNDING_BOX_CHROMIUM:
3279 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3280 break;
3281 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003282 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003283 return false;
3284 }
3285
3286 return true;
3287}
3288
3289bool ValidateStencilFillPathInstanced(Context *context,
3290 GLsizei numPaths,
3291 GLenum pathNameType,
3292 const void *paths,
3293 GLuint pathBase,
3294 GLenum fillMode,
3295 GLuint mask,
3296 GLenum transformType,
3297 const GLfloat *transformValues)
3298{
3299
3300 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3301 transformType, transformValues))
3302 return false;
3303
3304 switch (fillMode)
3305 {
3306 case GL_COUNT_UP_CHROMIUM:
3307 case GL_COUNT_DOWN_CHROMIUM:
3308 break;
3309 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003310 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003311 return false;
3312 }
3313 if (!isPow2(mask + 1))
3314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003315 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003316 return false;
3317 }
3318 return true;
3319}
3320
3321bool ValidateStencilStrokePathInstanced(Context *context,
3322 GLsizei numPaths,
3323 GLenum pathNameType,
3324 const void *paths,
3325 GLuint pathBase,
3326 GLint reference,
3327 GLuint mask,
3328 GLenum transformType,
3329 const GLfloat *transformValues)
3330{
3331 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3332 transformType, transformValues))
3333 return false;
3334
3335 // no more validation here.
3336
3337 return true;
3338}
3339
3340bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3341 GLsizei numPaths,
3342 GLenum pathNameType,
3343 const void *paths,
3344 GLuint pathBase,
3345 GLenum fillMode,
3346 GLuint mask,
3347 GLenum coverMode,
3348 GLenum transformType,
3349 const GLfloat *transformValues)
3350{
3351 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3352 transformType, transformValues))
3353 return false;
3354
3355 switch (coverMode)
3356 {
3357 case GL_CONVEX_HULL_CHROMIUM:
3358 case GL_BOUNDING_BOX_CHROMIUM:
3359 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3360 break;
3361 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003362 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003363 return false;
3364 }
3365
3366 switch (fillMode)
3367 {
3368 case GL_COUNT_UP_CHROMIUM:
3369 case GL_COUNT_DOWN_CHROMIUM:
3370 break;
3371 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003372 context->handleError(InvalidEnum() << "Invalid fill mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003373 return false;
3374 }
3375 if (!isPow2(mask + 1))
3376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003377 context->handleError(InvalidValue() << "Invalid stencil bit mask.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003378 return false;
3379 }
3380
3381 return true;
3382}
3383
3384bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3385 GLsizei numPaths,
3386 GLenum pathNameType,
3387 const void *paths,
3388 GLuint pathBase,
3389 GLint reference,
3390 GLuint mask,
3391 GLenum coverMode,
3392 GLenum transformType,
3393 const GLfloat *transformValues)
3394{
3395 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3396 transformType, transformValues))
3397 return false;
3398
3399 switch (coverMode)
3400 {
3401 case GL_CONVEX_HULL_CHROMIUM:
3402 case GL_BOUNDING_BOX_CHROMIUM:
3403 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3404 break;
3405 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003406 context->handleError(InvalidEnum() << "Invalid cover mode.");
Sami Väisänend59ca052016-06-21 16:10:00 +03003407 return false;
3408 }
3409
3410 return true;
3411}
3412
Sami Väisänen46eaa942016-06-29 10:26:37 +03003413bool ValidateBindFragmentInputLocation(Context *context,
3414 GLuint program,
3415 GLint location,
3416 const GLchar *name)
3417{
3418 if (!context->getExtensions().pathRendering)
3419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003420 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003421 return false;
3422 }
3423
3424 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3425 if (location >= MaxLocation)
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidValue() << "Location exceeds max varying.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003428 return false;
3429 }
3430
3431 const auto *programObject = context->getProgram(program);
3432 if (!programObject)
3433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003435 return false;
3436 }
3437
3438 if (!name)
3439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003440 context->handleError(InvalidValue() << "No name given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003441 return false;
3442 }
3443
3444 if (angle::BeginsWith(name, "gl_"))
3445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003446 context->handleError(InvalidOperation() << "Cannot bind a built-in variable.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003447 return false;
3448 }
3449
3450 return true;
3451}
3452
3453bool ValidateProgramPathFragmentInputGen(Context *context,
3454 GLuint program,
3455 GLint location,
3456 GLenum genMode,
3457 GLint components,
3458 const GLfloat *coeffs)
3459{
3460 if (!context->getExtensions().pathRendering)
3461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003462 context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003463 return false;
3464 }
3465
3466 const auto *programObject = context->getProgram(program);
3467 if (!programObject || programObject->isFlaggedForDeletion())
3468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003470 return false;
3471 }
3472
3473 if (!programObject->isLinked())
3474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003476 return false;
3477 }
3478
3479 switch (genMode)
3480 {
3481 case GL_NONE:
3482 if (components != 0)
3483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003484 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003485 return false;
3486 }
3487 break;
3488
3489 case GL_OBJECT_LINEAR_CHROMIUM:
3490 case GL_EYE_LINEAR_CHROMIUM:
3491 case GL_CONSTANT_CHROMIUM:
3492 if (components < 1 || components > 4)
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidValue() << "Invalid components.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003495 return false;
3496 }
3497 if (!coeffs)
3498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003499 context->handleError(InvalidValue() << "No coefficients array given.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003500 return false;
3501 }
3502 break;
3503
3504 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidEnum() << "Invalid gen mode.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003506 return false;
3507 }
3508
3509 // If the location is -1 then the command is silently ignored
3510 // and no further validation is needed.
3511 if (location == -1)
3512 return true;
3513
Jamie Madillbd044ed2017-06-05 12:59:21 -04003514 const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
Sami Väisänen46eaa942016-06-29 10:26:37 +03003515
3516 if (!binding.valid)
3517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003518 context->handleError(InvalidOperation() << "No such binding.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003519 return false;
3520 }
3521
3522 if (binding.type != GL_NONE)
3523 {
3524 GLint expectedComponents = 0;
3525 switch (binding.type)
3526 {
3527 case GL_FLOAT:
3528 expectedComponents = 1;
3529 break;
3530 case GL_FLOAT_VEC2:
3531 expectedComponents = 2;
3532 break;
3533 case GL_FLOAT_VEC3:
3534 expectedComponents = 3;
3535 break;
3536 case GL_FLOAT_VEC4:
3537 expectedComponents = 4;
3538 break;
3539 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003540 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003541 InvalidOperation()
3542 << "Fragment input type is not a floating point scalar or vector.");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003543 return false;
3544 }
3545 if (expectedComponents != components && genMode != GL_NONE)
3546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003547 context->handleError(InvalidOperation() << "Unexpected number of components");
Sami Väisänen46eaa942016-06-29 10:26:37 +03003548 return false;
3549 }
3550 }
3551 return true;
3552}
3553
Geoff Lang97073d12016-04-20 10:42:34 -07003554bool ValidateCopyTextureCHROMIUM(Context *context,
3555 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003556 GLint sourceLevel,
3557 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003558 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003559 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003560 GLint internalFormat,
3561 GLenum destType,
3562 GLboolean unpackFlipY,
3563 GLboolean unpackPremultiplyAlpha,
3564 GLboolean unpackUnmultiplyAlpha)
3565{
3566 if (!context->getExtensions().copyTexture)
3567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003568 context->handleError(InvalidOperation()
3569 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003570 return false;
3571 }
3572
Geoff Lang4f0e0032017-05-01 16:04:35 -04003573 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003574 if (source == nullptr)
3575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003577 return false;
3578 }
3579
3580 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003582 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003583 return false;
3584 }
3585
3586 GLenum sourceTarget = source->getTarget();
3587 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003588
3589 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003591 context->handleError(InvalidValue() << "Source texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003592 return false;
3593 }
3594
Geoff Lang4f0e0032017-05-01 16:04:35 -04003595 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3596 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3597 if (sourceWidth == 0 || sourceHeight == 0)
3598 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003600 return false;
3601 }
3602
3603 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3604 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003606 context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003607 return false;
3608 }
3609
Geoff Lang4f0e0032017-05-01 16:04:35 -04003610 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003611 if (dest == nullptr)
3612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidValue()
3614 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003615 return false;
3616 }
3617
Geoff Lang4f0e0032017-05-01 16:04:35 -04003618 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003621 return false;
3622 }
3623
Geoff Lang4f0e0032017-05-01 16:04:35 -04003624 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
3625 sourceHeight))
3626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003627 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003628 return false;
3629 }
3630
Geoff Lang97073d12016-04-20 10:42:34 -07003631 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3632 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003633 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003634 return false;
3635 }
3636
Geoff Lang4f0e0032017-05-01 16:04:35 -04003637 if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
3638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(
3640 InvalidValue() << "Destination width and height must be equal for cube map textures.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003641 return false;
3642 }
3643
Geoff Lang97073d12016-04-20 10:42:34 -07003644 if (dest->getImmutableFormat())
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "Destination texture is immutable.");
Geoff Lang97073d12016-04-20 10:42:34 -07003647 return false;
3648 }
3649
3650 return true;
3651}
3652
3653bool ValidateCopySubTextureCHROMIUM(Context *context,
3654 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003655 GLint sourceLevel,
3656 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003657 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003658 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003659 GLint xoffset,
3660 GLint yoffset,
3661 GLint x,
3662 GLint y,
3663 GLsizei width,
3664 GLsizei height,
3665 GLboolean unpackFlipY,
3666 GLboolean unpackPremultiplyAlpha,
3667 GLboolean unpackUnmultiplyAlpha)
3668{
3669 if (!context->getExtensions().copyTexture)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "GL_CHROMIUM_copy_texture extension not available.");
Geoff Lang97073d12016-04-20 10:42:34 -07003673 return false;
3674 }
3675
Geoff Lang4f0e0032017-05-01 16:04:35 -04003676 const Texture *source = context->getTexture(sourceId);
Geoff Lang97073d12016-04-20 10:42:34 -07003677 if (source == nullptr)
3678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003679 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003680 return false;
3681 }
3682
3683 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidValue() << "Source texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003686 return false;
3687 }
3688
3689 GLenum sourceTarget = source->getTarget();
3690 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003691
3692 if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
3693 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003694 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Lang4f0e0032017-05-01 16:04:35 -04003695 return false;
3696 }
3697
3698 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3699 source->getHeight(sourceTarget, sourceLevel) == 0)
Geoff Lang97073d12016-04-20 10:42:34 -07003700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003701 context->handleError(InvalidValue()
3702 << "The source level of the source texture must be defined.");
Geoff Lang97073d12016-04-20 10:42:34 -07003703 return false;
3704 }
3705
3706 if (x < 0 || y < 0)
3707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidValue() << "x and y cannot be negative.");
Geoff Lang97073d12016-04-20 10:42:34 -07003709 return false;
3710 }
3711
3712 if (width < 0 || height < 0)
3713 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003714 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Lang97073d12016-04-20 10:42:34 -07003715 return false;
3716 }
3717
Geoff Lang4f0e0032017-05-01 16:04:35 -04003718 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3719 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003720 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003721 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
Geoff Lang97073d12016-04-20 10:42:34 -07003722 return false;
3723 }
3724
Geoff Lang4f0e0032017-05-01 16:04:35 -04003725 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3726 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003727 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
Geoff Lang97073d12016-04-20 10:42:34 -07003729 return false;
3730 }
3731
Geoff Lang4f0e0032017-05-01 16:04:35 -04003732 const Texture *dest = context->getTexture(destId);
Geoff Lang97073d12016-04-20 10:42:34 -07003733 if (dest == nullptr)
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidValue()
3736 << "Destination texture is not a valid texture object.");
Geoff Lang97073d12016-04-20 10:42:34 -07003737 return false;
3738 }
3739
Geoff Lang4f0e0032017-05-01 16:04:35 -04003740 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
Geoff Lang97073d12016-04-20 10:42:34 -07003741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(InvalidValue() << "Destination texture a valid texture type.");
Geoff Lang97073d12016-04-20 10:42:34 -07003743 return false;
3744 }
3745
Geoff Lang4f0e0032017-05-01 16:04:35 -04003746 if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
Geoff Lang97073d12016-04-20 10:42:34 -07003747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidValue() << "Destination texture level is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003749 return false;
3750 }
3751
Geoff Lang4f0e0032017-05-01 16:04:35 -04003752 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3753 {
Geoff Langbb1b19b2017-06-16 16:59:00 -04003754 context
3755 ->handleError(InvalidOperation()
3756 << "The destination level of the destination texture must be defined.");
Geoff Lang4f0e0032017-05-01 16:04:35 -04003757 return false;
3758 }
3759
3760 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3761 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidOperation()
3764 << "Destination internal format and type combination is not valid.");
Geoff Lang97073d12016-04-20 10:42:34 -07003765 return false;
3766 }
3767
3768 if (xoffset < 0 || yoffset < 0)
3769 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003770 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Geoff Lang97073d12016-04-20 10:42:34 -07003771 return false;
3772 }
3773
Geoff Lang4f0e0032017-05-01 16:04:35 -04003774 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3775 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
Geoff Lang97073d12016-04-20 10:42:34 -07003776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003777 context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
Geoff Lang97073d12016-04-20 10:42:34 -07003778 return false;
3779 }
3780
3781 return true;
3782}
3783
Geoff Lang47110bf2016-04-20 11:13:22 -07003784bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3785{
3786 if (!context->getExtensions().copyCompressedTexture)
3787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003788 context->handleError(InvalidOperation()
3789 << "GL_CHROMIUM_copy_compressed_texture extension not available.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003790 return false;
3791 }
3792
3793 const gl::Texture *source = context->getTexture(sourceId);
3794 if (source == nullptr)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003797 return false;
3798 }
3799
3800 if (source->getTarget() != GL_TEXTURE_2D)
3801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003802 context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003803 return false;
3804 }
3805
3806 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003808 context->handleError(InvalidValue() << "Source texture must level 0 defined.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003809 return false;
3810 }
3811
3812 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3813 if (!sourceFormat.info->compressed)
3814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003815 context->handleError(InvalidOperation()
3816 << "Source texture must have a compressed internal format.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003817 return false;
3818 }
3819
3820 const gl::Texture *dest = context->getTexture(destId);
3821 if (dest == nullptr)
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidValue()
3824 << "Destination texture is not a valid texture object.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003825 return false;
3826 }
3827
3828 if (dest->getTarget() != GL_TEXTURE_2D)
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidValue()
3831 << "Destination texture must be of type GL_TEXTURE_2D.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003832 return false;
3833 }
3834
3835 if (dest->getImmutableFormat())
3836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(InvalidOperation() << "Destination cannot be immutable.");
Geoff Lang47110bf2016-04-20 11:13:22 -07003838 return false;
3839 }
3840
3841 return true;
3842}
3843
Martin Radev4c4c8e72016-08-04 12:25:34 +03003844bool ValidateCreateShader(Context *context, GLenum type)
3845{
3846 switch (type)
3847 {
3848 case GL_VERTEX_SHADER:
3849 case GL_FRAGMENT_SHADER:
3850 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003851
Martin Radev4c4c8e72016-08-04 12:25:34 +03003852 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003853 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidEnum() << "GL_COMPUTE_SHADER requires OpenGL ES 3.1.");
Geoff Langeb66a6e2016-10-31 13:06:12 -04003856 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003857 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003858 break;
3859
Martin Radev4c4c8e72016-08-04 12:25:34 +03003860 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003861 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Martin Radev4c4c8e72016-08-04 12:25:34 +03003862 return false;
3863 }
Jamie Madill29639852016-09-02 15:00:09 -04003864
3865 return true;
3866}
3867
3868bool ValidateBufferData(ValidationContext *context,
3869 GLenum target,
3870 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003871 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003872 GLenum usage)
3873{
3874 if (size < 0)
3875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003876 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madill29639852016-09-02 15:00:09 -04003877 return false;
3878 }
3879
3880 switch (usage)
3881 {
3882 case GL_STREAM_DRAW:
3883 case GL_STATIC_DRAW:
3884 case GL_DYNAMIC_DRAW:
3885 break;
3886
3887 case GL_STREAM_READ:
3888 case GL_STREAM_COPY:
3889 case GL_STATIC_READ:
3890 case GL_STATIC_COPY:
3891 case GL_DYNAMIC_READ:
3892 case GL_DYNAMIC_COPY:
3893 if (context->getClientMajorVersion() < 3)
3894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04003896 return false;
3897 }
3898 break;
3899
3900 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003901 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
Jamie Madill29639852016-09-02 15:00:09 -04003902 return false;
3903 }
3904
3905 if (!ValidBufferTarget(context, target))
3906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04003908 return false;
3909 }
3910
3911 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3912
3913 if (!buffer)
3914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04003916 return false;
3917 }
3918
3919 return true;
3920}
3921
3922bool ValidateBufferSubData(ValidationContext *context,
3923 GLenum target,
3924 GLintptr offset,
3925 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003926 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003927{
Brandon Jones6cad5662017-06-14 13:25:13 -07003928 if (size < 0)
Jamie Madill29639852016-09-02 15:00:09 -04003929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003930 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
3931 return false;
3932 }
3933
3934 if (offset < 0)
3935 {
3936 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Jamie Madill29639852016-09-02 15:00:09 -04003937 return false;
3938 }
3939
3940 if (!ValidBufferTarget(context, target))
3941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill29639852016-09-02 15:00:09 -04003943 return false;
3944 }
3945
3946 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3947
3948 if (!buffer)
3949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003950 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madill29639852016-09-02 15:00:09 -04003951 return false;
3952 }
3953
3954 if (buffer->isMapped())
3955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003956 context->handleError(InvalidOperation());
Jamie Madill29639852016-09-02 15:00:09 -04003957 return false;
3958 }
3959
3960 // Check for possible overflow of size + offset
3961 angle::CheckedNumeric<size_t> checkedSize(size);
3962 checkedSize += offset;
3963 if (!checkedSize.IsValid())
3964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003965 context->handleError(OutOfMemory());
Jamie Madill29639852016-09-02 15:00:09 -04003966 return false;
3967 }
3968
3969 if (size + offset > buffer->getSize())
3970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003971 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Jamie Madill29639852016-09-02 15:00:09 -04003972 return false;
3973 }
3974
Martin Radev4c4c8e72016-08-04 12:25:34 +03003975 return true;
3976}
3977
Geoff Langc339c4e2016-11-29 10:37:36 -05003978bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003979{
Geoff Langc339c4e2016-11-29 10:37:36 -05003980 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003982 context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
Geoff Langc287ea62016-09-16 14:46:51 -04003983 return false;
3984 }
3985
3986 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3987 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003988 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003990 context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
Geoff Langc287ea62016-09-16 14:46:51 -04003991 return false;
3992 }
3993
3994 return true;
3995}
3996
Jamie Madillef300b12016-10-07 15:12:09 -04003997bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3998{
3999 if (texture < GL_TEXTURE0 ||
4000 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
4001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004002 context->handleError(InvalidEnum());
Jamie Madillef300b12016-10-07 15:12:09 -04004003 return false;
4004 }
4005
4006 return true;
4007}
4008
4009bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
4010{
4011 Program *programObject = GetValidProgram(context, program);
4012 if (!programObject)
4013 {
4014 return false;
4015 }
4016
4017 Shader *shaderObject = GetValidShader(context, shader);
4018 if (!shaderObject)
4019 {
4020 return false;
4021 }
4022
4023 switch (shaderObject->getType())
4024 {
4025 case GL_VERTEX_SHADER:
4026 {
4027 if (programObject->getAttachedVertexShader())
4028 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004029 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004030 return false;
4031 }
4032 break;
4033 }
4034 case GL_FRAGMENT_SHADER:
4035 {
4036 if (programObject->getAttachedFragmentShader())
4037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004039 return false;
4040 }
4041 break;
4042 }
4043 case GL_COMPUTE_SHADER:
4044 {
4045 if (programObject->getAttachedComputeShader())
4046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004047 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
Jamie Madillef300b12016-10-07 15:12:09 -04004048 return false;
4049 }
4050 break;
4051 }
4052 default:
4053 UNREACHABLE();
4054 break;
4055 }
4056
4057 return true;
4058}
4059
Jamie Madill01a80ee2016-11-07 12:06:18 -05004060bool ValidateBindAttribLocation(ValidationContext *context,
4061 GLuint program,
4062 GLuint index,
4063 const GLchar *name)
4064{
4065 if (index >= MAX_VERTEX_ATTRIBS)
4066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004067 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004068 return false;
4069 }
4070
4071 if (strncmp(name, "gl_", 3) == 0)
4072 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004074 return false;
4075 }
4076
Geoff Langfc32e8b2017-05-31 14:16:59 -04004077 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4078 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004079 if (context->getExtensions().webglCompatibility &&
4080 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004082 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004083 return false;
4084 }
4085
Jamie Madill01a80ee2016-11-07 12:06:18 -05004086 return GetValidProgram(context, program) != nullptr;
4087}
4088
4089bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
4090{
4091 if (!ValidBufferTarget(context, target))
4092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004094 return false;
4095 }
4096
4097 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4098 !context->isBufferGenerated(buffer))
4099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004101 return false;
4102 }
4103
4104 return true;
4105}
4106
4107bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
4108{
4109 if (!ValidFramebufferTarget(target))
4110 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004112 return false;
4113 }
4114
4115 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4116 !context->isFramebufferGenerated(framebuffer))
4117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004119 return false;
4120 }
4121
4122 return true;
4123}
4124
4125bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
4126{
4127 if (target != GL_RENDERBUFFER)
4128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004130 return false;
4131 }
4132
4133 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
4134 !context->isRenderbufferGenerated(renderbuffer))
4135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
Jamie Madill01a80ee2016-11-07 12:06:18 -05004137 return false;
4138 }
4139
4140 return true;
4141}
4142
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004143static bool ValidBlendEquationMode(GLenum mode)
4144{
4145 switch (mode)
4146 {
4147 case GL_FUNC_ADD:
4148 case GL_FUNC_SUBTRACT:
4149 case GL_FUNC_REVERSE_SUBTRACT:
4150 case GL_MIN:
4151 case GL_MAX:
4152 return true;
4153
4154 default:
4155 return false;
4156 }
4157}
4158
Jamie Madillc1d770e2017-04-13 17:31:24 -04004159bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004160 GLfloat red,
4161 GLfloat green,
4162 GLfloat blue,
4163 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004164{
4165 return true;
4166}
4167
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004168bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
4169{
4170 if (!ValidBlendEquationMode(mode))
4171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004173 return false;
4174 }
4175
4176 return true;
4177}
4178
4179bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
4180{
4181 if (!ValidBlendEquationMode(modeRGB))
4182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004184 return false;
4185 }
4186
4187 if (!ValidBlendEquationMode(modeAlpha))
4188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004190 return false;
4191 }
4192
4193 return true;
4194}
4195
4196bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
4197{
4198 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
4199}
4200
4201static bool ValidSrcBlendFunc(GLenum srcBlend)
4202{
4203 switch (srcBlend)
4204 {
4205 case GL_ZERO:
4206 case GL_ONE:
4207 case GL_SRC_COLOR:
4208 case GL_ONE_MINUS_SRC_COLOR:
4209 case GL_DST_COLOR:
4210 case GL_ONE_MINUS_DST_COLOR:
4211 case GL_SRC_ALPHA:
4212 case GL_ONE_MINUS_SRC_ALPHA:
4213 case GL_DST_ALPHA:
4214 case GL_ONE_MINUS_DST_ALPHA:
4215 case GL_CONSTANT_COLOR:
4216 case GL_ONE_MINUS_CONSTANT_COLOR:
4217 case GL_CONSTANT_ALPHA:
4218 case GL_ONE_MINUS_CONSTANT_ALPHA:
4219 case GL_SRC_ALPHA_SATURATE:
4220 return true;
4221
4222 default:
4223 return false;
4224 }
4225}
4226
4227static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4228{
4229 switch (dstBlend)
4230 {
4231 case GL_ZERO:
4232 case GL_ONE:
4233 case GL_SRC_COLOR:
4234 case GL_ONE_MINUS_SRC_COLOR:
4235 case GL_DST_COLOR:
4236 case GL_ONE_MINUS_DST_COLOR:
4237 case GL_SRC_ALPHA:
4238 case GL_ONE_MINUS_SRC_ALPHA:
4239 case GL_DST_ALPHA:
4240 case GL_ONE_MINUS_DST_ALPHA:
4241 case GL_CONSTANT_COLOR:
4242 case GL_ONE_MINUS_CONSTANT_COLOR:
4243 case GL_CONSTANT_ALPHA:
4244 case GL_ONE_MINUS_CONSTANT_ALPHA:
4245 return true;
4246
4247 case GL_SRC_ALPHA_SATURATE:
4248 return (contextMajorVersion >= 3);
4249
4250 default:
4251 return false;
4252 }
4253}
4254
4255bool ValidateBlendFuncSeparate(ValidationContext *context,
4256 GLenum srcRGB,
4257 GLenum dstRGB,
4258 GLenum srcAlpha,
4259 GLenum dstAlpha)
4260{
4261 if (!ValidSrcBlendFunc(srcRGB))
4262 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004263 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004264 return false;
4265 }
4266
4267 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004270 return false;
4271 }
4272
4273 if (!ValidSrcBlendFunc(srcAlpha))
4274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004276 return false;
4277 }
4278
4279 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004282 return false;
4283 }
4284
Frank Henigman146e8a12017-03-02 23:22:37 -05004285 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4286 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004287 {
4288 bool constantColorUsed =
4289 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4290 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4291
4292 bool constantAlphaUsed =
4293 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4294 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4295
4296 if (constantColorUsed && constantAlphaUsed)
4297 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004298 const char *msg;
4299 if (context->getExtensions().webglCompatibility)
4300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004301 msg = kErrorInvalidConstantColor;
Frank Henigman146e8a12017-03-02 23:22:37 -05004302 }
4303 else
4304 {
4305 msg =
4306 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4307 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4308 "implementation.";
4309 ERR() << msg;
4310 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004311 context->handleError(InvalidOperation() << msg);
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004312 return false;
4313 }
4314 }
4315
4316 return true;
4317}
4318
Geoff Langc339c4e2016-11-29 10:37:36 -05004319bool ValidateGetString(Context *context, GLenum name)
4320{
4321 switch (name)
4322 {
4323 case GL_VENDOR:
4324 case GL_RENDERER:
4325 case GL_VERSION:
4326 case GL_SHADING_LANGUAGE_VERSION:
4327 case GL_EXTENSIONS:
4328 break;
4329
4330 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4331 if (!context->getExtensions().requestExtension)
4332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004333 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004334 return false;
4335 }
4336 break;
4337
4338 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004339 context->handleError(InvalidEnum() << "Invalid name.");
Geoff Langc339c4e2016-11-29 10:37:36 -05004340 return false;
4341 }
4342
4343 return true;
4344}
4345
Geoff Lang47c48082016-12-07 15:38:13 -05004346bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4347{
4348 if (width <= 0.0f || isNaN(width))
4349 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004350 context->handleError(InvalidValue() << "Invalid width value.");
Geoff Lang47c48082016-12-07 15:38:13 -05004351 return false;
4352 }
4353
4354 return true;
4355}
4356
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004357bool ValidateVertexAttribPointer(ValidationContext *context,
4358 GLuint index,
4359 GLint size,
4360 GLenum type,
4361 GLboolean normalized,
4362 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004363 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004364{
Shao80957d92017-02-20 21:25:59 +08004365 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004366 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004367 return false;
4368 }
4369
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004370 if (stride < 0)
4371 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004372 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004373 return false;
4374 }
4375
Shao80957d92017-02-20 21:25:59 +08004376 const Caps &caps = context->getCaps();
4377 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004378 {
Shao80957d92017-02-20 21:25:59 +08004379 if (stride > caps.maxVertexAttribStride)
4380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004381 context->handleError(InvalidValue()
4382 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08004383 return false;
4384 }
4385
4386 if (index >= caps.maxVertexAttribBindings)
4387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004388 context->handleError(InvalidValue()
4389 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08004390 return false;
4391 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004392 }
4393
4394 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4395 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4396 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4397 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004398 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4399 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004400 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004402 context
4403 ->handleError(InvalidOperation()
4404 << "Client data cannot be used with a non-default vertex array object.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004405 return false;
4406 }
4407
4408 if (context->getExtensions().webglCompatibility)
4409 {
4410 // WebGL 1.0 [Section 6.14] Fixed point support
4411 // The WebGL API does not support the GL_FIXED data type.
4412 if (type == GL_FIXED)
4413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004414 context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004415 return false;
4416 }
4417
Geoff Lang2d62ab72017-03-23 16:54:40 -04004418 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004419 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004420 return false;
4421 }
4422 }
4423
4424 return true;
4425}
4426
Jamie Madill876429b2017-04-20 15:46:24 -04004427bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004428{
4429 if (context->getExtensions().webglCompatibility && zNear > zFar)
4430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
Frank Henigman6137ddc2017-02-10 18:55:07 -05004432 return false;
4433 }
4434
4435 return true;
4436}
4437
Jamie Madille8fb6402017-02-14 17:56:40 -05004438bool ValidateRenderbufferStorage(ValidationContext *context,
4439 GLenum target,
4440 GLenum internalformat,
4441 GLsizei width,
4442 GLsizei height)
4443{
4444 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4445 height);
4446}
4447
4448bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4449 GLenum target,
4450 GLsizei samples,
4451 GLenum internalformat,
4452 GLsizei width,
4453 GLsizei height)
4454{
4455 if (!context->getExtensions().framebufferMultisample)
4456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004457 context->handleError(InvalidOperation()
4458 << "GL_ANGLE_framebuffer_multisample not available");
Jamie Madille8fb6402017-02-14 17:56:40 -05004459 return false;
4460 }
4461
4462 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4463 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4464 // generated.
4465 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004467 context->handleError(InvalidValue());
Jamie Madille8fb6402017-02-14 17:56:40 -05004468 return false;
4469 }
4470
4471 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4472 // the specified storage. This is different than ES 3.0 in which a sample number higher
4473 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4474 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4475 if (context->getClientMajorVersion() >= 3)
4476 {
4477 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4478 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004480 context->handleError(OutOfMemory());
Jamie Madille8fb6402017-02-14 17:56:40 -05004481 return false;
4482 }
4483 }
4484
4485 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4486 width, height);
4487}
4488
Jamie Madillc1d770e2017-04-13 17:31:24 -04004489bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4490{
4491 if (!ValidFramebufferTarget(target))
4492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004494 return false;
4495 }
4496
4497 return true;
4498}
4499
4500bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004501 GLfloat red,
4502 GLfloat green,
4503 GLfloat blue,
4504 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004505{
4506 return true;
4507}
4508
Jamie Madill876429b2017-04-20 15:46:24 -04004509bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004510{
4511 return true;
4512}
4513
4514bool ValidateClearStencil(ValidationContext *context, GLint s)
4515{
4516 return true;
4517}
4518
4519bool ValidateColorMask(ValidationContext *context,
4520 GLboolean red,
4521 GLboolean green,
4522 GLboolean blue,
4523 GLboolean alpha)
4524{
4525 return true;
4526}
4527
4528bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4529{
4530 return true;
4531}
4532
4533bool ValidateCreateProgram(ValidationContext *context)
4534{
4535 return true;
4536}
4537
4538bool ValidateCullFace(ValidationContext *context, GLenum mode)
4539{
4540 switch (mode)
4541 {
4542 case GL_FRONT:
4543 case GL_BACK:
4544 case GL_FRONT_AND_BACK:
4545 break;
4546
4547 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004549 return false;
4550 }
4551
4552 return true;
4553}
4554
4555bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4556{
4557 if (program == 0)
4558 {
4559 return false;
4560 }
4561
4562 if (!context->getProgram(program))
4563 {
4564 if (context->getShader(program))
4565 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004567 return false;
4568 }
4569 else
4570 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004571 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004572 return false;
4573 }
4574 }
4575
4576 return true;
4577}
4578
4579bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4580{
4581 if (shader == 0)
4582 {
4583 return false;
4584 }
4585
4586 if (!context->getShader(shader))
4587 {
4588 if (context->getProgram(shader))
4589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004591 return false;
4592 }
4593 else
4594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004595 ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004596 return false;
4597 }
4598 }
4599
4600 return true;
4601}
4602
4603bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4604{
4605 switch (func)
4606 {
4607 case GL_NEVER:
4608 case GL_ALWAYS:
4609 case GL_LESS:
4610 case GL_LEQUAL:
4611 case GL_EQUAL:
4612 case GL_GREATER:
4613 case GL_GEQUAL:
4614 case GL_NOTEQUAL:
4615 break;
4616
4617 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004618 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004619 return false;
4620 }
4621
4622 return true;
4623}
4624
4625bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4626{
4627 return true;
4628}
4629
4630bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4631{
4632 Program *programObject = GetValidProgram(context, program);
4633 if (!programObject)
4634 {
4635 return false;
4636 }
4637
4638 Shader *shaderObject = GetValidShader(context, shader);
4639 if (!shaderObject)
4640 {
4641 return false;
4642 }
4643
4644 const Shader *attachedShader = nullptr;
4645
4646 switch (shaderObject->getType())
4647 {
4648 case GL_VERTEX_SHADER:
4649 {
4650 attachedShader = programObject->getAttachedVertexShader();
4651 break;
4652 }
4653 case GL_FRAGMENT_SHADER:
4654 {
4655 attachedShader = programObject->getAttachedFragmentShader();
4656 break;
4657 }
4658 case GL_COMPUTE_SHADER:
4659 {
4660 attachedShader = programObject->getAttachedComputeShader();
4661 break;
4662 }
4663 default:
4664 UNREACHABLE();
4665 return false;
4666 }
4667
4668 if (attachedShader != shaderObject)
4669 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004671 return false;
4672 }
4673
4674 return true;
4675}
4676
4677bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4678{
4679 if (index >= MAX_VERTEX_ATTRIBS)
4680 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004681 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004682 return false;
4683 }
4684
4685 return true;
4686}
4687
4688bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4689{
4690 if (index >= MAX_VERTEX_ATTRIBS)
4691 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004692 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004693 return false;
4694 }
4695
4696 return true;
4697}
4698
4699bool ValidateFinish(ValidationContext *context)
4700{
4701 return true;
4702}
4703
4704bool ValidateFlush(ValidationContext *context)
4705{
4706 return true;
4707}
4708
4709bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4710{
4711 switch (mode)
4712 {
4713 case GL_CW:
4714 case GL_CCW:
4715 break;
4716 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004718 return false;
4719 }
4720
4721 return true;
4722}
4723
4724bool ValidateGetActiveAttrib(ValidationContext *context,
4725 GLuint program,
4726 GLuint index,
4727 GLsizei bufsize,
4728 GLsizei *length,
4729 GLint *size,
4730 GLenum *type,
4731 GLchar *name)
4732{
4733 if (bufsize < 0)
4734 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004735 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004736 return false;
4737 }
4738
4739 Program *programObject = GetValidProgram(context, program);
4740
4741 if (!programObject)
4742 {
4743 return false;
4744 }
4745
4746 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004748 context->handleError(InvalidValue() << "index exeeds program active attribute count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004749 return false;
4750 }
4751
4752 return true;
4753}
4754
4755bool ValidateGetActiveUniform(ValidationContext *context,
4756 GLuint program,
4757 GLuint index,
4758 GLsizei bufsize,
4759 GLsizei *length,
4760 GLint *size,
4761 GLenum *type,
4762 GLchar *name)
4763{
4764 if (bufsize < 0)
4765 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004766 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004767 return false;
4768 }
4769
4770 Program *programObject = GetValidProgram(context, program);
4771
4772 if (!programObject)
4773 {
4774 return false;
4775 }
4776
4777 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004779 context->handleError(InvalidValue() << "index exceeds program active uniform count.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004780 return false;
4781 }
4782
4783 return true;
4784}
4785
4786bool ValidateGetAttachedShaders(ValidationContext *context,
4787 GLuint program,
4788 GLsizei maxcount,
4789 GLsizei *count,
4790 GLuint *shaders)
4791{
4792 if (maxcount < 0)
4793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004794 context->handleError(InvalidValue() << "max count must be non-negative.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004795 return false;
4796 }
4797
4798 Program *programObject = GetValidProgram(context, program);
4799
4800 if (!programObject)
4801 {
4802 return false;
4803 }
4804
4805 return true;
4806}
4807
4808bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4809{
Geoff Langfc32e8b2017-05-31 14:16:59 -04004810 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4811 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004812 if (context->getExtensions().webglCompatibility &&
4813 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004814 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004815 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004816 return false;
4817 }
4818
Jamie Madillc1d770e2017-04-13 17:31:24 -04004819 Program *programObject = GetValidProgram(context, program);
4820
4821 if (!programObject)
4822 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004823 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004824 return false;
4825 }
4826
4827 if (!programObject->isLinked())
4828 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004829 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004830 return false;
4831 }
4832
4833 return true;
4834}
4835
4836bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4837{
4838 GLenum nativeType;
4839 unsigned int numParams = 0;
4840 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4841}
4842
4843bool ValidateGetError(ValidationContext *context)
4844{
4845 return true;
4846}
4847
4848bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4849{
4850 GLenum nativeType;
4851 unsigned int numParams = 0;
4852 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4853}
4854
4855bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4856{
4857 GLenum nativeType;
4858 unsigned int numParams = 0;
4859 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4860}
4861
4862bool ValidateGetProgramInfoLog(ValidationContext *context,
4863 GLuint program,
4864 GLsizei bufsize,
4865 GLsizei *length,
4866 GLchar *infolog)
4867{
4868 if (bufsize < 0)
4869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004870 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004871 return false;
4872 }
4873
4874 Program *programObject = GetValidProgram(context, program);
4875 if (!programObject)
4876 {
4877 return false;
4878 }
4879
4880 return true;
4881}
4882
4883bool ValidateGetShaderInfoLog(ValidationContext *context,
4884 GLuint shader,
4885 GLsizei bufsize,
4886 GLsizei *length,
4887 GLchar *infolog)
4888{
4889 if (bufsize < 0)
4890 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004891 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004892 return false;
4893 }
4894
4895 Shader *shaderObject = GetValidShader(context, shader);
4896 if (!shaderObject)
4897 {
4898 return false;
4899 }
4900
4901 return true;
4902}
4903
4904bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4905 GLenum shadertype,
4906 GLenum precisiontype,
4907 GLint *range,
4908 GLint *precision)
4909{
4910 switch (shadertype)
4911 {
4912 case GL_VERTEX_SHADER:
4913 case GL_FRAGMENT_SHADER:
4914 break;
4915 case GL_COMPUTE_SHADER:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004916 context->handleError(InvalidOperation()
4917 << "compute shader precision not yet implemented.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04004918 return false;
4919 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004920 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004921 return false;
4922 }
4923
4924 switch (precisiontype)
4925 {
4926 case GL_LOW_FLOAT:
4927 case GL_MEDIUM_FLOAT:
4928 case GL_HIGH_FLOAT:
4929 case GL_LOW_INT:
4930 case GL_MEDIUM_INT:
4931 case GL_HIGH_INT:
4932 break;
4933
4934 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004935 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004936 return false;
4937 }
4938
4939 return true;
4940}
4941
4942bool ValidateGetShaderSource(ValidationContext *context,
4943 GLuint shader,
4944 GLsizei bufsize,
4945 GLsizei *length,
4946 GLchar *source)
4947{
4948 if (bufsize < 0)
4949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004950 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004951 return false;
4952 }
4953
4954 Shader *shaderObject = GetValidShader(context, shader);
4955 if (!shaderObject)
4956 {
4957 return false;
4958 }
4959
4960 return true;
4961}
4962
4963bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4964{
4965 if (strstr(name, "gl_") == name)
4966 {
4967 return false;
4968 }
4969
Geoff Langfc32e8b2017-05-31 14:16:59 -04004970 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4971 // shader-related entry points
Geoff Langa71a98e2017-06-19 15:15:00 -04004972 if (context->getExtensions().webglCompatibility &&
4973 !IsValidESSLString(name, strlen(name), false))
Geoff Langfc32e8b2017-05-31 14:16:59 -04004974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004975 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04004976 return false;
4977 }
4978
Jamie Madillc1d770e2017-04-13 17:31:24 -04004979 Program *programObject = GetValidProgram(context, program);
4980
4981 if (!programObject)
4982 {
4983 return false;
4984 }
4985
4986 if (!programObject->isLinked())
4987 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004988 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillc1d770e2017-04-13 17:31:24 -04004989 return false;
4990 }
4991
4992 return true;
4993}
4994
4995bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4996{
4997 switch (mode)
4998 {
4999 case GL_FASTEST:
5000 case GL_NICEST:
5001 case GL_DONT_CARE:
5002 break;
5003
5004 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005006 return false;
5007 }
5008
5009 switch (target)
5010 {
5011 case GL_GENERATE_MIPMAP_HINT:
5012 break;
5013
Geoff Lange7bd2182017-06-16 16:13:13 -04005014 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
5015 if (context->getClientVersion() < ES_3_0 &&
5016 !context->getExtensions().standardDerivatives)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005018 context->handleError(InvalidOperation()
5019 << "hint requires OES_standard_derivatives.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005020 return false;
5021 }
5022 break;
5023
5024 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005025 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005026 return false;
5027 }
5028
5029 return true;
5030}
5031
5032bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
5033{
5034 return true;
5035}
5036
5037bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
5038{
5039 return true;
5040}
5041
5042bool ValidateIsProgram(ValidationContext *context, GLuint program)
5043{
5044 return true;
5045}
5046
5047bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
5048{
5049 return true;
5050}
5051
5052bool ValidateIsShader(ValidationContext *context, GLuint shader)
5053{
5054 return true;
5055}
5056
5057bool ValidateIsTexture(ValidationContext *context, GLuint texture)
5058{
5059 return true;
5060}
5061
5062bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
5063{
5064 if (context->getClientMajorVersion() < 3)
5065 {
5066 switch (pname)
5067 {
5068 case GL_UNPACK_IMAGE_HEIGHT:
5069 case GL_UNPACK_SKIP_IMAGES:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005070 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005071 return false;
5072
5073 case GL_UNPACK_ROW_LENGTH:
5074 case GL_UNPACK_SKIP_ROWS:
5075 case GL_UNPACK_SKIP_PIXELS:
5076 if (!context->getExtensions().unpackSubimage)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005079 return false;
5080 }
5081 break;
5082
5083 case GL_PACK_ROW_LENGTH:
5084 case GL_PACK_SKIP_ROWS:
5085 case GL_PACK_SKIP_PIXELS:
5086 if (!context->getExtensions().packSubimage)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(InvalidEnum());
Jamie Madillc1d770e2017-04-13 17:31:24 -04005089 return false;
5090 }
5091 break;
5092 }
5093 }
5094
5095 if (param < 0)
5096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005097 context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005098 return false;
5099 }
5100
5101 switch (pname)
5102 {
5103 case GL_UNPACK_ALIGNMENT:
5104 if (param != 1 && param != 2 && param != 4 && param != 8)
5105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005106 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005107 return false;
5108 }
5109 break;
5110
5111 case GL_PACK_ALIGNMENT:
5112 if (param != 1 && param != 2 && param != 4 && param != 8)
5113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005114 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005115 return false;
5116 }
5117 break;
5118
5119 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5120 case GL_UNPACK_ROW_LENGTH:
5121 case GL_UNPACK_IMAGE_HEIGHT:
5122 case GL_UNPACK_SKIP_IMAGES:
5123 case GL_UNPACK_SKIP_ROWS:
5124 case GL_UNPACK_SKIP_PIXELS:
5125 case GL_PACK_ROW_LENGTH:
5126 case GL_PACK_SKIP_ROWS:
5127 case GL_PACK_SKIP_PIXELS:
5128 break;
5129
5130 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005132 return false;
5133 }
5134
5135 return true;
5136}
5137
5138bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
5139{
5140 return true;
5141}
5142
5143bool ValidateReleaseShaderCompiler(ValidationContext *context)
5144{
5145 return true;
5146}
5147
Jamie Madill876429b2017-04-20 15:46:24 -04005148bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04005149{
5150 return true;
5151}
5152
5153bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5154{
5155 if (width < 0 || height < 0)
5156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005158 return false;
5159 }
5160
5161 return true;
5162}
5163
5164bool ValidateShaderBinary(ValidationContext *context,
5165 GLsizei n,
5166 const GLuint *shaders,
5167 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04005168 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04005169 GLsizei length)
5170{
5171 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
5172 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
5173 shaderBinaryFormats.end())
5174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005175 context->handleError(InvalidEnum() << "Invalid shader binary format.");
Jamie Madillc1d770e2017-04-13 17:31:24 -04005176 return false;
5177 }
5178
5179 return true;
5180}
5181
5182bool ValidateShaderSource(ValidationContext *context,
5183 GLuint shader,
5184 GLsizei count,
5185 const GLchar *const *string,
5186 const GLint *length)
5187{
5188 if (count < 0)
5189 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005190 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005191 return false;
5192 }
5193
Geoff Langfc32e8b2017-05-31 14:16:59 -04005194 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
5195 // shader-related entry points
5196 if (context->getExtensions().webglCompatibility)
5197 {
5198 for (GLsizei i = 0; i < count; i++)
5199 {
5200 size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
Geoff Langa71a98e2017-06-19 15:15:00 -04005201
5202 // Backslash as line-continuation is allowed in WebGL 2.0.
5203 if (!IsValidESSLString(string[i], len, context->getClientVersion() >= ES_3_0))
Geoff Langfc32e8b2017-05-31 14:16:59 -04005204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005205 ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
Geoff Langfc32e8b2017-05-31 14:16:59 -04005206 return false;
5207 }
5208 }
5209 }
5210
Jamie Madillc1d770e2017-04-13 17:31:24 -04005211 Shader *shaderObject = GetValidShader(context, shader);
5212 if (!shaderObject)
5213 {
5214 return false;
5215 }
5216
5217 return true;
5218}
5219
5220bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
5221{
5222 if (!IsValidStencilFunc(func))
5223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005225 return false;
5226 }
5227
5228 return true;
5229}
5230
5231bool ValidateStencilFuncSeparate(ValidationContext *context,
5232 GLenum face,
5233 GLenum func,
5234 GLint ref,
5235 GLuint mask)
5236{
5237 if (!IsValidStencilFace(face))
5238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005240 return false;
5241 }
5242
5243 if (!IsValidStencilFunc(func))
5244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005246 return false;
5247 }
5248
5249 return true;
5250}
5251
5252bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5253{
5254 return true;
5255}
5256
5257bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5258{
5259 if (!IsValidStencilFace(face))
5260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005262 return false;
5263 }
5264
5265 return true;
5266}
5267
5268bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5269{
5270 if (!IsValidStencilOp(fail))
5271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005273 return false;
5274 }
5275
5276 if (!IsValidStencilOp(zfail))
5277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005279 return false;
5280 }
5281
5282 if (!IsValidStencilOp(zpass))
5283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005284 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005285 return false;
5286 }
5287
5288 return true;
5289}
5290
5291bool ValidateStencilOpSeparate(ValidationContext *context,
5292 GLenum face,
5293 GLenum fail,
5294 GLenum zfail,
5295 GLenum zpass)
5296{
5297 if (!IsValidStencilFace(face))
5298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005300 return false;
5301 }
5302
5303 return ValidateStencilOp(context, fail, zfail, zpass);
5304}
5305
5306bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5307{
5308 return ValidateUniform(context, GL_FLOAT, location, 1);
5309}
5310
5311bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5312{
5313 return ValidateUniform(context, GL_FLOAT, location, count);
5314}
5315
Jamie Madillbe849e42017-05-02 15:49:00 -04005316bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5317{
5318 return ValidateUniform1iv(context, location, 1, &x);
5319}
5320
Jamie Madillc1d770e2017-04-13 17:31:24 -04005321bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5322{
5323 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5324}
5325
5326bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5327{
5328 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5329}
5330
5331bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5332{
5333 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5334}
5335
5336bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5337{
5338 return ValidateUniform(context, GL_INT_VEC2, location, count);
5339}
5340
5341bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5342{
5343 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5344}
5345
5346bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5347{
5348 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5349}
5350
5351bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5352{
5353 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5354}
5355
5356bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5357{
5358 return ValidateUniform(context, GL_INT_VEC3, location, count);
5359}
5360
5361bool ValidateUniform4f(ValidationContext *context,
5362 GLint location,
5363 GLfloat x,
5364 GLfloat y,
5365 GLfloat z,
5366 GLfloat w)
5367{
5368 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5369}
5370
5371bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5372{
5373 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5374}
5375
5376bool ValidateUniform4i(ValidationContext *context,
5377 GLint location,
5378 GLint x,
5379 GLint y,
5380 GLint z,
5381 GLint w)
5382{
5383 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5384}
5385
5386bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5387{
5388 return ValidateUniform(context, GL_INT_VEC4, location, count);
5389}
5390
5391bool ValidateUniformMatrix2fv(ValidationContext *context,
5392 GLint location,
5393 GLsizei count,
5394 GLboolean transpose,
5395 const GLfloat *value)
5396{
5397 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5398}
5399
5400bool ValidateUniformMatrix3fv(ValidationContext *context,
5401 GLint location,
5402 GLsizei count,
5403 GLboolean transpose,
5404 const GLfloat *value)
5405{
5406 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5407}
5408
5409bool ValidateUniformMatrix4fv(ValidationContext *context,
5410 GLint location,
5411 GLsizei count,
5412 GLboolean transpose,
5413 const GLfloat *value)
5414{
5415 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5416}
5417
5418bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5419{
5420 Program *programObject = GetValidProgram(context, program);
5421
5422 if (!programObject)
5423 {
5424 return false;
5425 }
5426
5427 return true;
5428}
5429
5430bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5431{
5432 if (index >= MAX_VERTEX_ATTRIBS)
5433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005434 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005435 return false;
5436 }
5437
5438 return true;
5439}
5440
5441bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5442{
5443 return ValidateVertexAttribIndex(context, index);
5444}
5445
5446bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5447{
5448 return ValidateVertexAttribIndex(context, index);
5449}
5450
5451bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5452{
5453 return ValidateVertexAttribIndex(context, index);
5454}
5455
5456bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5457{
5458 return ValidateVertexAttribIndex(context, index);
5459}
5460
5461bool ValidateVertexAttrib3f(ValidationContext *context,
5462 GLuint index,
5463 GLfloat x,
5464 GLfloat y,
5465 GLfloat z)
5466{
5467 return ValidateVertexAttribIndex(context, index);
5468}
5469
5470bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5471{
5472 return ValidateVertexAttribIndex(context, index);
5473}
5474
5475bool ValidateVertexAttrib4f(ValidationContext *context,
5476 GLuint index,
5477 GLfloat x,
5478 GLfloat y,
5479 GLfloat z,
5480 GLfloat w)
5481{
5482 return ValidateVertexAttribIndex(context, index);
5483}
5484
5485bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5486{
5487 return ValidateVertexAttribIndex(context, index);
5488}
5489
5490bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5491{
5492 if (width < 0 || height < 0)
5493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005494 ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
Jamie Madillc1d770e2017-04-13 17:31:24 -04005495 return false;
5496 }
5497
5498 return true;
5499}
5500
5501bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5502{
5503 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5504}
5505
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005506bool ValidateDrawElements(ValidationContext *context,
5507 GLenum mode,
5508 GLsizei count,
5509 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005510 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005511{
5512 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5513}
5514
Jamie Madillbe849e42017-05-02 15:49:00 -04005515bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5516 GLenum target,
5517 GLenum attachment,
5518 GLenum pname,
5519 GLint *params)
5520{
5521 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5522 nullptr);
5523}
5524
5525bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5526{
5527 return ValidateGetProgramivBase(context, program, pname, nullptr);
5528}
5529
5530bool ValidateCopyTexImage2D(ValidationContext *context,
5531 GLenum target,
5532 GLint level,
5533 GLenum internalformat,
5534 GLint x,
5535 GLint y,
5536 GLsizei width,
5537 GLsizei height,
5538 GLint border)
5539{
5540 if (context->getClientMajorVersion() < 3)
5541 {
5542 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5543 0, x, y, width, height, border);
5544 }
5545
5546 ASSERT(context->getClientMajorVersion() == 3);
5547 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5548 0, x, y, width, height, border);
5549}
5550
5551bool ValidateCopyTexSubImage2D(Context *context,
5552 GLenum target,
5553 GLint level,
5554 GLint xoffset,
5555 GLint yoffset,
5556 GLint x,
5557 GLint y,
5558 GLsizei width,
5559 GLsizei height)
5560{
5561 if (context->getClientMajorVersion() < 3)
5562 {
5563 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5564 yoffset, x, y, width, height, 0);
5565 }
5566
5567 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5568 yoffset, 0, x, y, width, height, 0);
5569}
5570
5571bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5572{
5573 return ValidateGenOrDelete(context, n);
5574}
5575
5576bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5577{
5578 return ValidateGenOrDelete(context, n);
5579}
5580
5581bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5582{
5583 return ValidateGenOrDelete(context, n);
5584}
5585
5586bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5587{
5588 return ValidateGenOrDelete(context, n);
5589}
5590
5591bool ValidateDisable(Context *context, GLenum cap)
5592{
5593 if (!ValidCap(context, cap, false))
5594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 return false;
5597 }
5598
5599 return true;
5600}
5601
5602bool ValidateEnable(Context *context, GLenum cap)
5603{
5604 if (!ValidCap(context, cap, false))
5605 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005606 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 return false;
5608 }
5609
5610 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5611 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5612 {
5613 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005614 context->handleError(InvalidOperation() << errorMessage);
Jamie Madillbe849e42017-05-02 15:49:00 -04005615
5616 // We also output an error message to the debugger window if tracing is active, so that
5617 // developers can see the error message.
5618 ERR() << errorMessage;
5619 return false;
5620 }
5621
5622 return true;
5623}
5624
5625bool ValidateFramebufferRenderbuffer(Context *context,
5626 GLenum target,
5627 GLenum attachment,
5628 GLenum renderbuffertarget,
5629 GLuint renderbuffer)
5630{
Brandon Jones6cad5662017-06-14 13:25:13 -07005631 if (!ValidFramebufferTarget(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005632 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
5634 return false;
5635 }
5636
5637 if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
5638 {
5639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005640 return false;
5641 }
5642
5643 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5644 renderbuffertarget, renderbuffer);
5645}
5646
5647bool ValidateFramebufferTexture2D(Context *context,
5648 GLenum target,
5649 GLenum attachment,
5650 GLenum textarget,
5651 GLuint texture,
5652 GLint level)
5653{
5654 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5655 // extension
5656 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5657 level != 0)
5658 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005659 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662
5663 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5664 {
5665 return false;
5666 }
5667
5668 if (texture != 0)
5669 {
5670 gl::Texture *tex = context->getTexture(texture);
5671 ASSERT(tex);
5672
5673 const gl::Caps &caps = context->getCaps();
5674
5675 switch (textarget)
5676 {
5677 case GL_TEXTURE_2D:
5678 {
5679 if (level > gl::log2(caps.max2DTextureSize))
5680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005681 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 return false;
5683 }
5684 if (tex->getTarget() != GL_TEXTURE_2D)
5685 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 return false;
5688 }
5689 }
5690 break;
5691
5692 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5693 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5694 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5695 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5696 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5697 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5698 {
5699 if (level > gl::log2(caps.maxCubeMapTextureSize))
5700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005701 context->handleError(InvalidValue());
Jamie Madillbe849e42017-05-02 15:49:00 -04005702 return false;
5703 }
5704 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005706 context->handleError(InvalidOperation()
5707 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 return false;
5709 }
5710 }
5711 break;
5712
5713 case GL_TEXTURE_2D_MULTISAMPLE:
5714 {
5715 if (context->getClientVersion() < ES_3_1)
5716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005717 context->handleError(InvalidOperation()
5718 << "Texture target requires at least OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005719 return false;
5720 }
5721
5722 if (level != 0)
5723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005724 context->handleError(InvalidValue()
5725 << "Level must be 0 for TEXTURE_2D_MULTISAMPLE.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005726 return false;
5727 }
5728 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005730 context->handleError(InvalidOperation()
5731 << "Textarget must match the texture target type.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005732 return false;
5733 }
5734 }
5735 break;
5736
5737 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005738 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005739 return false;
5740 }
5741
5742 const Format &format = tex->getFormat(textarget, level);
5743 if (format.info->compressed)
5744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005745 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 return false;
5747 }
5748 }
5749
5750 return true;
5751}
5752
5753bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5754{
5755 return ValidateGenOrDelete(context, n);
5756}
5757
5758bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5759{
5760 return ValidateGenOrDelete(context, n);
5761}
5762
5763bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5764{
5765 return ValidateGenOrDelete(context, n);
5766}
5767
5768bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5769{
5770 return ValidateGenOrDelete(context, n);
5771}
5772
5773bool ValidateGenerateMipmap(Context *context, GLenum target)
5774{
5775 if (!ValidTextureTarget(context, target))
5776 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005777 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 return false;
5779 }
5780
5781 Texture *texture = context->getTargetTexture(target);
5782
5783 if (texture == nullptr)
5784 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005785 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 return false;
5787 }
5788
5789 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5790
5791 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5792 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5793 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005795 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005796 return false;
5797 }
5798
5799 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5800 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5801 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5802
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 if (format.info->compressed)
5804 {
5805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
5806 return false;
5807 }
5808
Jamie Madillbe849e42017-05-02 15:49:00 -04005809 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
Brandon Jones6cad5662017-06-14 13:25:13 -07005810 // unsized formats or that are color renderable and filterable. Since we do not track if
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 // the texture was created with sized or unsized format (only sized formats are stored),
5812 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5813 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5814 // textures since they're the only texture format that can be created with unsized formats
5815 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5816 // was the last version to use add them.
5817 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
Brandon Jones6cad5662017-06-14 13:25:13 -07005818 (!formatCaps.renderable && !format.info->isLUMA()))
Jamie Madillbe849e42017-05-02 15:49:00 -04005819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005820 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
5823
Geoff Lang65ac5b92017-05-01 13:16:30 -04005824 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5825 bool supportsSRGBMipmapGeneration =
5826 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5827 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005829 context->handleError(InvalidOperation()
5830 << "Mipmap generation of sRGB textures is not allowed.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005831 return false;
5832 }
5833
5834 // Non-power of 2 ES2 check
5835 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5836 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5837 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5838 {
5839 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Brandon Jones6cad5662017-06-14 13:25:13 -07005840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
Jamie Madillbe849e42017-05-02 15:49:00 -04005841 return false;
5842 }
5843
5844 // Cube completeness check
5845 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 return false;
5849 }
5850
5851 return true;
5852}
5853
5854bool ValidateGetBufferParameteriv(ValidationContext *context,
5855 GLenum target,
5856 GLenum pname,
5857 GLint *params)
5858{
5859 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5860}
5861
5862bool ValidateGetRenderbufferParameteriv(Context *context,
5863 GLenum target,
5864 GLenum pname,
5865 GLint *params)
5866{
5867 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5868}
5869
5870bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5871{
5872 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5873}
5874
5875bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5876{
5877 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5878}
5879
5880bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5881{
5882 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5883}
5884
5885bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5886{
5887 return ValidateGetUniformBase(context, program, location);
5888}
5889
5890bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5891{
5892 return ValidateGetUniformBase(context, program, location);
5893}
5894
5895bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5896{
5897 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5898}
5899
5900bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5901{
5902 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5903}
5904
5905bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5906{
5907 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5908}
5909
5910bool ValidateIsEnabled(Context *context, GLenum cap)
5911{
5912 if (!ValidCap(context, cap, true))
5913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005915 return false;
5916 }
5917
5918 return true;
5919}
5920
5921bool ValidateLinkProgram(Context *context, GLuint program)
5922{
5923 if (context->hasActiveTransformFeedback(program))
5924 {
5925 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005926 context->handleError(InvalidOperation() << "Cannot link program while program is "
5927 "associated with an active transform "
5928 "feedback object.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 return false;
5930 }
5931
5932 Program *programObject = GetValidProgram(context, program);
5933 if (!programObject)
5934 {
5935 return false;
5936 }
5937
5938 return true;
5939}
5940
Jamie Madill4928b7c2017-06-20 12:57:39 -04005941bool ValidateReadPixels(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005942 GLint x,
5943 GLint y,
5944 GLsizei width,
5945 GLsizei height,
5946 GLenum format,
5947 GLenum type,
5948 void *pixels)
5949{
5950 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5951 nullptr, pixels);
5952}
5953
5954bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5955{
5956 return ValidateTexParameterBase(context, target, pname, -1, &param);
5957}
5958
5959bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5960{
5961 return ValidateTexParameterBase(context, target, pname, -1, params);
5962}
5963
5964bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5965{
5966 return ValidateTexParameterBase(context, target, pname, -1, &param);
5967}
5968
5969bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5970{
5971 return ValidateTexParameterBase(context, target, pname, -1, params);
5972}
5973
5974bool ValidateUseProgram(Context *context, GLuint program)
5975{
5976 if (program != 0)
5977 {
5978 Program *programObject = context->getProgram(program);
5979 if (!programObject)
5980 {
5981 // ES 3.1.0 section 7.3 page 72
5982 if (context->getShader(program))
5983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04005985 return false;
5986 }
5987 else
5988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005989 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 return false;
5991 }
5992 }
5993 if (!programObject->isLinked())
5994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Jamie Madillbe849e42017-05-02 15:49:00 -04005996 return false;
5997 }
5998 }
5999 if (context->getGLState().isTransformFeedbackActiveUnpaused())
6000 {
6001 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006002 context
6003 ->handleError(InvalidOperation()
6004 << "Cannot change active program while transform feedback is unpaused.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006005 return false;
6006 }
6007
6008 return true;
6009}
6010
Jamie Madillc29968b2016-01-20 11:17:23 -05006011} // namespace gl