blob: fb23caccc5a893663910f9cbb01757d02f11ec1b [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"
17#include "libANGLE/Texture.h"
18#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
22#include "libANGLE/Uniform.h"
23#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES.h"
25#include "libANGLE/validationES3.h"
Corentin Wallez0c7baf12016-12-19 15:43:10 -050026#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
78 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
79 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
95 context->handleError(
96 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
97 return false;
98 }
99
100 if (paths == nullptr)
101 {
102 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
103 return false;
104 }
105
106 if (numPaths < 0)
107 {
108 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
114 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
115 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:
160 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
161 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:
188 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
193 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
194 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 {
202 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang97073d12016-04-20 10:42:34 -0700209bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
210{
211 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
212 switch (internalFormatInfo.format)
213 {
214 case GL_ALPHA:
215 case GL_LUMINANCE:
216 case GL_LUMINANCE_ALPHA:
217 case GL_RGB:
218 case GL_RGBA:
219 return true;
220
221 case GL_RED:
222 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
223
224 case GL_BGRA_EXT:
225 return context->getExtensions().textureFormatBGRA8888;
226
227 default:
228 return false;
229 }
230}
231
232bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
233{
234 switch (internalFormat)
235 {
236 case GL_RGB:
237 case GL_RGBA:
238 break;
239
240 case GL_BGRA_EXT:
241 return context->getExtensions().textureFormatBGRA8888;
242
243 default:
244 return false;
245 }
246
247 switch (type)
248 {
249 case GL_UNSIGNED_BYTE:
250 break;
251
252 default:
253 return false;
254 }
255
256 return true;
257}
258
259bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
260{
261 switch (target)
262 {
263 case GL_TEXTURE_2D:
264 return true;
265
266 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
267 // supported
268
269 default:
270 return false;
271 }
272}
273
274bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
275{
276 if (IsValidCopyTextureDestinationTarget(context, target))
277 {
278 return true;
279 }
280
281 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
282 // supported
283
284 return false;
285}
286
Jamie Madillc1d770e2017-04-13 17:31:24 -0400287bool IsValidStencilFunc(GLenum func)
288{
289 switch (func)
290 {
291 case GL_NEVER:
292 case GL_ALWAYS:
293 case GL_LESS:
294 case GL_LEQUAL:
295 case GL_EQUAL:
296 case GL_GEQUAL:
297 case GL_GREATER:
298 case GL_NOTEQUAL:
299 return true;
300
301 default:
302 return false;
303 }
304}
305
306bool IsValidStencilFace(GLenum face)
307{
308 switch (face)
309 {
310 case GL_FRONT:
311 case GL_BACK:
312 case GL_FRONT_AND_BACK:
313 return true;
314
315 default:
316 return false;
317 }
318}
319
320bool IsValidStencilOp(GLenum op)
321{
322 switch (op)
323 {
324 case GL_ZERO:
325 case GL_KEEP:
326 case GL_REPLACE:
327 case GL_INCR:
328 case GL_DECR:
329 case GL_INVERT:
330 case GL_INCR_WRAP:
331 case GL_DECR_WRAP:
332 return true;
333
334 default:
335 return false;
336 }
337}
338
Jamie Madillc29968b2016-01-20 11:17:23 -0500339} // anonymous namespace
340
Geoff Langff5b2d52016-09-07 11:32:23 -0400341bool ValidateES2TexImageParameters(Context *context,
342 GLenum target,
343 GLint level,
344 GLenum internalformat,
345 bool isCompressed,
346 bool isSubImage,
347 GLint xoffset,
348 GLint yoffset,
349 GLsizei width,
350 GLsizei height,
351 GLint border,
352 GLenum format,
353 GLenum type,
354 GLsizei imageSize,
355 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356{
Jamie Madill6f38f822014-06-06 17:12:20 -0400357 if (!ValidTexture2DDestinationTarget(context, target))
358 {
Jamie Madill437fa652016-05-03 15:13:24 -0400359 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400360 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400361 }
362
Austin Kinross08528e12015-10-07 16:24:40 -0700363 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 {
Jamie Madill437fa652016-05-03 15:13:24 -0400365 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
368
He Yunchaoced53ae2016-11-29 15:00:51 +0800369 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370 std::numeric_limits<GLsizei>::max() - yoffset < height)
371 {
Jamie Madill437fa652016-05-03 15:13:24 -0400372 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400373 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400374 }
375
Geoff Lang005df412013-10-16 14:12:50 -0400376 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377 {
Jamie Madill437fa652016-05-03 15:13:24 -0400378 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400379 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400380 }
381
Geoff Langaae65a42014-05-26 12:43:44 -0400382 const gl::Caps &caps = context->getCaps();
383
Geoff Langa9be0dc2014-12-17 12:34:40 -0500384 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400385 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500386 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
387 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388 {
Jamie Madill437fa652016-05-03 15:13:24 -0400389 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500392 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500393 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500394 {
395 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 {
Jamie Madill437fa652016-05-03 15:13:24 -0400397 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400400
Geoff Langa9be0dc2014-12-17 12:34:40 -0500401 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
402 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
403 {
Jamie Madill437fa652016-05-03 15:13:24 -0400404 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500405 return false;
406 }
407 }
408 else
409 {
Jamie Madill437fa652016-05-03 15:13:24 -0400410 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400411 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400412 }
413
He Yunchaoced53ae2016-11-29 15:00:51 +0800414 gl::Texture *texture =
415 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416 if (!texture)
417 {
Jamie Madill437fa652016-05-03 15:13:24 -0400418 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400419 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400420 }
421
Geoff Langa9be0dc2014-12-17 12:34:40 -0500422 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 {
Geoff Langc51642b2016-11-14 16:18:26 -0500424 GLenum textureFormat = texture->getFormat(target, level).asSized();
425 if (textureFormat == GL_NONE)
426 {
427 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
428 return false;
429 }
430
Geoff Langa9be0dc2014-12-17 12:34:40 -0500431 if (format != GL_NONE)
432 {
Geoff Langc51642b2016-11-14 16:18:26 -0500433 if (gl::GetSizedInternalFormat(format, type) != textureFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500434 {
Jamie Madill437fa652016-05-03 15:13:24 -0400435 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500436 return false;
437 }
438 }
439
440 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
441 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
442 {
Jamie Madill437fa652016-05-03 15:13:24 -0400443 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500444 return false;
445 }
446 }
447 else
448 {
Geoff Lang69cce582015-09-17 13:20:36 -0400449 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500450 {
Jamie Madill437fa652016-05-03 15:13:24 -0400451 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500452 return false;
453 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400454 }
455
456 // Verify zero border
457 if (border != 0)
458 {
Jamie Madill437fa652016-05-03 15:13:24 -0400459 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400461 }
462
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400463 if (isCompressed)
464 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400465 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400466 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400467 switch (actualInternalFormat)
468 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800469 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
470 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
471 if (!context->getExtensions().textureCompressionDXT1)
472 {
473 context->handleError(Error(GL_INVALID_ENUM));
474 return false;
475 }
476 break;
477 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
478 if (!context->getExtensions().textureCompressionDXT1)
479 {
480 context->handleError(Error(GL_INVALID_ENUM));
481 return false;
482 }
483 break;
484 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
485 if (!context->getExtensions().textureCompressionDXT5)
486 {
487 context->handleError(Error(GL_INVALID_ENUM));
488 return false;
489 }
490 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800491 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
492 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
493 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
494 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
495 if (!context->getExtensions().textureCompressionS3TCsRGB)
496 {
497 context->handleError(Error(GL_INVALID_ENUM));
498 return false;
499 }
500 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800501 case GL_ETC1_RGB8_OES:
502 if (!context->getExtensions().compressedETC1RGB8Texture)
503 {
504 context->handleError(Error(GL_INVALID_ENUM));
505 return false;
506 }
507 break;
508 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800509 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
510 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
511 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
512 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800513 if (!context->getExtensions().lossyETCDecode)
514 {
515 context->handleError(Error(
516 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
517 return false;
518 }
519 break;
520 default:
521 context->handleError(
522 Error(GL_INVALID_ENUM,
523 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400524 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400525 }
Geoff Lang44ff5a72017-02-03 15:15:43 -0500526 if (!ValidCompressedImageSize(context, actualInternalFormat, xoffset, yoffset, width,
527 height))
tmartino0ccd5ae2015-10-01 14:33:14 -0400528 {
Jamie Madill437fa652016-05-03 15:13:24 -0400529 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400531 }
532 }
533 else
534 {
535 // validate <type> by itself (used as secondary key below)
536 switch (type)
537 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800538 case GL_UNSIGNED_BYTE:
539 case GL_UNSIGNED_SHORT_5_6_5:
540 case GL_UNSIGNED_SHORT_4_4_4_4:
541 case GL_UNSIGNED_SHORT_5_5_5_1:
542 case GL_UNSIGNED_SHORT:
543 case GL_UNSIGNED_INT:
544 case GL_UNSIGNED_INT_24_8_OES:
545 case GL_HALF_FLOAT_OES:
546 case GL_FLOAT:
547 break;
548 default:
549 context->handleError(Error(GL_INVALID_ENUM));
550 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400551 }
552
553 // validate <format> + <type> combinations
554 // - invalid <format> -> sets INVALID_ENUM
555 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
556 switch (format)
557 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800558 case GL_ALPHA:
559 case GL_LUMINANCE:
560 case GL_LUMINANCE_ALPHA:
561 switch (type)
562 {
563 case GL_UNSIGNED_BYTE:
564 case GL_FLOAT:
565 case GL_HALF_FLOAT_OES:
566 break;
567 default:
568 context->handleError(Error(GL_INVALID_OPERATION));
569 return false;
570 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400571 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800572 case GL_RED:
573 case GL_RG:
574 if (!context->getExtensions().textureRG)
575 {
576 context->handleError(Error(GL_INVALID_ENUM));
577 return false;
578 }
579 switch (type)
580 {
581 case GL_UNSIGNED_BYTE:
582 case GL_FLOAT:
583 case GL_HALF_FLOAT_OES:
584 break;
585 default:
586 context->handleError(Error(GL_INVALID_OPERATION));
587 return false;
588 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400589 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 case GL_RGB:
591 switch (type)
592 {
593 case GL_UNSIGNED_BYTE:
594 case GL_UNSIGNED_SHORT_5_6_5:
595 case GL_FLOAT:
596 case GL_HALF_FLOAT_OES:
597 break;
598 default:
599 context->handleError(Error(GL_INVALID_OPERATION));
600 return false;
601 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400602 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800603 case GL_RGBA:
604 switch (type)
605 {
606 case GL_UNSIGNED_BYTE:
607 case GL_UNSIGNED_SHORT_4_4_4_4:
608 case GL_UNSIGNED_SHORT_5_5_5_1:
609 case GL_FLOAT:
610 case GL_HALF_FLOAT_OES:
611 break;
612 default:
613 context->handleError(Error(GL_INVALID_OPERATION));
614 return false;
615 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800617 case GL_BGRA_EXT:
618 switch (type)
619 {
620 case GL_UNSIGNED_BYTE:
621 break;
622 default:
623 context->handleError(Error(GL_INVALID_OPERATION));
624 return false;
625 }
626 break;
627 case GL_SRGB_EXT:
628 case GL_SRGB_ALPHA_EXT:
629 if (!context->getExtensions().sRGB)
630 {
631 context->handleError(Error(GL_INVALID_ENUM));
632 return false;
633 }
634 switch (type)
635 {
636 case GL_UNSIGNED_BYTE:
637 break;
638 default:
639 context->handleError(Error(GL_INVALID_OPERATION));
640 return false;
641 }
642 break;
643 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
644 // handled below
645 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
646 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
647 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
648 break;
649 case GL_DEPTH_COMPONENT:
650 switch (type)
651 {
652 case GL_UNSIGNED_SHORT:
653 case GL_UNSIGNED_INT:
654 break;
655 default:
656 context->handleError(Error(GL_INVALID_OPERATION));
657 return false;
658 }
659 break;
660 case GL_DEPTH_STENCIL_OES:
661 switch (type)
662 {
663 case GL_UNSIGNED_INT_24_8_OES:
664 break;
665 default:
666 context->handleError(Error(GL_INVALID_OPERATION));
667 return false;
668 }
669 break;
670 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400671 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400672 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400673 }
674
675 switch (format)
676 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800677 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
678 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
679 if (context->getExtensions().textureCompressionDXT1)
680 {
681 context->handleError(Error(GL_INVALID_OPERATION));
682 return false;
683 }
684 else
685 {
686 context->handleError(Error(GL_INVALID_ENUM));
687 return false;
688 }
689 break;
690 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
691 if (context->getExtensions().textureCompressionDXT3)
692 {
693 context->handleError(Error(GL_INVALID_OPERATION));
694 return false;
695 }
696 else
697 {
698 context->handleError(Error(GL_INVALID_ENUM));
699 return false;
700 }
701 break;
702 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
703 if (context->getExtensions().textureCompressionDXT5)
704 {
705 context->handleError(Error(GL_INVALID_OPERATION));
706 return false;
707 }
708 else
709 {
710 context->handleError(Error(GL_INVALID_ENUM));
711 return false;
712 }
713 break;
714 case GL_ETC1_RGB8_OES:
715 if (context->getExtensions().compressedETC1RGB8Texture)
716 {
717 context->handleError(Error(GL_INVALID_OPERATION));
718 return false;
719 }
720 else
721 {
722 context->handleError(Error(GL_INVALID_ENUM));
723 return false;
724 }
725 break;
726 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800727 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
728 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
729 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
730 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800731 if (context->getExtensions().lossyETCDecode)
732 {
733 context->handleError(
734 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -0800735 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 return false;
737 }
738 else
739 {
740 context->handleError(Error(
741 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
742 return false;
743 }
744 break;
745 case GL_DEPTH_COMPONENT:
746 case GL_DEPTH_STENCIL_OES:
747 if (!context->getExtensions().depthTextures)
748 {
749 context->handleError(Error(GL_INVALID_VALUE));
750 return false;
751 }
752 if (target != GL_TEXTURE_2D)
753 {
754 context->handleError(Error(GL_INVALID_OPERATION));
755 return false;
756 }
757 // OES_depth_texture supports loading depth data and multiple levels,
758 // but ANGLE_depth_texture does not
759 if (pixels != NULL || level != 0)
760 {
761 context->handleError(Error(GL_INVALID_OPERATION));
762 return false;
763 }
764 break;
765 default:
766 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 }
768
769 if (type == GL_FLOAT)
770 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400771 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 {
Jamie Madill437fa652016-05-03 15:13:24 -0400773 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400774 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 }
776 }
777 else if (type == GL_HALF_FLOAT_OES)
778 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400779 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400780 {
Jamie Madill437fa652016-05-03 15:13:24 -0400781 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400782 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400783 }
784 }
785 }
786
Geoff Langff5b2d52016-09-07 11:32:23 -0400787 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
788 imageSize))
789 {
790 return false;
791 }
792
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400793 return true;
794}
795
He Yunchaoced53ae2016-11-29 15:00:51 +0800796bool ValidateES2TexStorageParameters(Context *context,
797 GLenum target,
798 GLsizei levels,
799 GLenum internalformat,
800 GLsizei width,
801 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802{
803 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
804 {
Jamie Madill437fa652016-05-03 15:13:24 -0400805 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400806 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400807 }
808
809 if (width < 1 || height < 1 || levels < 1)
810 {
Jamie Madill437fa652016-05-03 15:13:24 -0400811 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400812 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400813 }
814
815 if (target == GL_TEXTURE_CUBE_MAP && width != height)
816 {
Jamie Madill437fa652016-05-03 15:13:24 -0400817 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820
821 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
822 {
Jamie Madill437fa652016-05-03 15:13:24 -0400823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400824 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 }
826
Geoff Lang5d601382014-07-22 15:14:06 -0400827 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
828 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 {
Jamie Madill437fa652016-05-03 15:13:24 -0400830 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400831 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 }
833
Geoff Langaae65a42014-05-26 12:43:44 -0400834 const gl::Caps &caps = context->getCaps();
835
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 switch (target)
837 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800838 case GL_TEXTURE_2D:
839 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
840 static_cast<GLuint>(height) > caps.max2DTextureSize)
841 {
842 context->handleError(Error(GL_INVALID_VALUE));
843 return false;
844 }
845 break;
846 case GL_TEXTURE_CUBE_MAP:
847 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
848 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
849 {
850 context->handleError(Error(GL_INVALID_VALUE));
851 return false;
852 }
853 break;
854 default:
855 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858
Geoff Langc0b9ef42014-07-02 10:02:37 -0400859 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
861 if (!gl::isPow2(width) || !gl::isPow2(height))
862 {
Jamie Madill437fa652016-05-03 15:13:24 -0400863 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400864 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 }
866 }
867
868 switch (internalformat)
869 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800870 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
871 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
872 if (!context->getExtensions().textureCompressionDXT1)
873 {
874 context->handleError(Error(GL_INVALID_ENUM));
875 return false;
876 }
877 break;
878 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
879 if (!context->getExtensions().textureCompressionDXT3)
880 {
881 context->handleError(Error(GL_INVALID_ENUM));
882 return false;
883 }
884 break;
885 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
886 if (!context->getExtensions().textureCompressionDXT5)
887 {
888 context->handleError(Error(GL_INVALID_ENUM));
889 return false;
890 }
891 break;
892 case GL_ETC1_RGB8_OES:
893 if (!context->getExtensions().compressedETC1RGB8Texture)
894 {
895 context->handleError(Error(GL_INVALID_ENUM));
896 return false;
897 }
898 break;
899 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800900 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
901 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
902 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
903 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800904 if (!context->getExtensions().lossyETCDecode)
905 {
906 context->handleError(
907 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
908 return false;
909 }
910 break;
911 case GL_RGBA32F_EXT:
912 case GL_RGB32F_EXT:
913 case GL_ALPHA32F_EXT:
914 case GL_LUMINANCE32F_EXT:
915 case GL_LUMINANCE_ALPHA32F_EXT:
916 if (!context->getExtensions().textureFloat)
917 {
918 context->handleError(Error(GL_INVALID_ENUM));
919 return false;
920 }
921 break;
922 case GL_RGBA16F_EXT:
923 case GL_RGB16F_EXT:
924 case GL_ALPHA16F_EXT:
925 case GL_LUMINANCE16F_EXT:
926 case GL_LUMINANCE_ALPHA16F_EXT:
927 if (!context->getExtensions().textureHalfFloat)
928 {
929 context->handleError(Error(GL_INVALID_ENUM));
930 return false;
931 }
932 break;
933 case GL_R8_EXT:
934 case GL_RG8_EXT:
935 case GL_R16F_EXT:
936 case GL_RG16F_EXT:
937 case GL_R32F_EXT:
938 case GL_RG32F_EXT:
939 if (!context->getExtensions().textureRG)
940 {
941 context->handleError(Error(GL_INVALID_ENUM));
942 return false;
943 }
944 break;
945 case GL_DEPTH_COMPONENT16:
946 case GL_DEPTH_COMPONENT32_OES:
947 case GL_DEPTH24_STENCIL8_OES:
948 if (!context->getExtensions().depthTextures)
949 {
950 context->handleError(Error(GL_INVALID_ENUM));
951 return false;
952 }
953 if (target != GL_TEXTURE_2D)
954 {
955 context->handleError(Error(GL_INVALID_OPERATION));
956 return false;
957 }
958 // ANGLE_depth_texture only supports 1-level textures
959 if (levels != 1)
960 {
961 context->handleError(Error(GL_INVALID_OPERATION));
962 return false;
963 }
964 break;
965 default:
966 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 }
968
Geoff Lang691e58c2014-12-19 17:03:25 -0500969 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 if (!texture || texture->id() == 0)
971 {
Jamie Madill437fa652016-05-03 15:13:24 -0400972 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400973 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 }
975
Geoff Lang69cce582015-09-17 13:20:36 -0400976 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400977 {
Jamie Madill437fa652016-05-03 15:13:24 -0400978 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400979 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 }
981
982 return true;
983}
984
He Yunchaoced53ae2016-11-29 15:00:51 +0800985bool ValidateDiscardFramebufferEXT(Context *context,
986 GLenum target,
987 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -0700988 const GLenum *attachments)
989{
Jamie Madillc29968b2016-01-20 11:17:23 -0500990 if (!context->getExtensions().discardFramebuffer)
991 {
Jamie Madill437fa652016-05-03 15:13:24 -0400992 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -0500993 return false;
994 }
995
Austin Kinross08332632015-05-05 13:35:47 -0700996 bool defaultFramebuffer = false;
997
998 switch (target)
999 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001000 case GL_FRAMEBUFFER:
1001 defaultFramebuffer =
1002 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1003 break;
1004 default:
1005 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1006 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001007 }
1008
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1010 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001011}
1012
Austin Kinrossbc781f32015-10-26 09:27:38 -07001013bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1014{
1015 if (!context->getExtensions().vertexArrayObject)
1016 {
Jamie Madill437fa652016-05-03 15:13:24 -04001017 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001018 return false;
1019 }
1020
1021 return ValidateBindVertexArrayBase(context, array);
1022}
1023
1024bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1025{
1026 if (!context->getExtensions().vertexArrayObject)
1027 {
Jamie Madill437fa652016-05-03 15:13:24 -04001028 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001029 return false;
1030 }
1031
Olli Etuaho41997e72016-03-10 13:38:39 +02001032 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001033}
1034
1035bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1036{
1037 if (!context->getExtensions().vertexArrayObject)
1038 {
Jamie Madill437fa652016-05-03 15:13:24 -04001039 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001040 return false;
1041 }
1042
Olli Etuaho41997e72016-03-10 13:38:39 +02001043 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001044}
1045
1046bool ValidateIsVertexArrayOES(Context *context)
1047{
1048 if (!context->getExtensions().vertexArrayObject)
1049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001051 return false;
1052 }
1053
1054 return true;
1055}
Geoff Langc5629752015-12-07 16:29:04 -05001056
1057bool ValidateProgramBinaryOES(Context *context,
1058 GLuint program,
1059 GLenum binaryFormat,
1060 const void *binary,
1061 GLint length)
1062{
1063 if (!context->getExtensions().getProgramBinary)
1064 {
Jamie Madill437fa652016-05-03 15:13:24 -04001065 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001066 return false;
1067 }
1068
1069 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1070}
1071
1072bool ValidateGetProgramBinaryOES(Context *context,
1073 GLuint program,
1074 GLsizei bufSize,
1075 GLsizei *length,
1076 GLenum *binaryFormat,
1077 void *binary)
1078{
1079 if (!context->getExtensions().getProgramBinary)
1080 {
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001082 return false;
1083 }
1084
1085 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1086}
Geoff Lange102fee2015-12-10 11:23:30 -05001087
Geoff Lang70d0f492015-12-10 17:45:46 -05001088static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1089{
1090 switch (source)
1091 {
1092 case GL_DEBUG_SOURCE_API:
1093 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1094 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1095 case GL_DEBUG_SOURCE_OTHER:
1096 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1097 return !mustBeThirdPartyOrApplication;
1098
1099 case GL_DEBUG_SOURCE_THIRD_PARTY:
1100 case GL_DEBUG_SOURCE_APPLICATION:
1101 return true;
1102
1103 default:
1104 return false;
1105 }
1106}
1107
1108static bool ValidDebugType(GLenum type)
1109{
1110 switch (type)
1111 {
1112 case GL_DEBUG_TYPE_ERROR:
1113 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1114 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1115 case GL_DEBUG_TYPE_PERFORMANCE:
1116 case GL_DEBUG_TYPE_PORTABILITY:
1117 case GL_DEBUG_TYPE_OTHER:
1118 case GL_DEBUG_TYPE_MARKER:
1119 case GL_DEBUG_TYPE_PUSH_GROUP:
1120 case GL_DEBUG_TYPE_POP_GROUP:
1121 return true;
1122
1123 default:
1124 return false;
1125 }
1126}
1127
1128static bool ValidDebugSeverity(GLenum severity)
1129{
1130 switch (severity)
1131 {
1132 case GL_DEBUG_SEVERITY_HIGH:
1133 case GL_DEBUG_SEVERITY_MEDIUM:
1134 case GL_DEBUG_SEVERITY_LOW:
1135 case GL_DEBUG_SEVERITY_NOTIFICATION:
1136 return true;
1137
1138 default:
1139 return false;
1140 }
1141}
1142
Geoff Lange102fee2015-12-10 11:23:30 -05001143bool ValidateDebugMessageControlKHR(Context *context,
1144 GLenum source,
1145 GLenum type,
1146 GLenum severity,
1147 GLsizei count,
1148 const GLuint *ids,
1149 GLboolean enabled)
1150{
1151 if (!context->getExtensions().debug)
1152 {
Jamie Madill437fa652016-05-03 15:13:24 -04001153 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001154 return false;
1155 }
1156
Geoff Lang70d0f492015-12-10 17:45:46 -05001157 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1158 {
Jamie Madill437fa652016-05-03 15:13:24 -04001159 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001160 return false;
1161 }
1162
1163 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1164 {
Jamie Madill437fa652016-05-03 15:13:24 -04001165 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001166 return false;
1167 }
1168
1169 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1170 {
Jamie Madill437fa652016-05-03 15:13:24 -04001171 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001172 return false;
1173 }
1174
1175 if (count > 0)
1176 {
1177 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1178 {
Jamie Madill437fa652016-05-03 15:13:24 -04001179 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001180 GL_INVALID_OPERATION,
1181 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1182 return false;
1183 }
1184
1185 if (severity != GL_DONT_CARE)
1186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001188 Error(GL_INVALID_OPERATION,
1189 "If count is greater than zero, severity must be GL_DONT_CARE."));
1190 return false;
1191 }
1192 }
1193
Geoff Lange102fee2015-12-10 11:23:30 -05001194 return true;
1195}
1196
1197bool ValidateDebugMessageInsertKHR(Context *context,
1198 GLenum source,
1199 GLenum type,
1200 GLuint id,
1201 GLenum severity,
1202 GLsizei length,
1203 const GLchar *buf)
1204{
1205 if (!context->getExtensions().debug)
1206 {
Jamie Madill437fa652016-05-03 15:13:24 -04001207 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001208 return false;
1209 }
1210
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001211 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001212 {
1213 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1214 // not generate an error.
1215 return false;
1216 }
1217
1218 if (!ValidDebugSeverity(severity))
1219 {
Jamie Madill437fa652016-05-03 15:13:24 -04001220 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001221 return false;
1222 }
1223
1224 if (!ValidDebugType(type))
1225 {
Jamie Madill437fa652016-05-03 15:13:24 -04001226 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001227 return false;
1228 }
1229
1230 if (!ValidDebugSource(source, true))
1231 {
Jamie Madill437fa652016-05-03 15:13:24 -04001232 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001233 return false;
1234 }
1235
1236 size_t messageLength = (length < 0) ? strlen(buf) : length;
1237 if (messageLength > context->getExtensions().maxDebugMessageLength)
1238 {
Jamie Madill437fa652016-05-03 15:13:24 -04001239 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001240 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1241 return false;
1242 }
1243
Geoff Lange102fee2015-12-10 11:23:30 -05001244 return true;
1245}
1246
1247bool ValidateDebugMessageCallbackKHR(Context *context,
1248 GLDEBUGPROCKHR callback,
1249 const void *userParam)
1250{
1251 if (!context->getExtensions().debug)
1252 {
Jamie Madill437fa652016-05-03 15:13:24 -04001253 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001254 return false;
1255 }
1256
Geoff Lange102fee2015-12-10 11:23:30 -05001257 return true;
1258}
1259
1260bool ValidateGetDebugMessageLogKHR(Context *context,
1261 GLuint count,
1262 GLsizei bufSize,
1263 GLenum *sources,
1264 GLenum *types,
1265 GLuint *ids,
1266 GLenum *severities,
1267 GLsizei *lengths,
1268 GLchar *messageLog)
1269{
1270 if (!context->getExtensions().debug)
1271 {
Jamie Madill437fa652016-05-03 15:13:24 -04001272 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001273 return false;
1274 }
1275
Geoff Lang70d0f492015-12-10 17:45:46 -05001276 if (bufSize < 0 && messageLog != nullptr)
1277 {
Jamie Madill437fa652016-05-03 15:13:24 -04001278 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001279 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1280 return false;
1281 }
1282
Geoff Lange102fee2015-12-10 11:23:30 -05001283 return true;
1284}
1285
1286bool ValidatePushDebugGroupKHR(Context *context,
1287 GLenum source,
1288 GLuint id,
1289 GLsizei length,
1290 const GLchar *message)
1291{
1292 if (!context->getExtensions().debug)
1293 {
Jamie Madill437fa652016-05-03 15:13:24 -04001294 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001295 return false;
1296 }
1297
Geoff Lang70d0f492015-12-10 17:45:46 -05001298 if (!ValidDebugSource(source, true))
1299 {
Jamie Madill437fa652016-05-03 15:13:24 -04001300 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001301 return false;
1302 }
1303
1304 size_t messageLength = (length < 0) ? strlen(message) : length;
1305 if (messageLength > context->getExtensions().maxDebugMessageLength)
1306 {
Jamie Madill437fa652016-05-03 15:13:24 -04001307 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001308 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1309 return false;
1310 }
1311
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001312 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001313 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1314 {
Jamie Madill437fa652016-05-03 15:13:24 -04001315 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001316 Error(GL_STACK_OVERFLOW,
1317 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1318 return false;
1319 }
1320
Geoff Lange102fee2015-12-10 11:23:30 -05001321 return true;
1322}
1323
1324bool ValidatePopDebugGroupKHR(Context *context)
1325{
1326 if (!context->getExtensions().debug)
1327 {
Jamie Madill437fa652016-05-03 15:13:24 -04001328 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001329 return false;
1330 }
1331
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001332 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001333 if (currentStackSize <= 1)
1334 {
Jamie Madill437fa652016-05-03 15:13:24 -04001335 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001336 return false;
1337 }
1338
1339 return true;
1340}
1341
1342static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1343{
1344 switch (identifier)
1345 {
1346 case GL_BUFFER:
1347 if (context->getBuffer(name) == nullptr)
1348 {
Jamie Madill437fa652016-05-03 15:13:24 -04001349 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001350 return false;
1351 }
1352 return true;
1353
1354 case GL_SHADER:
1355 if (context->getShader(name) == nullptr)
1356 {
Jamie Madill437fa652016-05-03 15:13:24 -04001357 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001358 return false;
1359 }
1360 return true;
1361
1362 case GL_PROGRAM:
1363 if (context->getProgram(name) == nullptr)
1364 {
Jamie Madill437fa652016-05-03 15:13:24 -04001365 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001366 return false;
1367 }
1368 return true;
1369
1370 case GL_VERTEX_ARRAY:
1371 if (context->getVertexArray(name) == nullptr)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001374 return false;
1375 }
1376 return true;
1377
1378 case GL_QUERY:
1379 if (context->getQuery(name) == nullptr)
1380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001382 return false;
1383 }
1384 return true;
1385
1386 case GL_TRANSFORM_FEEDBACK:
1387 if (context->getTransformFeedback(name) == nullptr)
1388 {
Jamie Madill437fa652016-05-03 15:13:24 -04001389 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001390 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1391 return false;
1392 }
1393 return true;
1394
1395 case GL_SAMPLER:
1396 if (context->getSampler(name) == nullptr)
1397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001399 return false;
1400 }
1401 return true;
1402
1403 case GL_TEXTURE:
1404 if (context->getTexture(name) == nullptr)
1405 {
Jamie Madill437fa652016-05-03 15:13:24 -04001406 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001407 return false;
1408 }
1409 return true;
1410
1411 case GL_RENDERBUFFER:
1412 if (context->getRenderbuffer(name) == nullptr)
1413 {
Jamie Madill437fa652016-05-03 15:13:24 -04001414 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001415 return false;
1416 }
1417 return true;
1418
1419 case GL_FRAMEBUFFER:
1420 if (context->getFramebuffer(name) == nullptr)
1421 {
Jamie Madill437fa652016-05-03 15:13:24 -04001422 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001423 return false;
1424 }
1425 return true;
1426
1427 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001429 return false;
1430 }
Geoff Lange102fee2015-12-10 11:23:30 -05001431}
1432
Martin Radev9d901792016-07-15 15:58:58 +03001433static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1434{
1435 size_t labelLength = 0;
1436
1437 if (length < 0)
1438 {
1439 if (label != nullptr)
1440 {
1441 labelLength = strlen(label);
1442 }
1443 }
1444 else
1445 {
1446 labelLength = static_cast<size_t>(length);
1447 }
1448
1449 if (labelLength > context->getExtensions().maxLabelLength)
1450 {
1451 context->handleError(
1452 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1453 return false;
1454 }
1455
1456 return true;
1457}
1458
Geoff Lange102fee2015-12-10 11:23:30 -05001459bool ValidateObjectLabelKHR(Context *context,
1460 GLenum identifier,
1461 GLuint name,
1462 GLsizei length,
1463 const GLchar *label)
1464{
1465 if (!context->getExtensions().debug)
1466 {
Jamie Madill437fa652016-05-03 15:13:24 -04001467 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001468 return false;
1469 }
1470
Geoff Lang70d0f492015-12-10 17:45:46 -05001471 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1472 {
1473 return false;
1474 }
1475
Martin Radev9d901792016-07-15 15:58:58 +03001476 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001477 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001478 return false;
1479 }
1480
Geoff Lange102fee2015-12-10 11:23:30 -05001481 return true;
1482}
1483
1484bool ValidateGetObjectLabelKHR(Context *context,
1485 GLenum identifier,
1486 GLuint name,
1487 GLsizei bufSize,
1488 GLsizei *length,
1489 GLchar *label)
1490{
1491 if (!context->getExtensions().debug)
1492 {
Jamie Madill437fa652016-05-03 15:13:24 -04001493 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001494 return false;
1495 }
1496
Geoff Lang70d0f492015-12-10 17:45:46 -05001497 if (bufSize < 0)
1498 {
Jamie Madill437fa652016-05-03 15:13:24 -04001499 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001500 return false;
1501 }
1502
1503 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1504 {
1505 return false;
1506 }
1507
Martin Radev9d901792016-07-15 15:58:58 +03001508 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001509}
1510
1511static bool ValidateObjectPtrName(Context *context, const void *ptr)
1512{
1513 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1514 {
Jamie Madill437fa652016-05-03 15:13:24 -04001515 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001516 return false;
1517 }
1518
Geoff Lange102fee2015-12-10 11:23:30 -05001519 return true;
1520}
1521
1522bool ValidateObjectPtrLabelKHR(Context *context,
1523 const void *ptr,
1524 GLsizei length,
1525 const GLchar *label)
1526{
1527 if (!context->getExtensions().debug)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001530 return false;
1531 }
1532
Geoff Lang70d0f492015-12-10 17:45:46 -05001533 if (!ValidateObjectPtrName(context, ptr))
1534 {
1535 return false;
1536 }
1537
Martin Radev9d901792016-07-15 15:58:58 +03001538 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001539 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001540 return false;
1541 }
1542
Geoff Lange102fee2015-12-10 11:23:30 -05001543 return true;
1544}
1545
1546bool ValidateGetObjectPtrLabelKHR(Context *context,
1547 const void *ptr,
1548 GLsizei bufSize,
1549 GLsizei *length,
1550 GLchar *label)
1551{
1552 if (!context->getExtensions().debug)
1553 {
Jamie Madill437fa652016-05-03 15:13:24 -04001554 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001555 return false;
1556 }
1557
Geoff Lang70d0f492015-12-10 17:45:46 -05001558 if (bufSize < 0)
1559 {
Jamie Madill437fa652016-05-03 15:13:24 -04001560 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001561 return false;
1562 }
1563
1564 if (!ValidateObjectPtrName(context, ptr))
1565 {
1566 return false;
1567 }
1568
Martin Radev9d901792016-07-15 15:58:58 +03001569 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001570}
1571
1572bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1573{
1574 if (!context->getExtensions().debug)
1575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001577 return false;
1578 }
1579
Geoff Lang70d0f492015-12-10 17:45:46 -05001580 // TODO: represent this in Context::getQueryParameterInfo.
1581 switch (pname)
1582 {
1583 case GL_DEBUG_CALLBACK_FUNCTION:
1584 case GL_DEBUG_CALLBACK_USER_PARAM:
1585 break;
1586
1587 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001588 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001589 return false;
1590 }
1591
Geoff Lange102fee2015-12-10 11:23:30 -05001592 return true;
1593}
Jamie Madillc29968b2016-01-20 11:17:23 -05001594
1595bool ValidateBlitFramebufferANGLE(Context *context,
1596 GLint srcX0,
1597 GLint srcY0,
1598 GLint srcX1,
1599 GLint srcY1,
1600 GLint dstX0,
1601 GLint dstY0,
1602 GLint dstX1,
1603 GLint dstY1,
1604 GLbitfield mask,
1605 GLenum filter)
1606{
1607 if (!context->getExtensions().framebufferBlit)
1608 {
Jamie Madill437fa652016-05-03 15:13:24 -04001609 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001610 return false;
1611 }
1612
1613 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1614 {
1615 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001617 GL_INVALID_OPERATION,
1618 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1619 return false;
1620 }
1621
1622 if (filter == GL_LINEAR)
1623 {
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001625 return false;
1626 }
1627
Jamie Madill51f40ec2016-06-15 14:06:00 -04001628 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1629 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001630
1631 if (mask & GL_COLOR_BUFFER_BIT)
1632 {
1633 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1634 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1635
1636 if (readColorAttachment && drawColorAttachment)
1637 {
1638 if (!(readColorAttachment->type() == GL_TEXTURE &&
1639 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1640 readColorAttachment->type() != GL_RENDERBUFFER &&
1641 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1642 {
Jamie Madill437fa652016-05-03 15:13:24 -04001643 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001644 return false;
1645 }
1646
Geoff Langa15472a2015-08-11 11:48:03 -04001647 for (size_t drawbufferIdx = 0;
1648 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001649 {
Geoff Langa15472a2015-08-11 11:48:03 -04001650 const FramebufferAttachment *attachment =
1651 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1652 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001653 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001654 if (!(attachment->type() == GL_TEXTURE &&
1655 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1656 attachment->type() != GL_RENDERBUFFER &&
1657 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1658 {
Jamie Madill437fa652016-05-03 15:13:24 -04001659 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001660 return false;
1661 }
1662
1663 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001664 if (!Format::SameSized(attachment->getFormat(),
1665 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001666 {
Jamie Madill437fa652016-05-03 15:13:24 -04001667 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001668 return false;
1669 }
1670 }
1671 }
1672
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001673 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001674 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1675 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1676 {
Jamie Madill437fa652016-05-03 15:13:24 -04001677 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001678 return false;
1679 }
1680 }
1681 }
1682
1683 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1684 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1685 for (size_t i = 0; i < 2; i++)
1686 {
1687 if (mask & masks[i])
1688 {
1689 const FramebufferAttachment *readBuffer =
1690 readFramebuffer->getAttachment(attachments[i]);
1691 const FramebufferAttachment *drawBuffer =
1692 drawFramebuffer->getAttachment(attachments[i]);
1693
1694 if (readBuffer && drawBuffer)
1695 {
1696 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1697 dstX0, dstY0, dstX1, dstY1))
1698 {
1699 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05001700 context->handleError(Error(GL_INVALID_OPERATION,
1701 "Only whole-buffer depth and stencil blits are "
1702 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001703 return false;
1704 }
1705
1706 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001709 return false;
1710 }
1711 }
1712 }
1713 }
1714
1715 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1716 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001717}
Jamie Madillc29968b2016-01-20 11:17:23 -05001718
1719bool ValidateClear(ValidationContext *context, GLbitfield mask)
1720{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001721 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001722 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 {
Jamie Madill437fa652016-05-03 15:13:24 -04001724 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
1727
1728 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1729 {
Jamie Madill437fa652016-05-03 15:13:24 -04001730 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001731 return false;
1732 }
1733
Geoff Lang76e65652017-03-27 14:58:02 -04001734 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
1735 {
1736 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1737 GL_SIGNED_NORMALIZED};
1738
1739 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
1740 drawBufferIdx++)
1741 {
1742 if (!ValidateWebGLFramebufferAttachmentClearType(
1743 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
1744 {
1745 return false;
1746 }
1747 }
1748 }
1749
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 return true;
1751}
1752
1753bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1754{
1755 if (!context->getExtensions().drawBuffers)
1756 {
Jamie Madill437fa652016-05-03 15:13:24 -04001757 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001758 return false;
1759 }
1760
1761 return ValidateDrawBuffersBase(context, n, bufs);
1762}
1763
Jamie Madill73a84962016-02-12 09:27:23 -05001764bool ValidateTexImage2D(Context *context,
1765 GLenum target,
1766 GLint level,
1767 GLint internalformat,
1768 GLsizei width,
1769 GLsizei height,
1770 GLint border,
1771 GLenum format,
1772 GLenum type,
1773 const GLvoid *pixels)
1774{
Martin Radev1be913c2016-07-11 17:59:16 +03001775 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001776 {
1777 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001778 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001779 }
1780
Martin Radev1be913c2016-07-11 17:59:16 +03001781 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001782 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001783 0, 0, width, height, 1, border, format, type, -1,
1784 pixels);
1785}
1786
1787bool ValidateTexImage2DRobust(Context *context,
1788 GLenum target,
1789 GLint level,
1790 GLint internalformat,
1791 GLsizei width,
1792 GLsizei height,
1793 GLint border,
1794 GLenum format,
1795 GLenum type,
1796 GLsizei bufSize,
1797 const GLvoid *pixels)
1798{
1799 if (!ValidateRobustEntryPoint(context, bufSize))
1800 {
1801 return false;
1802 }
1803
1804 if (context->getClientMajorVersion() < 3)
1805 {
1806 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1807 0, 0, width, height, border, format, type, bufSize,
1808 pixels);
1809 }
1810
1811 ASSERT(context->getClientMajorVersion() >= 3);
1812 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1813 0, 0, width, height, 1, border, format, type, bufSize,
1814 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001815}
1816
1817bool ValidateTexSubImage2D(Context *context,
1818 GLenum target,
1819 GLint level,
1820 GLint xoffset,
1821 GLint yoffset,
1822 GLsizei width,
1823 GLsizei height,
1824 GLenum format,
1825 GLenum type,
1826 const GLvoid *pixels)
1827{
1828
Martin Radev1be913c2016-07-11 17:59:16 +03001829 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001830 {
1831 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001832 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001833 }
1834
Martin Radev1be913c2016-07-11 17:59:16 +03001835 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001836 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001837 yoffset, 0, width, height, 1, 0, format, type, -1,
1838 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001839}
1840
Geoff Langc52f6f12016-10-14 10:18:00 -04001841bool ValidateTexSubImage2DRobustANGLE(Context *context,
1842 GLenum target,
1843 GLint level,
1844 GLint xoffset,
1845 GLint yoffset,
1846 GLsizei width,
1847 GLsizei height,
1848 GLenum format,
1849 GLenum type,
1850 GLsizei bufSize,
1851 const GLvoid *pixels)
1852{
1853 if (!ValidateRobustEntryPoint(context, bufSize))
1854 {
1855 return false;
1856 }
1857
1858 if (context->getClientMajorVersion() < 3)
1859 {
1860 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1861 yoffset, width, height, 0, format, type, bufSize,
1862 pixels);
1863 }
1864
1865 ASSERT(context->getClientMajorVersion() >= 3);
1866 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1867 yoffset, 0, width, height, 1, 0, format, type, bufSize,
1868 pixels);
1869}
1870
Jamie Madill73a84962016-02-12 09:27:23 -05001871bool ValidateCompressedTexImage2D(Context *context,
1872 GLenum target,
1873 GLint level,
1874 GLenum internalformat,
1875 GLsizei width,
1876 GLsizei height,
1877 GLint border,
1878 GLsizei imageSize,
1879 const GLvoid *data)
1880{
Martin Radev1be913c2016-07-11 17:59:16 +03001881 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001882 {
1883 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001884 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001885 {
1886 return false;
1887 }
1888 }
1889 else
1890 {
Martin Radev1be913c2016-07-11 17:59:16 +03001891 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001892 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001893 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001894 data))
1895 {
1896 return false;
1897 }
1898 }
1899
1900 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001901 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001902 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001903 if (blockSizeOrErr.isError())
1904 {
1905 context->handleError(blockSizeOrErr.getError());
1906 return false;
1907 }
1908
1909 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001910 {
Jamie Madill437fa652016-05-03 15:13:24 -04001911 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001912 return false;
1913 }
1914
1915 return true;
1916}
1917
1918bool ValidateCompressedTexSubImage2D(Context *context,
1919 GLenum target,
1920 GLint level,
1921 GLint xoffset,
1922 GLint yoffset,
1923 GLsizei width,
1924 GLsizei height,
1925 GLenum format,
1926 GLsizei imageSize,
1927 const GLvoid *data)
1928{
Martin Radev1be913c2016-07-11 17:59:16 +03001929 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001930 {
1931 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001932 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001933 {
1934 return false;
1935 }
1936 }
1937 else
1938 {
Martin Radev1be913c2016-07-11 17:59:16 +03001939 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001940 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001941 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001942 data))
1943 {
1944 return false;
1945 }
1946 }
1947
1948 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001949 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001950 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001951 if (blockSizeOrErr.isError())
1952 {
1953 context->handleError(blockSizeOrErr.getError());
1954 return false;
1955 }
1956
1957 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001958 {
Jamie Madill437fa652016-05-03 15:13:24 -04001959 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001960 return false;
1961 }
1962
1963 return true;
1964}
1965
Olli Etuaho4f667482016-03-30 15:56:35 +03001966bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
1967{
Geoff Lang496c02d2016-10-20 11:38:11 -07001968 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03001969}
1970
1971bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
1972{
1973 if (!context->getExtensions().mapBuffer)
1974 {
Jamie Madill437fa652016-05-03 15:13:24 -04001975 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001976 return false;
1977 }
1978
1979 if (!ValidBufferTarget(context, target))
1980 {
Jamie Madill437fa652016-05-03 15:13:24 -04001981 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001982 return false;
1983 }
1984
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001985 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03001986
1987 if (buffer == nullptr)
1988 {
Jamie Madill437fa652016-05-03 15:13:24 -04001989 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001990 return false;
1991 }
1992
1993 if (access != GL_WRITE_ONLY_OES)
1994 {
Jamie Madill437fa652016-05-03 15:13:24 -04001995 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03001996 return false;
1997 }
1998
1999 if (buffer->isMapped())
2000 {
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002002 return false;
2003 }
2004
2005 return true;
2006}
2007
2008bool ValidateUnmapBufferOES(Context *context, GLenum target)
2009{
2010 if (!context->getExtensions().mapBuffer)
2011 {
Jamie Madill437fa652016-05-03 15:13:24 -04002012 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002013 return false;
2014 }
2015
2016 return ValidateUnmapBufferBase(context, target);
2017}
2018
2019bool ValidateMapBufferRangeEXT(Context *context,
2020 GLenum target,
2021 GLintptr offset,
2022 GLsizeiptr length,
2023 GLbitfield access)
2024{
2025 if (!context->getExtensions().mapBufferRange)
2026 {
Jamie Madill437fa652016-05-03 15:13:24 -04002027 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002028 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2029 return false;
2030 }
2031
2032 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2033}
2034
2035bool ValidateFlushMappedBufferRangeEXT(Context *context,
2036 GLenum target,
2037 GLintptr offset,
2038 GLsizeiptr length)
2039{
2040 if (!context->getExtensions().mapBufferRange)
2041 {
Jamie Madill437fa652016-05-03 15:13:24 -04002042 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002043 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2044 return false;
2045 }
2046
2047 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2048}
2049
Ian Ewell54f87462016-03-10 13:47:21 -05002050bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2051{
2052 Texture *textureObject = context->getTexture(texture);
2053 if (textureObject && textureObject->getTarget() != target && texture != 0)
2054 {
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002056 return false;
2057 }
2058
Geoff Langf41a7152016-09-19 15:11:17 -04002059 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2060 !context->isTextureGenerated(texture))
2061 {
2062 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2063 return false;
2064 }
2065
Ian Ewell54f87462016-03-10 13:47:21 -05002066 switch (target)
2067 {
2068 case GL_TEXTURE_2D:
2069 case GL_TEXTURE_CUBE_MAP:
2070 break;
2071
2072 case GL_TEXTURE_3D:
2073 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002074 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002077 return false;
2078 }
2079 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002080
2081 case GL_TEXTURE_2D_MULTISAMPLE:
2082 if (context->getClientVersion() < Version(3, 1))
2083 {
2084 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2085 return false;
2086 }
Geoff Lang3b573612016-10-31 14:08:10 -04002087 break;
2088
Ian Ewell54f87462016-03-10 13:47:21 -05002089 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002090 if (!context->getExtensions().eglImageExternal &&
2091 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002092 {
Jamie Madill437fa652016-05-03 15:13:24 -04002093 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002094 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2095 return false;
2096 }
2097 break;
2098 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002099 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002100 return false;
2101 }
2102
2103 return true;
2104}
2105
Geoff Langd8605522016-04-13 10:19:12 -04002106bool ValidateBindUniformLocationCHROMIUM(Context *context,
2107 GLuint program,
2108 GLint location,
2109 const GLchar *name)
2110{
2111 if (!context->getExtensions().bindUniformLocation)
2112 {
Jamie Madill437fa652016-05-03 15:13:24 -04002113 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002114 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2115 return false;
2116 }
2117
2118 Program *programObject = GetValidProgram(context, program);
2119 if (!programObject)
2120 {
2121 return false;
2122 }
2123
2124 if (location < 0)
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002127 return false;
2128 }
2129
2130 const Caps &caps = context->getCaps();
2131 if (static_cast<size_t>(location) >=
2132 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002135 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2136 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2137 return false;
2138 }
2139
2140 if (strncmp(name, "gl_", 3) == 0)
2141 {
Jamie Madill437fa652016-05-03 15:13:24 -04002142 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002143 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2144 return false;
2145 }
2146
2147 return true;
2148}
2149
Jamie Madille2e406c2016-06-02 13:04:10 -04002150bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002151{
2152 if (!context->getExtensions().framebufferMixedSamples)
2153 {
2154 context->handleError(
2155 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2156 return false;
2157 }
2158 switch (components)
2159 {
2160 case GL_RGB:
2161 case GL_RGBA:
2162 case GL_ALPHA:
2163 case GL_NONE:
2164 break;
2165 default:
2166 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002167 Error(GL_INVALID_ENUM,
2168 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002169 return false;
2170 }
2171
2172 return true;
2173}
2174
Sami Väisänene45e53b2016-05-25 10:36:04 +03002175// CHROMIUM_path_rendering
2176
2177bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2178{
2179 if (!context->getExtensions().pathRendering)
2180 {
2181 context->handleError(
2182 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2183 return false;
2184 }
2185 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2186 {
2187 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2188 return false;
2189 }
2190 if (matrix == nullptr)
2191 {
2192 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2193 return false;
2194 }
2195 return true;
2196}
2197
2198bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2199{
2200 if (!context->getExtensions().pathRendering)
2201 {
2202 context->handleError(
2203 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2204 return false;
2205 }
2206 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2207 {
2208 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2209 return false;
2210 }
2211 return true;
2212}
2213
2214bool ValidateGenPaths(Context *context, GLsizei range)
2215{
2216 if (!context->getExtensions().pathRendering)
2217 {
2218 context->handleError(
2219 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2220 return false;
2221 }
2222
2223 // range = 0 is undefined in NV_path_rendering.
2224 // we add stricter semantic check here and require a non zero positive range.
2225 if (range <= 0)
2226 {
2227 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2228 return false;
2229 }
2230
2231 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2232 {
2233 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2234 return false;
2235 }
2236
2237 return true;
2238}
2239
2240bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2241{
2242 if (!context->getExtensions().pathRendering)
2243 {
2244 context->handleError(
2245 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2246 return false;
2247 }
2248
2249 // range = 0 is undefined in NV_path_rendering.
2250 // we add stricter semantic check here and require a non zero positive range.
2251 if (range <= 0)
2252 {
2253 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2254 return false;
2255 }
2256
2257 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2258 checkedRange += range;
2259
2260 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2261 {
2262 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2263 return false;
2264 }
2265 return true;
2266}
2267
2268bool ValidatePathCommands(Context *context,
2269 GLuint path,
2270 GLsizei numCommands,
2271 const GLubyte *commands,
2272 GLsizei numCoords,
2273 GLenum coordType,
2274 const void *coords)
2275{
2276 if (!context->getExtensions().pathRendering)
2277 {
2278 context->handleError(
2279 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2280 return false;
2281 }
2282 if (!context->hasPath(path))
2283 {
2284 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2285 return false;
2286 }
2287
2288 if (numCommands < 0)
2289 {
2290 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2291 return false;
2292 }
2293 else if (numCommands > 0)
2294 {
2295 if (!commands)
2296 {
2297 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2298 return false;
2299 }
2300 }
2301
2302 if (numCoords < 0)
2303 {
2304 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2305 return false;
2306 }
2307 else if (numCoords > 0)
2308 {
2309 if (!coords)
2310 {
2311 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2312 return false;
2313 }
2314 }
2315
2316 std::uint32_t coordTypeSize = 0;
2317 switch (coordType)
2318 {
2319 case GL_BYTE:
2320 coordTypeSize = sizeof(GLbyte);
2321 break;
2322
2323 case GL_UNSIGNED_BYTE:
2324 coordTypeSize = sizeof(GLubyte);
2325 break;
2326
2327 case GL_SHORT:
2328 coordTypeSize = sizeof(GLshort);
2329 break;
2330
2331 case GL_UNSIGNED_SHORT:
2332 coordTypeSize = sizeof(GLushort);
2333 break;
2334
2335 case GL_FLOAT:
2336 coordTypeSize = sizeof(GLfloat);
2337 break;
2338
2339 default:
2340 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2341 return false;
2342 }
2343
2344 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2345 checkedSize += (coordTypeSize * numCoords);
2346 if (!checkedSize.IsValid())
2347 {
2348 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2349 return false;
2350 }
2351
2352 // early return skips command data validation when it doesn't exist.
2353 if (!commands)
2354 return true;
2355
2356 GLsizei expectedNumCoords = 0;
2357 for (GLsizei i = 0; i < numCommands; ++i)
2358 {
2359 switch (commands[i])
2360 {
2361 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2362 break;
2363 case GL_MOVE_TO_CHROMIUM:
2364 case GL_LINE_TO_CHROMIUM:
2365 expectedNumCoords += 2;
2366 break;
2367 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2368 expectedNumCoords += 4;
2369 break;
2370 case GL_CUBIC_CURVE_TO_CHROMIUM:
2371 expectedNumCoords += 6;
2372 break;
2373 case GL_CONIC_CURVE_TO_CHROMIUM:
2374 expectedNumCoords += 5;
2375 break;
2376 default:
2377 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2378 return false;
2379 }
2380 }
2381 if (expectedNumCoords != numCoords)
2382 {
2383 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2384 return false;
2385 }
2386
2387 return true;
2388}
2389
2390bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2391{
2392 if (!context->getExtensions().pathRendering)
2393 {
2394 context->handleError(
2395 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2396 return false;
2397 }
2398 if (!context->hasPath(path))
2399 {
2400 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2401 return false;
2402 }
2403
2404 switch (pname)
2405 {
2406 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2407 if (value < 0.0f)
2408 {
2409 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2410 return false;
2411 }
2412 break;
2413 case GL_PATH_END_CAPS_CHROMIUM:
2414 switch (static_cast<GLenum>(value))
2415 {
2416 case GL_FLAT_CHROMIUM:
2417 case GL_SQUARE_CHROMIUM:
2418 case GL_ROUND_CHROMIUM:
2419 break;
2420 default:
2421 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2422 return false;
2423 }
2424 break;
2425 case GL_PATH_JOIN_STYLE_CHROMIUM:
2426 switch (static_cast<GLenum>(value))
2427 {
2428 case GL_MITER_REVERT_CHROMIUM:
2429 case GL_BEVEL_CHROMIUM:
2430 case GL_ROUND_CHROMIUM:
2431 break;
2432 default:
2433 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2434 return false;
2435 }
2436 case GL_PATH_MITER_LIMIT_CHROMIUM:
2437 if (value < 0.0f)
2438 {
2439 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2440 return false;
2441 }
2442 break;
2443
2444 case GL_PATH_STROKE_BOUND_CHROMIUM:
2445 // no errors, only clamping.
2446 break;
2447
2448 default:
2449 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2450 return false;
2451 }
2452 return true;
2453}
2454
2455bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2456{
2457 if (!context->getExtensions().pathRendering)
2458 {
2459 context->handleError(
2460 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2461 return false;
2462 }
2463
2464 if (!context->hasPath(path))
2465 {
2466 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2467 return false;
2468 }
2469 if (!value)
2470 {
2471 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2472 return false;
2473 }
2474
2475 switch (pname)
2476 {
2477 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2478 case GL_PATH_END_CAPS_CHROMIUM:
2479 case GL_PATH_JOIN_STYLE_CHROMIUM:
2480 case GL_PATH_MITER_LIMIT_CHROMIUM:
2481 case GL_PATH_STROKE_BOUND_CHROMIUM:
2482 break;
2483
2484 default:
2485 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2486 return false;
2487 }
2488
2489 return true;
2490}
2491
2492bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2493{
2494 if (!context->getExtensions().pathRendering)
2495 {
2496 context->handleError(
2497 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2498 return false;
2499 }
2500
2501 switch (func)
2502 {
2503 case GL_NEVER:
2504 case GL_ALWAYS:
2505 case GL_LESS:
2506 case GL_LEQUAL:
2507 case GL_EQUAL:
2508 case GL_GEQUAL:
2509 case GL_GREATER:
2510 case GL_NOTEQUAL:
2511 break;
2512 default:
2513 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2514 return false;
2515 }
2516
2517 return true;
2518}
2519
2520// Note that the spec specifies that for the path drawing commands
2521// if the path object is not an existing path object the command
2522// does nothing and no error is generated.
2523// However if the path object exists but has not been specified any
2524// commands then an error is generated.
2525
2526bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2527{
2528 if (!context->getExtensions().pathRendering)
2529 {
2530 context->handleError(
2531 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2532 return false;
2533 }
2534 if (context->hasPath(path) && !context->hasPathData(path))
2535 {
2536 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2537 return false;
2538 }
2539
2540 switch (fillMode)
2541 {
2542 case GL_COUNT_UP_CHROMIUM:
2543 case GL_COUNT_DOWN_CHROMIUM:
2544 break;
2545 default:
2546 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2547 return false;
2548 }
2549
2550 if (!isPow2(mask + 1))
2551 {
2552 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2553 return false;
2554 }
2555
2556 return true;
2557}
2558
2559bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2560{
2561 if (!context->getExtensions().pathRendering)
2562 {
2563 context->handleError(
2564 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2565 return false;
2566 }
2567 if (context->hasPath(path) && !context->hasPathData(path))
2568 {
2569 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2570 return false;
2571 }
2572
2573 return true;
2574}
2575
2576bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2577{
2578 if (!context->getExtensions().pathRendering)
2579 {
2580 context->handleError(
2581 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2582 return false;
2583 }
2584 if (context->hasPath(path) && !context->hasPathData(path))
2585 {
2586 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2587 return false;
2588 }
2589
2590 switch (coverMode)
2591 {
2592 case GL_CONVEX_HULL_CHROMIUM:
2593 case GL_BOUNDING_BOX_CHROMIUM:
2594 break;
2595 default:
2596 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2597 return false;
2598 }
2599 return true;
2600}
2601
2602bool ValidateStencilThenCoverFillPath(Context *context,
2603 GLuint path,
2604 GLenum fillMode,
2605 GLuint mask,
2606 GLenum coverMode)
2607{
2608 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2609 ValidateCoverPath(context, path, coverMode);
2610}
2611
2612bool ValidateStencilThenCoverStrokePath(Context *context,
2613 GLuint path,
2614 GLint reference,
2615 GLuint mask,
2616 GLenum coverMode)
2617{
2618 return ValidateStencilStrokePath(context, path, reference, mask) &&
2619 ValidateCoverPath(context, path, coverMode);
2620}
2621
2622bool ValidateIsPath(Context *context)
2623{
2624 if (!context->getExtensions().pathRendering)
2625 {
2626 context->handleError(
2627 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2628 return false;
2629 }
2630 return true;
2631}
2632
Sami Väisänend59ca052016-06-21 16:10:00 +03002633bool ValidateCoverFillPathInstanced(Context *context,
2634 GLsizei numPaths,
2635 GLenum pathNameType,
2636 const void *paths,
2637 GLuint pathBase,
2638 GLenum coverMode,
2639 GLenum transformType,
2640 const GLfloat *transformValues)
2641{
2642 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2643 transformType, transformValues))
2644 return false;
2645
2646 switch (coverMode)
2647 {
2648 case GL_CONVEX_HULL_CHROMIUM:
2649 case GL_BOUNDING_BOX_CHROMIUM:
2650 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2651 break;
2652 default:
2653 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2654 return false;
2655 }
2656
2657 return true;
2658}
2659
2660bool ValidateCoverStrokePathInstanced(Context *context,
2661 GLsizei numPaths,
2662 GLenum pathNameType,
2663 const void *paths,
2664 GLuint pathBase,
2665 GLenum coverMode,
2666 GLenum transformType,
2667 const GLfloat *transformValues)
2668{
2669 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2670 transformType, transformValues))
2671 return false;
2672
2673 switch (coverMode)
2674 {
2675 case GL_CONVEX_HULL_CHROMIUM:
2676 case GL_BOUNDING_BOX_CHROMIUM:
2677 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2678 break;
2679 default:
2680 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2681 return false;
2682 }
2683
2684 return true;
2685}
2686
2687bool ValidateStencilFillPathInstanced(Context *context,
2688 GLsizei numPaths,
2689 GLenum pathNameType,
2690 const void *paths,
2691 GLuint pathBase,
2692 GLenum fillMode,
2693 GLuint mask,
2694 GLenum transformType,
2695 const GLfloat *transformValues)
2696{
2697
2698 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2699 transformType, transformValues))
2700 return false;
2701
2702 switch (fillMode)
2703 {
2704 case GL_COUNT_UP_CHROMIUM:
2705 case GL_COUNT_DOWN_CHROMIUM:
2706 break;
2707 default:
2708 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2709 return false;
2710 }
2711 if (!isPow2(mask + 1))
2712 {
2713 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2714 return false;
2715 }
2716 return true;
2717}
2718
2719bool ValidateStencilStrokePathInstanced(Context *context,
2720 GLsizei numPaths,
2721 GLenum pathNameType,
2722 const void *paths,
2723 GLuint pathBase,
2724 GLint reference,
2725 GLuint mask,
2726 GLenum transformType,
2727 const GLfloat *transformValues)
2728{
2729 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2730 transformType, transformValues))
2731 return false;
2732
2733 // no more validation here.
2734
2735 return true;
2736}
2737
2738bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2739 GLsizei numPaths,
2740 GLenum pathNameType,
2741 const void *paths,
2742 GLuint pathBase,
2743 GLenum fillMode,
2744 GLuint mask,
2745 GLenum coverMode,
2746 GLenum transformType,
2747 const GLfloat *transformValues)
2748{
2749 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2750 transformType, transformValues))
2751 return false;
2752
2753 switch (coverMode)
2754 {
2755 case GL_CONVEX_HULL_CHROMIUM:
2756 case GL_BOUNDING_BOX_CHROMIUM:
2757 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2758 break;
2759 default:
2760 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2761 return false;
2762 }
2763
2764 switch (fillMode)
2765 {
2766 case GL_COUNT_UP_CHROMIUM:
2767 case GL_COUNT_DOWN_CHROMIUM:
2768 break;
2769 default:
2770 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2771 return false;
2772 }
2773 if (!isPow2(mask + 1))
2774 {
2775 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2776 return false;
2777 }
2778
2779 return true;
2780}
2781
2782bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2783 GLsizei numPaths,
2784 GLenum pathNameType,
2785 const void *paths,
2786 GLuint pathBase,
2787 GLint reference,
2788 GLuint mask,
2789 GLenum coverMode,
2790 GLenum transformType,
2791 const GLfloat *transformValues)
2792{
2793 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2794 transformType, transformValues))
2795 return false;
2796
2797 switch (coverMode)
2798 {
2799 case GL_CONVEX_HULL_CHROMIUM:
2800 case GL_BOUNDING_BOX_CHROMIUM:
2801 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2802 break;
2803 default:
2804 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2805 return false;
2806 }
2807
2808 return true;
2809}
2810
Sami Väisänen46eaa942016-06-29 10:26:37 +03002811bool ValidateBindFragmentInputLocation(Context *context,
2812 GLuint program,
2813 GLint location,
2814 const GLchar *name)
2815{
2816 if (!context->getExtensions().pathRendering)
2817 {
2818 context->handleError(
2819 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2820 return false;
2821 }
2822
2823 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2824 if (location >= MaxLocation)
2825 {
2826 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2827 return false;
2828 }
2829
2830 const auto *programObject = context->getProgram(program);
2831 if (!programObject)
2832 {
2833 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2834 return false;
2835 }
2836
2837 if (!name)
2838 {
2839 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2840 return false;
2841 }
2842
2843 if (angle::BeginsWith(name, "gl_"))
2844 {
2845 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2846 return false;
2847 }
2848
2849 return true;
2850}
2851
2852bool ValidateProgramPathFragmentInputGen(Context *context,
2853 GLuint program,
2854 GLint location,
2855 GLenum genMode,
2856 GLint components,
2857 const GLfloat *coeffs)
2858{
2859 if (!context->getExtensions().pathRendering)
2860 {
2861 context->handleError(
2862 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2863 return false;
2864 }
2865
2866 const auto *programObject = context->getProgram(program);
2867 if (!programObject || programObject->isFlaggedForDeletion())
2868 {
2869 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2870 return false;
2871 }
2872
2873 if (!programObject->isLinked())
2874 {
2875 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2876 return false;
2877 }
2878
2879 switch (genMode)
2880 {
2881 case GL_NONE:
2882 if (components != 0)
2883 {
2884 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2885 return false;
2886 }
2887 break;
2888
2889 case GL_OBJECT_LINEAR_CHROMIUM:
2890 case GL_EYE_LINEAR_CHROMIUM:
2891 case GL_CONSTANT_CHROMIUM:
2892 if (components < 1 || components > 4)
2893 {
2894 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2895 return false;
2896 }
2897 if (!coeffs)
2898 {
2899 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2900 return false;
2901 }
2902 break;
2903
2904 default:
2905 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2906 return false;
2907 }
2908
2909 // If the location is -1 then the command is silently ignored
2910 // and no further validation is needed.
2911 if (location == -1)
2912 return true;
2913
2914 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2915
2916 if (!binding.valid)
2917 {
2918 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
2919 return false;
2920 }
2921
2922 if (binding.type != GL_NONE)
2923 {
2924 GLint expectedComponents = 0;
2925 switch (binding.type)
2926 {
2927 case GL_FLOAT:
2928 expectedComponents = 1;
2929 break;
2930 case GL_FLOAT_VEC2:
2931 expectedComponents = 2;
2932 break;
2933 case GL_FLOAT_VEC3:
2934 expectedComponents = 3;
2935 break;
2936 case GL_FLOAT_VEC4:
2937 expectedComponents = 4;
2938 break;
2939 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08002940 context->handleError(
2941 Error(GL_INVALID_OPERATION,
2942 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03002943 return false;
2944 }
2945 if (expectedComponents != components && genMode != GL_NONE)
2946 {
2947 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
2948 return false;
2949 }
2950 }
2951 return true;
2952}
2953
Geoff Lang97073d12016-04-20 10:42:34 -07002954bool ValidateCopyTextureCHROMIUM(Context *context,
2955 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04002956 GLint sourceLevel,
2957 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07002958 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04002959 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07002960 GLint internalFormat,
2961 GLenum destType,
2962 GLboolean unpackFlipY,
2963 GLboolean unpackPremultiplyAlpha,
2964 GLboolean unpackUnmultiplyAlpha)
2965{
2966 if (!context->getExtensions().copyTexture)
2967 {
2968 context->handleError(
2969 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
2970 return false;
2971 }
2972
2973 const gl::Texture *source = context->getTexture(sourceId);
2974 if (source == nullptr)
2975 {
2976 context->handleError(
2977 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
2978 return false;
2979 }
2980
2981 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
2982 {
2983 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
2984 return false;
2985 }
2986
2987 GLenum sourceTarget = source->getTarget();
2988 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
2989 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
2990 {
2991 context->handleError(
2992 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
2993 return false;
2994 }
2995
2996 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
2997 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
2998 {
2999 context->handleError(
3000 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3001 return false;
3002 }
3003
3004 const gl::Texture *dest = context->getTexture(destId);
3005 if (dest == nullptr)
3006 {
3007 context->handleError(
3008 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3009 return false;
3010 }
3011
3012 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3013 {
3014 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3015 return false;
3016 }
3017
3018 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3019 {
3020 context->handleError(
3021 Error(GL_INVALID_OPERATION,
3022 "Destination internal format and type combination is not valid."));
3023 return false;
3024 }
3025
3026 if (dest->getImmutableFormat())
3027 {
3028 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3029 return false;
3030 }
3031
3032 return true;
3033}
3034
3035bool ValidateCopySubTextureCHROMIUM(Context *context,
3036 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003037 GLint sourceLevel,
3038 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003039 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003040 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003041 GLint xoffset,
3042 GLint yoffset,
3043 GLint x,
3044 GLint y,
3045 GLsizei width,
3046 GLsizei height,
3047 GLboolean unpackFlipY,
3048 GLboolean unpackPremultiplyAlpha,
3049 GLboolean unpackUnmultiplyAlpha)
3050{
3051 if (!context->getExtensions().copyTexture)
3052 {
3053 context->handleError(
3054 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3055 return false;
3056 }
3057
3058 const gl::Texture *source = context->getTexture(sourceId);
3059 if (source == nullptr)
3060 {
3061 context->handleError(
3062 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3063 return false;
3064 }
3065
3066 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3067 {
3068 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3069 return false;
3070 }
3071
3072 GLenum sourceTarget = source->getTarget();
3073 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3074 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3075 {
3076 context->handleError(
3077 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3078 return false;
3079 }
3080
3081 if (x < 0 || y < 0)
3082 {
3083 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3084 return false;
3085 }
3086
3087 if (width < 0 || height < 0)
3088 {
3089 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3090 return false;
3091 }
3092
3093 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3094 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3095 {
3096 context->handleError(
3097 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3098 return false;
3099 }
3100
3101 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3102 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3103 {
3104 context->handleError(
3105 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3106 return false;
3107 }
3108
3109 const gl::Texture *dest = context->getTexture(destId);
3110 if (dest == nullptr)
3111 {
3112 context->handleError(
3113 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3114 return false;
3115 }
3116
3117 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3118 {
3119 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3120 return false;
3121 }
3122
Geoff Lang97073d12016-04-20 10:42:34 -07003123 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3124 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3125 {
3126 context->handleError(
3127 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3128 return false;
3129 }
3130
3131 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3132 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3133 {
3134 context->handleError(
3135 Error(GL_INVALID_OPERATION,
3136 "Destination internal format and type combination is not valid."));
3137 return false;
3138 }
3139
3140 if (xoffset < 0 || yoffset < 0)
3141 {
3142 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3143 return false;
3144 }
3145
3146 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3147 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3148 {
3149 context->handleError(
3150 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3151 return false;
3152 }
3153
3154 return true;
3155}
3156
Geoff Lang47110bf2016-04-20 11:13:22 -07003157bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3158{
3159 if (!context->getExtensions().copyCompressedTexture)
3160 {
3161 context->handleError(Error(GL_INVALID_OPERATION,
3162 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3163 return false;
3164 }
3165
3166 const gl::Texture *source = context->getTexture(sourceId);
3167 if (source == nullptr)
3168 {
3169 context->handleError(
3170 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3171 return false;
3172 }
3173
3174 if (source->getTarget() != GL_TEXTURE_2D)
3175 {
3176 context->handleError(
3177 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3178 return false;
3179 }
3180
3181 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3182 {
3183 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3184 return false;
3185 }
3186
3187 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3188 if (!sourceFormat.info->compressed)
3189 {
3190 context->handleError(
3191 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3192 return false;
3193 }
3194
3195 const gl::Texture *dest = context->getTexture(destId);
3196 if (dest == nullptr)
3197 {
3198 context->handleError(
3199 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3200 return false;
3201 }
3202
3203 if (dest->getTarget() != GL_TEXTURE_2D)
3204 {
3205 context->handleError(
3206 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3207 return false;
3208 }
3209
3210 if (dest->getImmutableFormat())
3211 {
3212 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3213 return false;
3214 }
3215
3216 return true;
3217}
3218
Martin Radev4c4c8e72016-08-04 12:25:34 +03003219bool ValidateCreateShader(Context *context, GLenum type)
3220{
3221 switch (type)
3222 {
3223 case GL_VERTEX_SHADER:
3224 case GL_FRAGMENT_SHADER:
3225 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003226
Martin Radev4c4c8e72016-08-04 12:25:34 +03003227 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003228 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003229 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003230 context->handleError(
3231 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3232 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003233 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003234 break;
3235
Martin Radev4c4c8e72016-08-04 12:25:34 +03003236 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003237 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003238 return false;
3239 }
Jamie Madill29639852016-09-02 15:00:09 -04003240
3241 return true;
3242}
3243
3244bool ValidateBufferData(ValidationContext *context,
3245 GLenum target,
3246 GLsizeiptr size,
3247 const GLvoid *data,
3248 GLenum usage)
3249{
3250 if (size < 0)
3251 {
3252 context->handleError(Error(GL_INVALID_VALUE));
3253 return false;
3254 }
3255
3256 switch (usage)
3257 {
3258 case GL_STREAM_DRAW:
3259 case GL_STATIC_DRAW:
3260 case GL_DYNAMIC_DRAW:
3261 break;
3262
3263 case GL_STREAM_READ:
3264 case GL_STREAM_COPY:
3265 case GL_STATIC_READ:
3266 case GL_STATIC_COPY:
3267 case GL_DYNAMIC_READ:
3268 case GL_DYNAMIC_COPY:
3269 if (context->getClientMajorVersion() < 3)
3270 {
3271 context->handleError(Error(GL_INVALID_ENUM));
3272 return false;
3273 }
3274 break;
3275
3276 default:
3277 context->handleError(Error(GL_INVALID_ENUM));
3278 return false;
3279 }
3280
3281 if (!ValidBufferTarget(context, target))
3282 {
3283 context->handleError(Error(GL_INVALID_ENUM));
3284 return false;
3285 }
3286
3287 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3288
3289 if (!buffer)
3290 {
3291 context->handleError(Error(GL_INVALID_OPERATION));
3292 return false;
3293 }
3294
3295 return true;
3296}
3297
3298bool ValidateBufferSubData(ValidationContext *context,
3299 GLenum target,
3300 GLintptr offset,
3301 GLsizeiptr size,
3302 const GLvoid *data)
3303{
3304 if (size < 0 || offset < 0)
3305 {
3306 context->handleError(Error(GL_INVALID_VALUE));
3307 return false;
3308 }
3309
3310 if (!ValidBufferTarget(context, target))
3311 {
3312 context->handleError(Error(GL_INVALID_ENUM));
3313 return false;
3314 }
3315
3316 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3317
3318 if (!buffer)
3319 {
3320 context->handleError(Error(GL_INVALID_OPERATION));
3321 return false;
3322 }
3323
3324 if (buffer->isMapped())
3325 {
3326 context->handleError(Error(GL_INVALID_OPERATION));
3327 return false;
3328 }
3329
3330 // Check for possible overflow of size + offset
3331 angle::CheckedNumeric<size_t> checkedSize(size);
3332 checkedSize += offset;
3333 if (!checkedSize.IsValid())
3334 {
3335 context->handleError(Error(GL_OUT_OF_MEMORY));
3336 return false;
3337 }
3338
3339 if (size + offset > buffer->getSize())
3340 {
3341 context->handleError(Error(GL_INVALID_VALUE));
3342 return false;
3343 }
3344
Martin Radev4c4c8e72016-08-04 12:25:34 +03003345 return true;
3346}
3347
Geoff Langc339c4e2016-11-29 10:37:36 -05003348bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003349{
Geoff Langc339c4e2016-11-29 10:37:36 -05003350 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003351 {
3352 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003353 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003354 return false;
3355 }
3356
3357 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3358 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003359 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003360 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003361 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003362 return false;
3363 }
3364
3365 return true;
3366}
3367
Jamie Madillef300b12016-10-07 15:12:09 -04003368bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3369{
3370 if (texture < GL_TEXTURE0 ||
3371 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3372 {
3373 context->handleError(Error(GL_INVALID_ENUM));
3374 return false;
3375 }
3376
3377 return true;
3378}
3379
3380bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3381{
3382 Program *programObject = GetValidProgram(context, program);
3383 if (!programObject)
3384 {
3385 return false;
3386 }
3387
3388 Shader *shaderObject = GetValidShader(context, shader);
3389 if (!shaderObject)
3390 {
3391 return false;
3392 }
3393
3394 switch (shaderObject->getType())
3395 {
3396 case GL_VERTEX_SHADER:
3397 {
3398 if (programObject->getAttachedVertexShader())
3399 {
3400 context->handleError(Error(GL_INVALID_OPERATION));
3401 return false;
3402 }
3403 break;
3404 }
3405 case GL_FRAGMENT_SHADER:
3406 {
3407 if (programObject->getAttachedFragmentShader())
3408 {
3409 context->handleError(Error(GL_INVALID_OPERATION));
3410 return false;
3411 }
3412 break;
3413 }
3414 case GL_COMPUTE_SHADER:
3415 {
3416 if (programObject->getAttachedComputeShader())
3417 {
3418 context->handleError(Error(GL_INVALID_OPERATION));
3419 return false;
3420 }
3421 break;
3422 }
3423 default:
3424 UNREACHABLE();
3425 break;
3426 }
3427
3428 return true;
3429}
3430
Jamie Madill01a80ee2016-11-07 12:06:18 -05003431bool ValidateBindAttribLocation(ValidationContext *context,
3432 GLuint program,
3433 GLuint index,
3434 const GLchar *name)
3435{
3436 if (index >= MAX_VERTEX_ATTRIBS)
3437 {
3438 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3439 return false;
3440 }
3441
3442 if (strncmp(name, "gl_", 3) == 0)
3443 {
3444 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3445 return false;
3446 }
3447
3448 return GetValidProgram(context, program) != nullptr;
3449}
3450
3451bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3452{
3453 if (!ValidBufferTarget(context, target))
3454 {
3455 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3456 return false;
3457 }
3458
3459 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3460 !context->isBufferGenerated(buffer))
3461 {
3462 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3463 return false;
3464 }
3465
3466 return true;
3467}
3468
3469bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3470{
3471 if (!ValidFramebufferTarget(target))
3472 {
3473 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3474 return false;
3475 }
3476
3477 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3478 !context->isFramebufferGenerated(framebuffer))
3479 {
3480 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3481 return false;
3482 }
3483
3484 return true;
3485}
3486
3487bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3488{
3489 if (target != GL_RENDERBUFFER)
3490 {
3491 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3492 return false;
3493 }
3494
3495 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3496 !context->isRenderbufferGenerated(renderbuffer))
3497 {
3498 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3499 return false;
3500 }
3501
3502 return true;
3503}
3504
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003505static bool ValidBlendEquationMode(GLenum mode)
3506{
3507 switch (mode)
3508 {
3509 case GL_FUNC_ADD:
3510 case GL_FUNC_SUBTRACT:
3511 case GL_FUNC_REVERSE_SUBTRACT:
3512 case GL_MIN:
3513 case GL_MAX:
3514 return true;
3515
3516 default:
3517 return false;
3518 }
3519}
3520
Jamie Madillc1d770e2017-04-13 17:31:24 -04003521bool ValidateBlendColor(ValidationContext *context,
3522 GLclampf red,
3523 GLclampf green,
3524 GLclampf blue,
3525 GLclampf alpha)
3526{
3527 return true;
3528}
3529
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003530bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3531{
3532 if (!ValidBlendEquationMode(mode))
3533 {
3534 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3535 return false;
3536 }
3537
3538 return true;
3539}
3540
3541bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3542{
3543 if (!ValidBlendEquationMode(modeRGB))
3544 {
3545 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3546 return false;
3547 }
3548
3549 if (!ValidBlendEquationMode(modeAlpha))
3550 {
3551 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3552 return false;
3553 }
3554
3555 return true;
3556}
3557
3558bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3559{
3560 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3561}
3562
3563static bool ValidSrcBlendFunc(GLenum srcBlend)
3564{
3565 switch (srcBlend)
3566 {
3567 case GL_ZERO:
3568 case GL_ONE:
3569 case GL_SRC_COLOR:
3570 case GL_ONE_MINUS_SRC_COLOR:
3571 case GL_DST_COLOR:
3572 case GL_ONE_MINUS_DST_COLOR:
3573 case GL_SRC_ALPHA:
3574 case GL_ONE_MINUS_SRC_ALPHA:
3575 case GL_DST_ALPHA:
3576 case GL_ONE_MINUS_DST_ALPHA:
3577 case GL_CONSTANT_COLOR:
3578 case GL_ONE_MINUS_CONSTANT_COLOR:
3579 case GL_CONSTANT_ALPHA:
3580 case GL_ONE_MINUS_CONSTANT_ALPHA:
3581 case GL_SRC_ALPHA_SATURATE:
3582 return true;
3583
3584 default:
3585 return false;
3586 }
3587}
3588
3589static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3590{
3591 switch (dstBlend)
3592 {
3593 case GL_ZERO:
3594 case GL_ONE:
3595 case GL_SRC_COLOR:
3596 case GL_ONE_MINUS_SRC_COLOR:
3597 case GL_DST_COLOR:
3598 case GL_ONE_MINUS_DST_COLOR:
3599 case GL_SRC_ALPHA:
3600 case GL_ONE_MINUS_SRC_ALPHA:
3601 case GL_DST_ALPHA:
3602 case GL_ONE_MINUS_DST_ALPHA:
3603 case GL_CONSTANT_COLOR:
3604 case GL_ONE_MINUS_CONSTANT_COLOR:
3605 case GL_CONSTANT_ALPHA:
3606 case GL_ONE_MINUS_CONSTANT_ALPHA:
3607 return true;
3608
3609 case GL_SRC_ALPHA_SATURATE:
3610 return (contextMajorVersion >= 3);
3611
3612 default:
3613 return false;
3614 }
3615}
3616
3617bool ValidateBlendFuncSeparate(ValidationContext *context,
3618 GLenum srcRGB,
3619 GLenum dstRGB,
3620 GLenum srcAlpha,
3621 GLenum dstAlpha)
3622{
3623 if (!ValidSrcBlendFunc(srcRGB))
3624 {
3625 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3626 return false;
3627 }
3628
3629 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3630 {
3631 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3632 return false;
3633 }
3634
3635 if (!ValidSrcBlendFunc(srcAlpha))
3636 {
3637 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3638 return false;
3639 }
3640
3641 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3642 {
3643 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3644 return false;
3645 }
3646
Frank Henigman146e8a12017-03-02 23:22:37 -05003647 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3648 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003649 {
3650 bool constantColorUsed =
3651 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3652 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3653
3654 bool constantAlphaUsed =
3655 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3656 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3657
3658 if (constantColorUsed && constantAlphaUsed)
3659 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003660 const char *msg;
3661 if (context->getExtensions().webglCompatibility)
3662 {
3663 msg =
3664 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3665 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3666 }
3667 else
3668 {
3669 msg =
3670 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3671 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3672 "implementation.";
3673 ERR() << msg;
3674 }
3675 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003676 return false;
3677 }
3678 }
3679
3680 return true;
3681}
3682
Geoff Langc339c4e2016-11-29 10:37:36 -05003683bool ValidateGetString(Context *context, GLenum name)
3684{
3685 switch (name)
3686 {
3687 case GL_VENDOR:
3688 case GL_RENDERER:
3689 case GL_VERSION:
3690 case GL_SHADING_LANGUAGE_VERSION:
3691 case GL_EXTENSIONS:
3692 break;
3693
3694 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3695 if (!context->getExtensions().requestExtension)
3696 {
3697 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3698 return false;
3699 }
3700 break;
3701
3702 default:
3703 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3704 return false;
3705 }
3706
3707 return true;
3708}
3709
Geoff Lang47c48082016-12-07 15:38:13 -05003710bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3711{
3712 if (width <= 0.0f || isNaN(width))
3713 {
3714 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3715 return false;
3716 }
3717
3718 return true;
3719}
3720
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003721bool ValidateVertexAttribPointer(ValidationContext *context,
3722 GLuint index,
3723 GLint size,
3724 GLenum type,
3725 GLboolean normalized,
3726 GLsizei stride,
3727 const GLvoid *ptr)
3728{
Shao80957d92017-02-20 21:25:59 +08003729 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003730 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003731 return false;
3732 }
3733
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003734 if (stride < 0)
3735 {
Shao80957d92017-02-20 21:25:59 +08003736 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003737 return false;
3738 }
3739
Shao80957d92017-02-20 21:25:59 +08003740 const Caps &caps = context->getCaps();
3741 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003742 {
Shao80957d92017-02-20 21:25:59 +08003743 if (stride > caps.maxVertexAttribStride)
3744 {
3745 context->handleError(
3746 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
3747 return false;
3748 }
3749
3750 if (index >= caps.maxVertexAttribBindings)
3751 {
3752 context->handleError(
3753 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
3754 return false;
3755 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003756 }
3757
3758 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3759 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3760 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3761 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003762 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3763 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08003764 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003765 {
3766 context->handleError(
3767 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08003768 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003769 return false;
3770 }
3771
3772 if (context->getExtensions().webglCompatibility)
3773 {
3774 // WebGL 1.0 [Section 6.14] Fixed point support
3775 // The WebGL API does not support the GL_FIXED data type.
3776 if (type == GL_FIXED)
3777 {
3778 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3779 return false;
3780 }
3781
Geoff Lang2d62ab72017-03-23 16:54:40 -04003782 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003783 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003784 return false;
3785 }
3786 }
3787
3788 return true;
3789}
3790
Frank Henigman6137ddc2017-02-10 18:55:07 -05003791bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
3792{
3793 if (context->getExtensions().webglCompatibility && zNear > zFar)
3794 {
3795 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
3796 return false;
3797 }
3798
3799 return true;
3800}
3801
Jamie Madille8fb6402017-02-14 17:56:40 -05003802bool ValidateRenderbufferStorage(ValidationContext *context,
3803 GLenum target,
3804 GLenum internalformat,
3805 GLsizei width,
3806 GLsizei height)
3807{
3808 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
3809 height);
3810}
3811
3812bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
3813 GLenum target,
3814 GLsizei samples,
3815 GLenum internalformat,
3816 GLsizei width,
3817 GLsizei height)
3818{
3819 if (!context->getExtensions().framebufferMultisample)
3820 {
3821 context->handleError(
3822 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
3823 return false;
3824 }
3825
3826 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
3827 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
3828 // generated.
3829 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
3830 {
3831 context->handleError(Error(GL_INVALID_VALUE));
3832 return false;
3833 }
3834
3835 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
3836 // the specified storage. This is different than ES 3.0 in which a sample number higher
3837 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
3838 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
3839 if (context->getClientMajorVersion() >= 3)
3840 {
3841 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3842 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3843 {
3844 context->handleError(Error(GL_OUT_OF_MEMORY));
3845 return false;
3846 }
3847 }
3848
3849 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
3850 width, height);
3851}
3852
Jamie Madillc1d770e2017-04-13 17:31:24 -04003853bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
3854{
3855 if (!ValidFramebufferTarget(target))
3856 {
3857 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3858 return false;
3859 }
3860
3861 return true;
3862}
3863
3864bool ValidateClearColor(ValidationContext *context,
3865 GLclampf red,
3866 GLclampf green,
3867 GLclampf blue,
3868 GLclampf alpha)
3869{
3870 return true;
3871}
3872
3873bool ValidateClearDepthf(ValidationContext *context, GLclampf depth)
3874{
3875 return true;
3876}
3877
3878bool ValidateClearStencil(ValidationContext *context, GLint s)
3879{
3880 return true;
3881}
3882
3883bool ValidateColorMask(ValidationContext *context,
3884 GLboolean red,
3885 GLboolean green,
3886 GLboolean blue,
3887 GLboolean alpha)
3888{
3889 return true;
3890}
3891
3892bool ValidateCompileShader(ValidationContext *context, GLuint shader)
3893{
3894 return true;
3895}
3896
3897bool ValidateCreateProgram(ValidationContext *context)
3898{
3899 return true;
3900}
3901
3902bool ValidateCullFace(ValidationContext *context, GLenum mode)
3903{
3904 switch (mode)
3905 {
3906 case GL_FRONT:
3907 case GL_BACK:
3908 case GL_FRONT_AND_BACK:
3909 break;
3910
3911 default:
3912 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
3913 return false;
3914 }
3915
3916 return true;
3917}
3918
3919bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
3920{
3921 if (program == 0)
3922 {
3923 return false;
3924 }
3925
3926 if (!context->getProgram(program))
3927 {
3928 if (context->getShader(program))
3929 {
3930 context->handleError(
3931 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
3932 return false;
3933 }
3934 else
3935 {
3936 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
3937 return false;
3938 }
3939 }
3940
3941 return true;
3942}
3943
3944bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
3945{
3946 if (shader == 0)
3947 {
3948 return false;
3949 }
3950
3951 if (!context->getShader(shader))
3952 {
3953 if (context->getProgram(shader))
3954 {
3955 context->handleError(
3956 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
3957 return false;
3958 }
3959 else
3960 {
3961 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
3962 return false;
3963 }
3964 }
3965
3966 return true;
3967}
3968
3969bool ValidateDepthFunc(ValidationContext *context, GLenum func)
3970{
3971 switch (func)
3972 {
3973 case GL_NEVER:
3974 case GL_ALWAYS:
3975 case GL_LESS:
3976 case GL_LEQUAL:
3977 case GL_EQUAL:
3978 case GL_GREATER:
3979 case GL_GEQUAL:
3980 case GL_NOTEQUAL:
3981 break;
3982
3983 default:
3984 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
3985 return false;
3986 }
3987
3988 return true;
3989}
3990
3991bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
3992{
3993 return true;
3994}
3995
3996bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
3997{
3998 Program *programObject = GetValidProgram(context, program);
3999 if (!programObject)
4000 {
4001 return false;
4002 }
4003
4004 Shader *shaderObject = GetValidShader(context, shader);
4005 if (!shaderObject)
4006 {
4007 return false;
4008 }
4009
4010 const Shader *attachedShader = nullptr;
4011
4012 switch (shaderObject->getType())
4013 {
4014 case GL_VERTEX_SHADER:
4015 {
4016 attachedShader = programObject->getAttachedVertexShader();
4017 break;
4018 }
4019 case GL_FRAGMENT_SHADER:
4020 {
4021 attachedShader = programObject->getAttachedFragmentShader();
4022 break;
4023 }
4024 case GL_COMPUTE_SHADER:
4025 {
4026 attachedShader = programObject->getAttachedComputeShader();
4027 break;
4028 }
4029 default:
4030 UNREACHABLE();
4031 return false;
4032 }
4033
4034 if (attachedShader != shaderObject)
4035 {
4036 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4037 return false;
4038 }
4039
4040 return true;
4041}
4042
4043bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4044{
4045 if (index >= MAX_VERTEX_ATTRIBS)
4046 {
4047 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4048 return false;
4049 }
4050
4051 return true;
4052}
4053
4054bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4055{
4056 if (index >= MAX_VERTEX_ATTRIBS)
4057 {
4058 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4059 return false;
4060 }
4061
4062 return true;
4063}
4064
4065bool ValidateFinish(ValidationContext *context)
4066{
4067 return true;
4068}
4069
4070bool ValidateFlush(ValidationContext *context)
4071{
4072 return true;
4073}
4074
4075bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4076{
4077 switch (mode)
4078 {
4079 case GL_CW:
4080 case GL_CCW:
4081 break;
4082 default:
4083 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4084 return false;
4085 }
4086
4087 return true;
4088}
4089
4090bool ValidateGetActiveAttrib(ValidationContext *context,
4091 GLuint program,
4092 GLuint index,
4093 GLsizei bufsize,
4094 GLsizei *length,
4095 GLint *size,
4096 GLenum *type,
4097 GLchar *name)
4098{
4099 if (bufsize < 0)
4100 {
4101 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4102 return false;
4103 }
4104
4105 Program *programObject = GetValidProgram(context, program);
4106
4107 if (!programObject)
4108 {
4109 return false;
4110 }
4111
4112 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4113 {
4114 context->handleError(
4115 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4116 return false;
4117 }
4118
4119 return true;
4120}
4121
4122bool ValidateGetActiveUniform(ValidationContext *context,
4123 GLuint program,
4124 GLuint index,
4125 GLsizei bufsize,
4126 GLsizei *length,
4127 GLint *size,
4128 GLenum *type,
4129 GLchar *name)
4130{
4131 if (bufsize < 0)
4132 {
4133 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4134 return false;
4135 }
4136
4137 Program *programObject = GetValidProgram(context, program);
4138
4139 if (!programObject)
4140 {
4141 return false;
4142 }
4143
4144 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4145 {
4146 context->handleError(
4147 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4148 return false;
4149 }
4150
4151 return true;
4152}
4153
4154bool ValidateGetAttachedShaders(ValidationContext *context,
4155 GLuint program,
4156 GLsizei maxcount,
4157 GLsizei *count,
4158 GLuint *shaders)
4159{
4160 if (maxcount < 0)
4161 {
4162 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4163 return false;
4164 }
4165
4166 Program *programObject = GetValidProgram(context, program);
4167
4168 if (!programObject)
4169 {
4170 return false;
4171 }
4172
4173 return true;
4174}
4175
4176bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4177{
4178 Program *programObject = GetValidProgram(context, program);
4179
4180 if (!programObject)
4181 {
4182 return false;
4183 }
4184
4185 if (!programObject->isLinked())
4186 {
4187 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4188 return false;
4189 }
4190
4191 return true;
4192}
4193
4194bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4195{
4196 GLenum nativeType;
4197 unsigned int numParams = 0;
4198 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4199}
4200
4201bool ValidateGetError(ValidationContext *context)
4202{
4203 return true;
4204}
4205
4206bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4207{
4208 GLenum nativeType;
4209 unsigned int numParams = 0;
4210 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4211}
4212
4213bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4214{
4215 GLenum nativeType;
4216 unsigned int numParams = 0;
4217 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4218}
4219
4220bool ValidateGetProgramInfoLog(ValidationContext *context,
4221 GLuint program,
4222 GLsizei bufsize,
4223 GLsizei *length,
4224 GLchar *infolog)
4225{
4226 if (bufsize < 0)
4227 {
4228 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4229 return false;
4230 }
4231
4232 Program *programObject = GetValidProgram(context, program);
4233 if (!programObject)
4234 {
4235 return false;
4236 }
4237
4238 return true;
4239}
4240
4241bool ValidateGetShaderInfoLog(ValidationContext *context,
4242 GLuint shader,
4243 GLsizei bufsize,
4244 GLsizei *length,
4245 GLchar *infolog)
4246{
4247 if (bufsize < 0)
4248 {
4249 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4250 return false;
4251 }
4252
4253 Shader *shaderObject = GetValidShader(context, shader);
4254 if (!shaderObject)
4255 {
4256 return false;
4257 }
4258
4259 return true;
4260}
4261
4262bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4263 GLenum shadertype,
4264 GLenum precisiontype,
4265 GLint *range,
4266 GLint *precision)
4267{
4268 switch (shadertype)
4269 {
4270 case GL_VERTEX_SHADER:
4271 case GL_FRAGMENT_SHADER:
4272 break;
4273 case GL_COMPUTE_SHADER:
4274 context->handleError(
4275 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4276 return false;
4277 default:
4278 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4279 return false;
4280 }
4281
4282 switch (precisiontype)
4283 {
4284 case GL_LOW_FLOAT:
4285 case GL_MEDIUM_FLOAT:
4286 case GL_HIGH_FLOAT:
4287 case GL_LOW_INT:
4288 case GL_MEDIUM_INT:
4289 case GL_HIGH_INT:
4290 break;
4291
4292 default:
4293 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4294 return false;
4295 }
4296
4297 return true;
4298}
4299
4300bool ValidateGetShaderSource(ValidationContext *context,
4301 GLuint shader,
4302 GLsizei bufsize,
4303 GLsizei *length,
4304 GLchar *source)
4305{
4306 if (bufsize < 0)
4307 {
4308 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4309 return false;
4310 }
4311
4312 Shader *shaderObject = GetValidShader(context, shader);
4313 if (!shaderObject)
4314 {
4315 return false;
4316 }
4317
4318 return true;
4319}
4320
4321bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4322{
4323 if (strstr(name, "gl_") == name)
4324 {
4325 return false;
4326 }
4327
4328 Program *programObject = GetValidProgram(context, program);
4329
4330 if (!programObject)
4331 {
4332 return false;
4333 }
4334
4335 if (!programObject->isLinked())
4336 {
4337 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4338 return false;
4339 }
4340
4341 return true;
4342}
4343
4344bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4345{
4346 switch (mode)
4347 {
4348 case GL_FASTEST:
4349 case GL_NICEST:
4350 case GL_DONT_CARE:
4351 break;
4352
4353 default:
4354 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4355 return false;
4356 }
4357
4358 switch (target)
4359 {
4360 case GL_GENERATE_MIPMAP_HINT:
4361 break;
4362
4363 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4364 if (!context->getExtensions().standardDerivatives)
4365 {
4366 context->handleError(
4367 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4368 return false;
4369 }
4370 break;
4371
4372 default:
4373 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4374 return false;
4375 }
4376
4377 return true;
4378}
4379
4380bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4381{
4382 return true;
4383}
4384
4385bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4386{
4387 return true;
4388}
4389
4390bool ValidateIsProgram(ValidationContext *context, GLuint program)
4391{
4392 return true;
4393}
4394
4395bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4396{
4397 return true;
4398}
4399
4400bool ValidateIsShader(ValidationContext *context, GLuint shader)
4401{
4402 return true;
4403}
4404
4405bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4406{
4407 return true;
4408}
4409
4410bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4411{
4412 if (context->getClientMajorVersion() < 3)
4413 {
4414 switch (pname)
4415 {
4416 case GL_UNPACK_IMAGE_HEIGHT:
4417 case GL_UNPACK_SKIP_IMAGES:
4418 context->handleError(Error(GL_INVALID_ENUM));
4419 return false;
4420
4421 case GL_UNPACK_ROW_LENGTH:
4422 case GL_UNPACK_SKIP_ROWS:
4423 case GL_UNPACK_SKIP_PIXELS:
4424 if (!context->getExtensions().unpackSubimage)
4425 {
4426 context->handleError(Error(GL_INVALID_ENUM));
4427 return false;
4428 }
4429 break;
4430
4431 case GL_PACK_ROW_LENGTH:
4432 case GL_PACK_SKIP_ROWS:
4433 case GL_PACK_SKIP_PIXELS:
4434 if (!context->getExtensions().packSubimage)
4435 {
4436 context->handleError(Error(GL_INVALID_ENUM));
4437 return false;
4438 }
4439 break;
4440 }
4441 }
4442
4443 if (param < 0)
4444 {
4445 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4446 return false;
4447 }
4448
4449 switch (pname)
4450 {
4451 case GL_UNPACK_ALIGNMENT:
4452 if (param != 1 && param != 2 && param != 4 && param != 8)
4453 {
4454 context->handleError(Error(GL_INVALID_VALUE));
4455 return false;
4456 }
4457 break;
4458
4459 case GL_PACK_ALIGNMENT:
4460 if (param != 1 && param != 2 && param != 4 && param != 8)
4461 {
4462 context->handleError(Error(GL_INVALID_VALUE));
4463 return false;
4464 }
4465 break;
4466
4467 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4468 case GL_UNPACK_ROW_LENGTH:
4469 case GL_UNPACK_IMAGE_HEIGHT:
4470 case GL_UNPACK_SKIP_IMAGES:
4471 case GL_UNPACK_SKIP_ROWS:
4472 case GL_UNPACK_SKIP_PIXELS:
4473 case GL_PACK_ROW_LENGTH:
4474 case GL_PACK_SKIP_ROWS:
4475 case GL_PACK_SKIP_PIXELS:
4476 break;
4477
4478 default:
4479 context->handleError(Error(GL_INVALID_ENUM));
4480 return false;
4481 }
4482
4483 return true;
4484}
4485
4486bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4487{
4488 return true;
4489}
4490
4491bool ValidateReleaseShaderCompiler(ValidationContext *context)
4492{
4493 return true;
4494}
4495
4496bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert)
4497{
4498 return true;
4499}
4500
4501bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4502{
4503 if (width < 0 || height < 0)
4504 {
4505 context->handleError(
4506 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4507 return false;
4508 }
4509
4510 return true;
4511}
4512
4513bool ValidateShaderBinary(ValidationContext *context,
4514 GLsizei n,
4515 const GLuint *shaders,
4516 GLenum binaryformat,
4517 const GLvoid *binary,
4518 GLsizei length)
4519{
4520 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4521 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4522 shaderBinaryFormats.end())
4523 {
4524 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4525 return false;
4526 }
4527
4528 return true;
4529}
4530
4531bool ValidateShaderSource(ValidationContext *context,
4532 GLuint shader,
4533 GLsizei count,
4534 const GLchar *const *string,
4535 const GLint *length)
4536{
4537 if (count < 0)
4538 {
4539 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4540 return false;
4541 }
4542
4543 Shader *shaderObject = GetValidShader(context, shader);
4544 if (!shaderObject)
4545 {
4546 return false;
4547 }
4548
4549 return true;
4550}
4551
4552bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4553{
4554 if (!IsValidStencilFunc(func))
4555 {
4556 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4557 return false;
4558 }
4559
4560 return true;
4561}
4562
4563bool ValidateStencilFuncSeparate(ValidationContext *context,
4564 GLenum face,
4565 GLenum func,
4566 GLint ref,
4567 GLuint mask)
4568{
4569 if (!IsValidStencilFace(face))
4570 {
4571 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4572 return false;
4573 }
4574
4575 if (!IsValidStencilFunc(func))
4576 {
4577 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4578 return false;
4579 }
4580
4581 return true;
4582}
4583
4584bool ValidateStencilMask(ValidationContext *context, GLuint mask)
4585{
4586 return true;
4587}
4588
4589bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
4590{
4591 if (!IsValidStencilFace(face))
4592 {
4593 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4594 return false;
4595 }
4596
4597 return true;
4598}
4599
4600bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
4601{
4602 if (!IsValidStencilOp(fail))
4603 {
4604 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
4605 return false;
4606 }
4607
4608 if (!IsValidStencilOp(zfail))
4609 {
4610 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
4611 return false;
4612 }
4613
4614 if (!IsValidStencilOp(zpass))
4615 {
4616 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
4617 return false;
4618 }
4619
4620 return true;
4621}
4622
4623bool ValidateStencilOpSeparate(ValidationContext *context,
4624 GLenum face,
4625 GLenum fail,
4626 GLenum zfail,
4627 GLenum zpass)
4628{
4629 if (!IsValidStencilFace(face))
4630 {
4631 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4632 return false;
4633 }
4634
4635 return ValidateStencilOp(context, fail, zfail, zpass);
4636}
4637
4638bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
4639{
4640 return ValidateUniform(context, GL_FLOAT, location, 1);
4641}
4642
4643bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4644{
4645 return ValidateUniform(context, GL_FLOAT, location, count);
4646}
4647
4648bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
4649{
4650 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
4651}
4652
4653bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4654{
4655 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
4656}
4657
4658bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
4659{
4660 return ValidateUniform(context, GL_INT_VEC2, location, 1);
4661}
4662
4663bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4664{
4665 return ValidateUniform(context, GL_INT_VEC2, location, count);
4666}
4667
4668bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
4669{
4670 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
4671}
4672
4673bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4674{
4675 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
4676}
4677
4678bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
4679{
4680 return ValidateUniform(context, GL_INT_VEC3, location, 1);
4681}
4682
4683bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4684{
4685 return ValidateUniform(context, GL_INT_VEC3, location, count);
4686}
4687
4688bool ValidateUniform4f(ValidationContext *context,
4689 GLint location,
4690 GLfloat x,
4691 GLfloat y,
4692 GLfloat z,
4693 GLfloat w)
4694{
4695 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
4696}
4697
4698bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4699{
4700 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
4701}
4702
4703bool ValidateUniform4i(ValidationContext *context,
4704 GLint location,
4705 GLint x,
4706 GLint y,
4707 GLint z,
4708 GLint w)
4709{
4710 return ValidateUniform(context, GL_INT_VEC4, location, 1);
4711}
4712
4713bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4714{
4715 return ValidateUniform(context, GL_INT_VEC4, location, count);
4716}
4717
4718bool ValidateUniformMatrix2fv(ValidationContext *context,
4719 GLint location,
4720 GLsizei count,
4721 GLboolean transpose,
4722 const GLfloat *value)
4723{
4724 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
4725}
4726
4727bool ValidateUniformMatrix3fv(ValidationContext *context,
4728 GLint location,
4729 GLsizei count,
4730 GLboolean transpose,
4731 const GLfloat *value)
4732{
4733 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
4734}
4735
4736bool ValidateUniformMatrix4fv(ValidationContext *context,
4737 GLint location,
4738 GLsizei count,
4739 GLboolean transpose,
4740 const GLfloat *value)
4741{
4742 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
4743}
4744
4745bool ValidateValidateProgram(ValidationContext *context, GLuint program)
4746{
4747 Program *programObject = GetValidProgram(context, program);
4748
4749 if (!programObject)
4750 {
4751 return false;
4752 }
4753
4754 return true;
4755}
4756
4757bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
4758{
4759 if (index >= MAX_VERTEX_ATTRIBS)
4760 {
4761 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
4762 return false;
4763 }
4764
4765 return true;
4766}
4767
4768bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
4769{
4770 return ValidateVertexAttribIndex(context, index);
4771}
4772
4773bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
4774{
4775 return ValidateVertexAttribIndex(context, index);
4776}
4777
4778bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
4779{
4780 return ValidateVertexAttribIndex(context, index);
4781}
4782
4783bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
4784{
4785 return ValidateVertexAttribIndex(context, index);
4786}
4787
4788bool ValidateVertexAttrib3f(ValidationContext *context,
4789 GLuint index,
4790 GLfloat x,
4791 GLfloat y,
4792 GLfloat z)
4793{
4794 return ValidateVertexAttribIndex(context, index);
4795}
4796
4797bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
4798{
4799 return ValidateVertexAttribIndex(context, index);
4800}
4801
4802bool ValidateVertexAttrib4f(ValidationContext *context,
4803 GLuint index,
4804 GLfloat x,
4805 GLfloat y,
4806 GLfloat z,
4807 GLfloat w)
4808{
4809 return ValidateVertexAttribIndex(context, index);
4810}
4811
4812bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
4813{
4814 return ValidateVertexAttribIndex(context, index);
4815}
4816
4817bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4818{
4819 if (width < 0 || height < 0)
4820 {
4821 context->handleError(
4822 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
4823 return false;
4824 }
4825
4826 return true;
4827}
4828
4829bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
4830{
4831 return ValidateDrawArraysCommon(context, mode, first, count, 1);
4832}
4833
Jamie Madillc29968b2016-01-20 11:17:23 -05004834} // namespace gl