blob: f13a596ac6a900708f66708affa76a34824c9e49 [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
Corentin Wallezb2931602017-04-11 15:58:57 -04001918bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
1919 GLenum target,
1920 GLint level,
1921 GLenum internalformat,
1922 GLsizei width,
1923 GLsizei height,
1924 GLint border,
1925 GLsizei imageSize,
1926 GLsizei dataSize,
1927 const GLvoid *data)
1928{
1929 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1930 {
1931 return false;
1932 }
1933
1934 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
1935 border, imageSize, data);
1936}
1937bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
1938 GLenum target,
1939 GLint level,
1940 GLint xoffset,
1941 GLint yoffset,
1942 GLsizei width,
1943 GLsizei height,
1944 GLenum format,
1945 GLsizei imageSize,
1946 GLsizei dataSize,
1947 const GLvoid *data)
1948{
1949 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1950 {
1951 return false;
1952 }
1953
1954 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
1955 format, imageSize, data);
1956}
1957
Jamie Madill73a84962016-02-12 09:27:23 -05001958bool ValidateCompressedTexSubImage2D(Context *context,
1959 GLenum target,
1960 GLint level,
1961 GLint xoffset,
1962 GLint yoffset,
1963 GLsizei width,
1964 GLsizei height,
1965 GLenum format,
1966 GLsizei imageSize,
1967 const GLvoid *data)
1968{
Martin Radev1be913c2016-07-11 17:59:16 +03001969 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001970 {
1971 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001972 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001973 {
1974 return false;
1975 }
1976 }
1977 else
1978 {
Martin Radev1be913c2016-07-11 17:59:16 +03001979 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001980 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001981 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001982 data))
1983 {
1984 return false;
1985 }
1986 }
1987
1988 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001989 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001990 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001991 if (blockSizeOrErr.isError())
1992 {
1993 context->handleError(blockSizeOrErr.getError());
1994 return false;
1995 }
1996
1997 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002000 return false;
2001 }
2002
2003 return true;
2004}
2005
Olli Etuaho4f667482016-03-30 15:56:35 +03002006bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2007{
Geoff Lang496c02d2016-10-20 11:38:11 -07002008 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002009}
2010
2011bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2012{
2013 if (!context->getExtensions().mapBuffer)
2014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002016 return false;
2017 }
2018
2019 if (!ValidBufferTarget(context, target))
2020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002022 return false;
2023 }
2024
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002025 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002026
2027 if (buffer == nullptr)
2028 {
Jamie Madill437fa652016-05-03 15:13:24 -04002029 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002030 return false;
2031 }
2032
2033 if (access != GL_WRITE_ONLY_OES)
2034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002036 return false;
2037 }
2038
2039 if (buffer->isMapped())
2040 {
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002042 return false;
2043 }
2044
2045 return true;
2046}
2047
2048bool ValidateUnmapBufferOES(Context *context, GLenum target)
2049{
2050 if (!context->getExtensions().mapBuffer)
2051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002053 return false;
2054 }
2055
2056 return ValidateUnmapBufferBase(context, target);
2057}
2058
2059bool ValidateMapBufferRangeEXT(Context *context,
2060 GLenum target,
2061 GLintptr offset,
2062 GLsizeiptr length,
2063 GLbitfield access)
2064{
2065 if (!context->getExtensions().mapBufferRange)
2066 {
Jamie Madill437fa652016-05-03 15:13:24 -04002067 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002068 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2069 return false;
2070 }
2071
2072 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2073}
2074
2075bool ValidateFlushMappedBufferRangeEXT(Context *context,
2076 GLenum target,
2077 GLintptr offset,
2078 GLsizeiptr length)
2079{
2080 if (!context->getExtensions().mapBufferRange)
2081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002083 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2084 return false;
2085 }
2086
2087 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2088}
2089
Ian Ewell54f87462016-03-10 13:47:21 -05002090bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2091{
2092 Texture *textureObject = context->getTexture(texture);
2093 if (textureObject && textureObject->getTarget() != target && texture != 0)
2094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002096 return false;
2097 }
2098
Geoff Langf41a7152016-09-19 15:11:17 -04002099 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2100 !context->isTextureGenerated(texture))
2101 {
2102 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2103 return false;
2104 }
2105
Ian Ewell54f87462016-03-10 13:47:21 -05002106 switch (target)
2107 {
2108 case GL_TEXTURE_2D:
2109 case GL_TEXTURE_CUBE_MAP:
2110 break;
2111
2112 case GL_TEXTURE_3D:
2113 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002114 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002115 {
Jamie Madill437fa652016-05-03 15:13:24 -04002116 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002117 return false;
2118 }
2119 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002120
2121 case GL_TEXTURE_2D_MULTISAMPLE:
2122 if (context->getClientVersion() < Version(3, 1))
2123 {
2124 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2125 return false;
2126 }
Geoff Lang3b573612016-10-31 14:08:10 -04002127 break;
2128
Ian Ewell54f87462016-03-10 13:47:21 -05002129 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002130 if (!context->getExtensions().eglImageExternal &&
2131 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002132 {
Jamie Madill437fa652016-05-03 15:13:24 -04002133 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002134 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2135 return false;
2136 }
2137 break;
2138 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002139 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002140 return false;
2141 }
2142
2143 return true;
2144}
2145
Geoff Langd8605522016-04-13 10:19:12 -04002146bool ValidateBindUniformLocationCHROMIUM(Context *context,
2147 GLuint program,
2148 GLint location,
2149 const GLchar *name)
2150{
2151 if (!context->getExtensions().bindUniformLocation)
2152 {
Jamie Madill437fa652016-05-03 15:13:24 -04002153 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002154 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2155 return false;
2156 }
2157
2158 Program *programObject = GetValidProgram(context, program);
2159 if (!programObject)
2160 {
2161 return false;
2162 }
2163
2164 if (location < 0)
2165 {
Jamie Madill437fa652016-05-03 15:13:24 -04002166 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002167 return false;
2168 }
2169
2170 const Caps &caps = context->getCaps();
2171 if (static_cast<size_t>(location) >=
2172 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2173 {
Jamie Madill437fa652016-05-03 15:13:24 -04002174 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002175 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2176 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2177 return false;
2178 }
2179
2180 if (strncmp(name, "gl_", 3) == 0)
2181 {
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002183 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2184 return false;
2185 }
2186
2187 return true;
2188}
2189
Jamie Madille2e406c2016-06-02 13:04:10 -04002190bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002191{
2192 if (!context->getExtensions().framebufferMixedSamples)
2193 {
2194 context->handleError(
2195 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2196 return false;
2197 }
2198 switch (components)
2199 {
2200 case GL_RGB:
2201 case GL_RGBA:
2202 case GL_ALPHA:
2203 case GL_NONE:
2204 break;
2205 default:
2206 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002207 Error(GL_INVALID_ENUM,
2208 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002209 return false;
2210 }
2211
2212 return true;
2213}
2214
Sami Väisänene45e53b2016-05-25 10:36:04 +03002215// CHROMIUM_path_rendering
2216
2217bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2218{
2219 if (!context->getExtensions().pathRendering)
2220 {
2221 context->handleError(
2222 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2223 return false;
2224 }
2225 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2226 {
2227 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2228 return false;
2229 }
2230 if (matrix == nullptr)
2231 {
2232 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2233 return false;
2234 }
2235 return true;
2236}
2237
2238bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2239{
2240 if (!context->getExtensions().pathRendering)
2241 {
2242 context->handleError(
2243 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2244 return false;
2245 }
2246 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2247 {
2248 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2249 return false;
2250 }
2251 return true;
2252}
2253
2254bool ValidateGenPaths(Context *context, GLsizei range)
2255{
2256 if (!context->getExtensions().pathRendering)
2257 {
2258 context->handleError(
2259 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2260 return false;
2261 }
2262
2263 // range = 0 is undefined in NV_path_rendering.
2264 // we add stricter semantic check here and require a non zero positive range.
2265 if (range <= 0)
2266 {
2267 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2268 return false;
2269 }
2270
2271 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2272 {
2273 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2274 return false;
2275 }
2276
2277 return true;
2278}
2279
2280bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2281{
2282 if (!context->getExtensions().pathRendering)
2283 {
2284 context->handleError(
2285 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2286 return false;
2287 }
2288
2289 // range = 0 is undefined in NV_path_rendering.
2290 // we add stricter semantic check here and require a non zero positive range.
2291 if (range <= 0)
2292 {
2293 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2294 return false;
2295 }
2296
2297 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2298 checkedRange += range;
2299
2300 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2301 {
2302 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2303 return false;
2304 }
2305 return true;
2306}
2307
2308bool ValidatePathCommands(Context *context,
2309 GLuint path,
2310 GLsizei numCommands,
2311 const GLubyte *commands,
2312 GLsizei numCoords,
2313 GLenum coordType,
2314 const void *coords)
2315{
2316 if (!context->getExtensions().pathRendering)
2317 {
2318 context->handleError(
2319 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2320 return false;
2321 }
2322 if (!context->hasPath(path))
2323 {
2324 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2325 return false;
2326 }
2327
2328 if (numCommands < 0)
2329 {
2330 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2331 return false;
2332 }
2333 else if (numCommands > 0)
2334 {
2335 if (!commands)
2336 {
2337 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2338 return false;
2339 }
2340 }
2341
2342 if (numCoords < 0)
2343 {
2344 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2345 return false;
2346 }
2347 else if (numCoords > 0)
2348 {
2349 if (!coords)
2350 {
2351 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2352 return false;
2353 }
2354 }
2355
2356 std::uint32_t coordTypeSize = 0;
2357 switch (coordType)
2358 {
2359 case GL_BYTE:
2360 coordTypeSize = sizeof(GLbyte);
2361 break;
2362
2363 case GL_UNSIGNED_BYTE:
2364 coordTypeSize = sizeof(GLubyte);
2365 break;
2366
2367 case GL_SHORT:
2368 coordTypeSize = sizeof(GLshort);
2369 break;
2370
2371 case GL_UNSIGNED_SHORT:
2372 coordTypeSize = sizeof(GLushort);
2373 break;
2374
2375 case GL_FLOAT:
2376 coordTypeSize = sizeof(GLfloat);
2377 break;
2378
2379 default:
2380 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2381 return false;
2382 }
2383
2384 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2385 checkedSize += (coordTypeSize * numCoords);
2386 if (!checkedSize.IsValid())
2387 {
2388 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2389 return false;
2390 }
2391
2392 // early return skips command data validation when it doesn't exist.
2393 if (!commands)
2394 return true;
2395
2396 GLsizei expectedNumCoords = 0;
2397 for (GLsizei i = 0; i < numCommands; ++i)
2398 {
2399 switch (commands[i])
2400 {
2401 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2402 break;
2403 case GL_MOVE_TO_CHROMIUM:
2404 case GL_LINE_TO_CHROMIUM:
2405 expectedNumCoords += 2;
2406 break;
2407 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2408 expectedNumCoords += 4;
2409 break;
2410 case GL_CUBIC_CURVE_TO_CHROMIUM:
2411 expectedNumCoords += 6;
2412 break;
2413 case GL_CONIC_CURVE_TO_CHROMIUM:
2414 expectedNumCoords += 5;
2415 break;
2416 default:
2417 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2418 return false;
2419 }
2420 }
2421 if (expectedNumCoords != numCoords)
2422 {
2423 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2424 return false;
2425 }
2426
2427 return true;
2428}
2429
2430bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2431{
2432 if (!context->getExtensions().pathRendering)
2433 {
2434 context->handleError(
2435 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2436 return false;
2437 }
2438 if (!context->hasPath(path))
2439 {
2440 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2441 return false;
2442 }
2443
2444 switch (pname)
2445 {
2446 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2447 if (value < 0.0f)
2448 {
2449 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2450 return false;
2451 }
2452 break;
2453 case GL_PATH_END_CAPS_CHROMIUM:
2454 switch (static_cast<GLenum>(value))
2455 {
2456 case GL_FLAT_CHROMIUM:
2457 case GL_SQUARE_CHROMIUM:
2458 case GL_ROUND_CHROMIUM:
2459 break;
2460 default:
2461 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2462 return false;
2463 }
2464 break;
2465 case GL_PATH_JOIN_STYLE_CHROMIUM:
2466 switch (static_cast<GLenum>(value))
2467 {
2468 case GL_MITER_REVERT_CHROMIUM:
2469 case GL_BEVEL_CHROMIUM:
2470 case GL_ROUND_CHROMIUM:
2471 break;
2472 default:
2473 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2474 return false;
2475 }
2476 case GL_PATH_MITER_LIMIT_CHROMIUM:
2477 if (value < 0.0f)
2478 {
2479 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2480 return false;
2481 }
2482 break;
2483
2484 case GL_PATH_STROKE_BOUND_CHROMIUM:
2485 // no errors, only clamping.
2486 break;
2487
2488 default:
2489 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2490 return false;
2491 }
2492 return true;
2493}
2494
2495bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2496{
2497 if (!context->getExtensions().pathRendering)
2498 {
2499 context->handleError(
2500 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2501 return false;
2502 }
2503
2504 if (!context->hasPath(path))
2505 {
2506 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2507 return false;
2508 }
2509 if (!value)
2510 {
2511 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2512 return false;
2513 }
2514
2515 switch (pname)
2516 {
2517 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2518 case GL_PATH_END_CAPS_CHROMIUM:
2519 case GL_PATH_JOIN_STYLE_CHROMIUM:
2520 case GL_PATH_MITER_LIMIT_CHROMIUM:
2521 case GL_PATH_STROKE_BOUND_CHROMIUM:
2522 break;
2523
2524 default:
2525 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2526 return false;
2527 }
2528
2529 return true;
2530}
2531
2532bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2533{
2534 if (!context->getExtensions().pathRendering)
2535 {
2536 context->handleError(
2537 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2538 return false;
2539 }
2540
2541 switch (func)
2542 {
2543 case GL_NEVER:
2544 case GL_ALWAYS:
2545 case GL_LESS:
2546 case GL_LEQUAL:
2547 case GL_EQUAL:
2548 case GL_GEQUAL:
2549 case GL_GREATER:
2550 case GL_NOTEQUAL:
2551 break;
2552 default:
2553 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2554 return false;
2555 }
2556
2557 return true;
2558}
2559
2560// Note that the spec specifies that for the path drawing commands
2561// if the path object is not an existing path object the command
2562// does nothing and no error is generated.
2563// However if the path object exists but has not been specified any
2564// commands then an error is generated.
2565
2566bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2567{
2568 if (!context->getExtensions().pathRendering)
2569 {
2570 context->handleError(
2571 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2572 return false;
2573 }
2574 if (context->hasPath(path) && !context->hasPathData(path))
2575 {
2576 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2577 return false;
2578 }
2579
2580 switch (fillMode)
2581 {
2582 case GL_COUNT_UP_CHROMIUM:
2583 case GL_COUNT_DOWN_CHROMIUM:
2584 break;
2585 default:
2586 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2587 return false;
2588 }
2589
2590 if (!isPow2(mask + 1))
2591 {
2592 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2593 return false;
2594 }
2595
2596 return true;
2597}
2598
2599bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2600{
2601 if (!context->getExtensions().pathRendering)
2602 {
2603 context->handleError(
2604 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2605 return false;
2606 }
2607 if (context->hasPath(path) && !context->hasPathData(path))
2608 {
2609 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2610 return false;
2611 }
2612
2613 return true;
2614}
2615
2616bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2617{
2618 if (!context->getExtensions().pathRendering)
2619 {
2620 context->handleError(
2621 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2622 return false;
2623 }
2624 if (context->hasPath(path) && !context->hasPathData(path))
2625 {
2626 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2627 return false;
2628 }
2629
2630 switch (coverMode)
2631 {
2632 case GL_CONVEX_HULL_CHROMIUM:
2633 case GL_BOUNDING_BOX_CHROMIUM:
2634 break;
2635 default:
2636 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2637 return false;
2638 }
2639 return true;
2640}
2641
2642bool ValidateStencilThenCoverFillPath(Context *context,
2643 GLuint path,
2644 GLenum fillMode,
2645 GLuint mask,
2646 GLenum coverMode)
2647{
2648 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2649 ValidateCoverPath(context, path, coverMode);
2650}
2651
2652bool ValidateStencilThenCoverStrokePath(Context *context,
2653 GLuint path,
2654 GLint reference,
2655 GLuint mask,
2656 GLenum coverMode)
2657{
2658 return ValidateStencilStrokePath(context, path, reference, mask) &&
2659 ValidateCoverPath(context, path, coverMode);
2660}
2661
2662bool ValidateIsPath(Context *context)
2663{
2664 if (!context->getExtensions().pathRendering)
2665 {
2666 context->handleError(
2667 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2668 return false;
2669 }
2670 return true;
2671}
2672
Sami Väisänend59ca052016-06-21 16:10:00 +03002673bool ValidateCoverFillPathInstanced(Context *context,
2674 GLsizei numPaths,
2675 GLenum pathNameType,
2676 const void *paths,
2677 GLuint pathBase,
2678 GLenum coverMode,
2679 GLenum transformType,
2680 const GLfloat *transformValues)
2681{
2682 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2683 transformType, transformValues))
2684 return false;
2685
2686 switch (coverMode)
2687 {
2688 case GL_CONVEX_HULL_CHROMIUM:
2689 case GL_BOUNDING_BOX_CHROMIUM:
2690 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2691 break;
2692 default:
2693 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2694 return false;
2695 }
2696
2697 return true;
2698}
2699
2700bool ValidateCoverStrokePathInstanced(Context *context,
2701 GLsizei numPaths,
2702 GLenum pathNameType,
2703 const void *paths,
2704 GLuint pathBase,
2705 GLenum coverMode,
2706 GLenum transformType,
2707 const GLfloat *transformValues)
2708{
2709 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2710 transformType, transformValues))
2711 return false;
2712
2713 switch (coverMode)
2714 {
2715 case GL_CONVEX_HULL_CHROMIUM:
2716 case GL_BOUNDING_BOX_CHROMIUM:
2717 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2718 break;
2719 default:
2720 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2721 return false;
2722 }
2723
2724 return true;
2725}
2726
2727bool ValidateStencilFillPathInstanced(Context *context,
2728 GLsizei numPaths,
2729 GLenum pathNameType,
2730 const void *paths,
2731 GLuint pathBase,
2732 GLenum fillMode,
2733 GLuint mask,
2734 GLenum transformType,
2735 const GLfloat *transformValues)
2736{
2737
2738 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2739 transformType, transformValues))
2740 return false;
2741
2742 switch (fillMode)
2743 {
2744 case GL_COUNT_UP_CHROMIUM:
2745 case GL_COUNT_DOWN_CHROMIUM:
2746 break;
2747 default:
2748 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2749 return false;
2750 }
2751 if (!isPow2(mask + 1))
2752 {
2753 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2754 return false;
2755 }
2756 return true;
2757}
2758
2759bool ValidateStencilStrokePathInstanced(Context *context,
2760 GLsizei numPaths,
2761 GLenum pathNameType,
2762 const void *paths,
2763 GLuint pathBase,
2764 GLint reference,
2765 GLuint mask,
2766 GLenum transformType,
2767 const GLfloat *transformValues)
2768{
2769 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2770 transformType, transformValues))
2771 return false;
2772
2773 // no more validation here.
2774
2775 return true;
2776}
2777
2778bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2779 GLsizei numPaths,
2780 GLenum pathNameType,
2781 const void *paths,
2782 GLuint pathBase,
2783 GLenum fillMode,
2784 GLuint mask,
2785 GLenum coverMode,
2786 GLenum transformType,
2787 const GLfloat *transformValues)
2788{
2789 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2790 transformType, transformValues))
2791 return false;
2792
2793 switch (coverMode)
2794 {
2795 case GL_CONVEX_HULL_CHROMIUM:
2796 case GL_BOUNDING_BOX_CHROMIUM:
2797 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2798 break;
2799 default:
2800 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2801 return false;
2802 }
2803
2804 switch (fillMode)
2805 {
2806 case GL_COUNT_UP_CHROMIUM:
2807 case GL_COUNT_DOWN_CHROMIUM:
2808 break;
2809 default:
2810 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2811 return false;
2812 }
2813 if (!isPow2(mask + 1))
2814 {
2815 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2816 return false;
2817 }
2818
2819 return true;
2820}
2821
2822bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2823 GLsizei numPaths,
2824 GLenum pathNameType,
2825 const void *paths,
2826 GLuint pathBase,
2827 GLint reference,
2828 GLuint mask,
2829 GLenum coverMode,
2830 GLenum transformType,
2831 const GLfloat *transformValues)
2832{
2833 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2834 transformType, transformValues))
2835 return false;
2836
2837 switch (coverMode)
2838 {
2839 case GL_CONVEX_HULL_CHROMIUM:
2840 case GL_BOUNDING_BOX_CHROMIUM:
2841 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2842 break;
2843 default:
2844 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2845 return false;
2846 }
2847
2848 return true;
2849}
2850
Sami Väisänen46eaa942016-06-29 10:26:37 +03002851bool ValidateBindFragmentInputLocation(Context *context,
2852 GLuint program,
2853 GLint location,
2854 const GLchar *name)
2855{
2856 if (!context->getExtensions().pathRendering)
2857 {
2858 context->handleError(
2859 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2860 return false;
2861 }
2862
2863 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2864 if (location >= MaxLocation)
2865 {
2866 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2867 return false;
2868 }
2869
2870 const auto *programObject = context->getProgram(program);
2871 if (!programObject)
2872 {
2873 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2874 return false;
2875 }
2876
2877 if (!name)
2878 {
2879 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2880 return false;
2881 }
2882
2883 if (angle::BeginsWith(name, "gl_"))
2884 {
2885 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2886 return false;
2887 }
2888
2889 return true;
2890}
2891
2892bool ValidateProgramPathFragmentInputGen(Context *context,
2893 GLuint program,
2894 GLint location,
2895 GLenum genMode,
2896 GLint components,
2897 const GLfloat *coeffs)
2898{
2899 if (!context->getExtensions().pathRendering)
2900 {
2901 context->handleError(
2902 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2903 return false;
2904 }
2905
2906 const auto *programObject = context->getProgram(program);
2907 if (!programObject || programObject->isFlaggedForDeletion())
2908 {
2909 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2910 return false;
2911 }
2912
2913 if (!programObject->isLinked())
2914 {
2915 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2916 return false;
2917 }
2918
2919 switch (genMode)
2920 {
2921 case GL_NONE:
2922 if (components != 0)
2923 {
2924 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2925 return false;
2926 }
2927 break;
2928
2929 case GL_OBJECT_LINEAR_CHROMIUM:
2930 case GL_EYE_LINEAR_CHROMIUM:
2931 case GL_CONSTANT_CHROMIUM:
2932 if (components < 1 || components > 4)
2933 {
2934 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2935 return false;
2936 }
2937 if (!coeffs)
2938 {
2939 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2940 return false;
2941 }
2942 break;
2943
2944 default:
2945 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2946 return false;
2947 }
2948
2949 // If the location is -1 then the command is silently ignored
2950 // and no further validation is needed.
2951 if (location == -1)
2952 return true;
2953
2954 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2955
2956 if (!binding.valid)
2957 {
2958 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
2959 return false;
2960 }
2961
2962 if (binding.type != GL_NONE)
2963 {
2964 GLint expectedComponents = 0;
2965 switch (binding.type)
2966 {
2967 case GL_FLOAT:
2968 expectedComponents = 1;
2969 break;
2970 case GL_FLOAT_VEC2:
2971 expectedComponents = 2;
2972 break;
2973 case GL_FLOAT_VEC3:
2974 expectedComponents = 3;
2975 break;
2976 case GL_FLOAT_VEC4:
2977 expectedComponents = 4;
2978 break;
2979 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08002980 context->handleError(
2981 Error(GL_INVALID_OPERATION,
2982 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03002983 return false;
2984 }
2985 if (expectedComponents != components && genMode != GL_NONE)
2986 {
2987 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
2988 return false;
2989 }
2990 }
2991 return true;
2992}
2993
Geoff Lang97073d12016-04-20 10:42:34 -07002994bool ValidateCopyTextureCHROMIUM(Context *context,
2995 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04002996 GLint sourceLevel,
2997 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07002998 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04002999 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003000 GLint internalFormat,
3001 GLenum destType,
3002 GLboolean unpackFlipY,
3003 GLboolean unpackPremultiplyAlpha,
3004 GLboolean unpackUnmultiplyAlpha)
3005{
3006 if (!context->getExtensions().copyTexture)
3007 {
3008 context->handleError(
3009 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3010 return false;
3011 }
3012
3013 const gl::Texture *source = context->getTexture(sourceId);
3014 if (source == nullptr)
3015 {
3016 context->handleError(
3017 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3018 return false;
3019 }
3020
3021 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3022 {
3023 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3024 return false;
3025 }
3026
3027 GLenum sourceTarget = source->getTarget();
3028 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3029 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3030 {
3031 context->handleError(
3032 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3033 return false;
3034 }
3035
3036 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3037 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3038 {
3039 context->handleError(
3040 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3041 return false;
3042 }
3043
3044 const gl::Texture *dest = context->getTexture(destId);
3045 if (dest == nullptr)
3046 {
3047 context->handleError(
3048 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3049 return false;
3050 }
3051
3052 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3053 {
3054 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3055 return false;
3056 }
3057
3058 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3059 {
3060 context->handleError(
3061 Error(GL_INVALID_OPERATION,
3062 "Destination internal format and type combination is not valid."));
3063 return false;
3064 }
3065
3066 if (dest->getImmutableFormat())
3067 {
3068 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3069 return false;
3070 }
3071
3072 return true;
3073}
3074
3075bool ValidateCopySubTextureCHROMIUM(Context *context,
3076 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003077 GLint sourceLevel,
3078 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003079 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003080 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003081 GLint xoffset,
3082 GLint yoffset,
3083 GLint x,
3084 GLint y,
3085 GLsizei width,
3086 GLsizei height,
3087 GLboolean unpackFlipY,
3088 GLboolean unpackPremultiplyAlpha,
3089 GLboolean unpackUnmultiplyAlpha)
3090{
3091 if (!context->getExtensions().copyTexture)
3092 {
3093 context->handleError(
3094 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3095 return false;
3096 }
3097
3098 const gl::Texture *source = context->getTexture(sourceId);
3099 if (source == nullptr)
3100 {
3101 context->handleError(
3102 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3103 return false;
3104 }
3105
3106 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3107 {
3108 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3109 return false;
3110 }
3111
3112 GLenum sourceTarget = source->getTarget();
3113 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3114 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3115 {
3116 context->handleError(
3117 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3118 return false;
3119 }
3120
3121 if (x < 0 || y < 0)
3122 {
3123 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3124 return false;
3125 }
3126
3127 if (width < 0 || height < 0)
3128 {
3129 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3130 return false;
3131 }
3132
3133 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3134 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3135 {
3136 context->handleError(
3137 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3138 return false;
3139 }
3140
3141 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3142 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3143 {
3144 context->handleError(
3145 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3146 return false;
3147 }
3148
3149 const gl::Texture *dest = context->getTexture(destId);
3150 if (dest == nullptr)
3151 {
3152 context->handleError(
3153 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3154 return false;
3155 }
3156
3157 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3158 {
3159 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3160 return false;
3161 }
3162
Geoff Lang97073d12016-04-20 10:42:34 -07003163 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3164 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3165 {
3166 context->handleError(
3167 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3168 return false;
3169 }
3170
3171 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3172 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3173 {
3174 context->handleError(
3175 Error(GL_INVALID_OPERATION,
3176 "Destination internal format and type combination is not valid."));
3177 return false;
3178 }
3179
3180 if (xoffset < 0 || yoffset < 0)
3181 {
3182 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3183 return false;
3184 }
3185
3186 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3187 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3188 {
3189 context->handleError(
3190 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3191 return false;
3192 }
3193
3194 return true;
3195}
3196
Geoff Lang47110bf2016-04-20 11:13:22 -07003197bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3198{
3199 if (!context->getExtensions().copyCompressedTexture)
3200 {
3201 context->handleError(Error(GL_INVALID_OPERATION,
3202 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3203 return false;
3204 }
3205
3206 const gl::Texture *source = context->getTexture(sourceId);
3207 if (source == nullptr)
3208 {
3209 context->handleError(
3210 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3211 return false;
3212 }
3213
3214 if (source->getTarget() != GL_TEXTURE_2D)
3215 {
3216 context->handleError(
3217 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3218 return false;
3219 }
3220
3221 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3222 {
3223 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3224 return false;
3225 }
3226
3227 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3228 if (!sourceFormat.info->compressed)
3229 {
3230 context->handleError(
3231 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3232 return false;
3233 }
3234
3235 const gl::Texture *dest = context->getTexture(destId);
3236 if (dest == nullptr)
3237 {
3238 context->handleError(
3239 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3240 return false;
3241 }
3242
3243 if (dest->getTarget() != GL_TEXTURE_2D)
3244 {
3245 context->handleError(
3246 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3247 return false;
3248 }
3249
3250 if (dest->getImmutableFormat())
3251 {
3252 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3253 return false;
3254 }
3255
3256 return true;
3257}
3258
Martin Radev4c4c8e72016-08-04 12:25:34 +03003259bool ValidateCreateShader(Context *context, GLenum type)
3260{
3261 switch (type)
3262 {
3263 case GL_VERTEX_SHADER:
3264 case GL_FRAGMENT_SHADER:
3265 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003266
Martin Radev4c4c8e72016-08-04 12:25:34 +03003267 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003268 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003269 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003270 context->handleError(
3271 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3272 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003273 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003274 break;
3275
Martin Radev4c4c8e72016-08-04 12:25:34 +03003276 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003277 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003278 return false;
3279 }
Jamie Madill29639852016-09-02 15:00:09 -04003280
3281 return true;
3282}
3283
3284bool ValidateBufferData(ValidationContext *context,
3285 GLenum target,
3286 GLsizeiptr size,
3287 const GLvoid *data,
3288 GLenum usage)
3289{
3290 if (size < 0)
3291 {
3292 context->handleError(Error(GL_INVALID_VALUE));
3293 return false;
3294 }
3295
3296 switch (usage)
3297 {
3298 case GL_STREAM_DRAW:
3299 case GL_STATIC_DRAW:
3300 case GL_DYNAMIC_DRAW:
3301 break;
3302
3303 case GL_STREAM_READ:
3304 case GL_STREAM_COPY:
3305 case GL_STATIC_READ:
3306 case GL_STATIC_COPY:
3307 case GL_DYNAMIC_READ:
3308 case GL_DYNAMIC_COPY:
3309 if (context->getClientMajorVersion() < 3)
3310 {
3311 context->handleError(Error(GL_INVALID_ENUM));
3312 return false;
3313 }
3314 break;
3315
3316 default:
3317 context->handleError(Error(GL_INVALID_ENUM));
3318 return false;
3319 }
3320
3321 if (!ValidBufferTarget(context, target))
3322 {
3323 context->handleError(Error(GL_INVALID_ENUM));
3324 return false;
3325 }
3326
3327 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3328
3329 if (!buffer)
3330 {
3331 context->handleError(Error(GL_INVALID_OPERATION));
3332 return false;
3333 }
3334
3335 return true;
3336}
3337
3338bool ValidateBufferSubData(ValidationContext *context,
3339 GLenum target,
3340 GLintptr offset,
3341 GLsizeiptr size,
3342 const GLvoid *data)
3343{
3344 if (size < 0 || offset < 0)
3345 {
3346 context->handleError(Error(GL_INVALID_VALUE));
3347 return false;
3348 }
3349
3350 if (!ValidBufferTarget(context, target))
3351 {
3352 context->handleError(Error(GL_INVALID_ENUM));
3353 return false;
3354 }
3355
3356 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3357
3358 if (!buffer)
3359 {
3360 context->handleError(Error(GL_INVALID_OPERATION));
3361 return false;
3362 }
3363
3364 if (buffer->isMapped())
3365 {
3366 context->handleError(Error(GL_INVALID_OPERATION));
3367 return false;
3368 }
3369
3370 // Check for possible overflow of size + offset
3371 angle::CheckedNumeric<size_t> checkedSize(size);
3372 checkedSize += offset;
3373 if (!checkedSize.IsValid())
3374 {
3375 context->handleError(Error(GL_OUT_OF_MEMORY));
3376 return false;
3377 }
3378
3379 if (size + offset > buffer->getSize())
3380 {
3381 context->handleError(Error(GL_INVALID_VALUE));
3382 return false;
3383 }
3384
Martin Radev4c4c8e72016-08-04 12:25:34 +03003385 return true;
3386}
3387
Geoff Langc339c4e2016-11-29 10:37:36 -05003388bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003389{
Geoff Langc339c4e2016-11-29 10:37:36 -05003390 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003391 {
3392 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003393 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003394 return false;
3395 }
3396
3397 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3398 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003399 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003400 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003401 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003402 return false;
3403 }
3404
3405 return true;
3406}
3407
Jamie Madillef300b12016-10-07 15:12:09 -04003408bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3409{
3410 if (texture < GL_TEXTURE0 ||
3411 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3412 {
3413 context->handleError(Error(GL_INVALID_ENUM));
3414 return false;
3415 }
3416
3417 return true;
3418}
3419
3420bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3421{
3422 Program *programObject = GetValidProgram(context, program);
3423 if (!programObject)
3424 {
3425 return false;
3426 }
3427
3428 Shader *shaderObject = GetValidShader(context, shader);
3429 if (!shaderObject)
3430 {
3431 return false;
3432 }
3433
3434 switch (shaderObject->getType())
3435 {
3436 case GL_VERTEX_SHADER:
3437 {
3438 if (programObject->getAttachedVertexShader())
3439 {
3440 context->handleError(Error(GL_INVALID_OPERATION));
3441 return false;
3442 }
3443 break;
3444 }
3445 case GL_FRAGMENT_SHADER:
3446 {
3447 if (programObject->getAttachedFragmentShader())
3448 {
3449 context->handleError(Error(GL_INVALID_OPERATION));
3450 return false;
3451 }
3452 break;
3453 }
3454 case GL_COMPUTE_SHADER:
3455 {
3456 if (programObject->getAttachedComputeShader())
3457 {
3458 context->handleError(Error(GL_INVALID_OPERATION));
3459 return false;
3460 }
3461 break;
3462 }
3463 default:
3464 UNREACHABLE();
3465 break;
3466 }
3467
3468 return true;
3469}
3470
Jamie Madill01a80ee2016-11-07 12:06:18 -05003471bool ValidateBindAttribLocation(ValidationContext *context,
3472 GLuint program,
3473 GLuint index,
3474 const GLchar *name)
3475{
3476 if (index >= MAX_VERTEX_ATTRIBS)
3477 {
3478 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3479 return false;
3480 }
3481
3482 if (strncmp(name, "gl_", 3) == 0)
3483 {
3484 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3485 return false;
3486 }
3487
3488 return GetValidProgram(context, program) != nullptr;
3489}
3490
3491bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3492{
3493 if (!ValidBufferTarget(context, target))
3494 {
3495 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3496 return false;
3497 }
3498
3499 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3500 !context->isBufferGenerated(buffer))
3501 {
3502 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3503 return false;
3504 }
3505
3506 return true;
3507}
3508
3509bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3510{
3511 if (!ValidFramebufferTarget(target))
3512 {
3513 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3514 return false;
3515 }
3516
3517 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3518 !context->isFramebufferGenerated(framebuffer))
3519 {
3520 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3521 return false;
3522 }
3523
3524 return true;
3525}
3526
3527bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3528{
3529 if (target != GL_RENDERBUFFER)
3530 {
3531 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3532 return false;
3533 }
3534
3535 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3536 !context->isRenderbufferGenerated(renderbuffer))
3537 {
3538 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3539 return false;
3540 }
3541
3542 return true;
3543}
3544
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003545static bool ValidBlendEquationMode(GLenum mode)
3546{
3547 switch (mode)
3548 {
3549 case GL_FUNC_ADD:
3550 case GL_FUNC_SUBTRACT:
3551 case GL_FUNC_REVERSE_SUBTRACT:
3552 case GL_MIN:
3553 case GL_MAX:
3554 return true;
3555
3556 default:
3557 return false;
3558 }
3559}
3560
Jamie Madillc1d770e2017-04-13 17:31:24 -04003561bool ValidateBlendColor(ValidationContext *context,
3562 GLclampf red,
3563 GLclampf green,
3564 GLclampf blue,
3565 GLclampf alpha)
3566{
3567 return true;
3568}
3569
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003570bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3571{
3572 if (!ValidBlendEquationMode(mode))
3573 {
3574 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3575 return false;
3576 }
3577
3578 return true;
3579}
3580
3581bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3582{
3583 if (!ValidBlendEquationMode(modeRGB))
3584 {
3585 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3586 return false;
3587 }
3588
3589 if (!ValidBlendEquationMode(modeAlpha))
3590 {
3591 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3592 return false;
3593 }
3594
3595 return true;
3596}
3597
3598bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3599{
3600 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3601}
3602
3603static bool ValidSrcBlendFunc(GLenum srcBlend)
3604{
3605 switch (srcBlend)
3606 {
3607 case GL_ZERO:
3608 case GL_ONE:
3609 case GL_SRC_COLOR:
3610 case GL_ONE_MINUS_SRC_COLOR:
3611 case GL_DST_COLOR:
3612 case GL_ONE_MINUS_DST_COLOR:
3613 case GL_SRC_ALPHA:
3614 case GL_ONE_MINUS_SRC_ALPHA:
3615 case GL_DST_ALPHA:
3616 case GL_ONE_MINUS_DST_ALPHA:
3617 case GL_CONSTANT_COLOR:
3618 case GL_ONE_MINUS_CONSTANT_COLOR:
3619 case GL_CONSTANT_ALPHA:
3620 case GL_ONE_MINUS_CONSTANT_ALPHA:
3621 case GL_SRC_ALPHA_SATURATE:
3622 return true;
3623
3624 default:
3625 return false;
3626 }
3627}
3628
3629static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3630{
3631 switch (dstBlend)
3632 {
3633 case GL_ZERO:
3634 case GL_ONE:
3635 case GL_SRC_COLOR:
3636 case GL_ONE_MINUS_SRC_COLOR:
3637 case GL_DST_COLOR:
3638 case GL_ONE_MINUS_DST_COLOR:
3639 case GL_SRC_ALPHA:
3640 case GL_ONE_MINUS_SRC_ALPHA:
3641 case GL_DST_ALPHA:
3642 case GL_ONE_MINUS_DST_ALPHA:
3643 case GL_CONSTANT_COLOR:
3644 case GL_ONE_MINUS_CONSTANT_COLOR:
3645 case GL_CONSTANT_ALPHA:
3646 case GL_ONE_MINUS_CONSTANT_ALPHA:
3647 return true;
3648
3649 case GL_SRC_ALPHA_SATURATE:
3650 return (contextMajorVersion >= 3);
3651
3652 default:
3653 return false;
3654 }
3655}
3656
3657bool ValidateBlendFuncSeparate(ValidationContext *context,
3658 GLenum srcRGB,
3659 GLenum dstRGB,
3660 GLenum srcAlpha,
3661 GLenum dstAlpha)
3662{
3663 if (!ValidSrcBlendFunc(srcRGB))
3664 {
3665 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3666 return false;
3667 }
3668
3669 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3670 {
3671 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3672 return false;
3673 }
3674
3675 if (!ValidSrcBlendFunc(srcAlpha))
3676 {
3677 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3678 return false;
3679 }
3680
3681 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3682 {
3683 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3684 return false;
3685 }
3686
Frank Henigman146e8a12017-03-02 23:22:37 -05003687 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3688 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003689 {
3690 bool constantColorUsed =
3691 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3692 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3693
3694 bool constantAlphaUsed =
3695 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3696 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3697
3698 if (constantColorUsed && constantAlphaUsed)
3699 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003700 const char *msg;
3701 if (context->getExtensions().webglCompatibility)
3702 {
3703 msg =
3704 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3705 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3706 }
3707 else
3708 {
3709 msg =
3710 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3711 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3712 "implementation.";
3713 ERR() << msg;
3714 }
3715 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003716 return false;
3717 }
3718 }
3719
3720 return true;
3721}
3722
Geoff Langc339c4e2016-11-29 10:37:36 -05003723bool ValidateGetString(Context *context, GLenum name)
3724{
3725 switch (name)
3726 {
3727 case GL_VENDOR:
3728 case GL_RENDERER:
3729 case GL_VERSION:
3730 case GL_SHADING_LANGUAGE_VERSION:
3731 case GL_EXTENSIONS:
3732 break;
3733
3734 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3735 if (!context->getExtensions().requestExtension)
3736 {
3737 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3738 return false;
3739 }
3740 break;
3741
3742 default:
3743 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3744 return false;
3745 }
3746
3747 return true;
3748}
3749
Geoff Lang47c48082016-12-07 15:38:13 -05003750bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3751{
3752 if (width <= 0.0f || isNaN(width))
3753 {
3754 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3755 return false;
3756 }
3757
3758 return true;
3759}
3760
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003761bool ValidateVertexAttribPointer(ValidationContext *context,
3762 GLuint index,
3763 GLint size,
3764 GLenum type,
3765 GLboolean normalized,
3766 GLsizei stride,
3767 const GLvoid *ptr)
3768{
Shao80957d92017-02-20 21:25:59 +08003769 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003770 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003771 return false;
3772 }
3773
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003774 if (stride < 0)
3775 {
Shao80957d92017-02-20 21:25:59 +08003776 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003777 return false;
3778 }
3779
Shao80957d92017-02-20 21:25:59 +08003780 const Caps &caps = context->getCaps();
3781 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003782 {
Shao80957d92017-02-20 21:25:59 +08003783 if (stride > caps.maxVertexAttribStride)
3784 {
3785 context->handleError(
3786 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
3787 return false;
3788 }
3789
3790 if (index >= caps.maxVertexAttribBindings)
3791 {
3792 context->handleError(
3793 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
3794 return false;
3795 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003796 }
3797
3798 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3799 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3800 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3801 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003802 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3803 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08003804 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003805 {
3806 context->handleError(
3807 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08003808 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003809 return false;
3810 }
3811
3812 if (context->getExtensions().webglCompatibility)
3813 {
3814 // WebGL 1.0 [Section 6.14] Fixed point support
3815 // The WebGL API does not support the GL_FIXED data type.
3816 if (type == GL_FIXED)
3817 {
3818 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3819 return false;
3820 }
3821
Geoff Lang2d62ab72017-03-23 16:54:40 -04003822 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003823 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003824 return false;
3825 }
3826 }
3827
3828 return true;
3829}
3830
Frank Henigman6137ddc2017-02-10 18:55:07 -05003831bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
3832{
3833 if (context->getExtensions().webglCompatibility && zNear > zFar)
3834 {
3835 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
3836 return false;
3837 }
3838
3839 return true;
3840}
3841
Jamie Madille8fb6402017-02-14 17:56:40 -05003842bool ValidateRenderbufferStorage(ValidationContext *context,
3843 GLenum target,
3844 GLenum internalformat,
3845 GLsizei width,
3846 GLsizei height)
3847{
3848 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
3849 height);
3850}
3851
3852bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
3853 GLenum target,
3854 GLsizei samples,
3855 GLenum internalformat,
3856 GLsizei width,
3857 GLsizei height)
3858{
3859 if (!context->getExtensions().framebufferMultisample)
3860 {
3861 context->handleError(
3862 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
3863 return false;
3864 }
3865
3866 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
3867 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
3868 // generated.
3869 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
3870 {
3871 context->handleError(Error(GL_INVALID_VALUE));
3872 return false;
3873 }
3874
3875 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
3876 // the specified storage. This is different than ES 3.0 in which a sample number higher
3877 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
3878 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
3879 if (context->getClientMajorVersion() >= 3)
3880 {
3881 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3882 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3883 {
3884 context->handleError(Error(GL_OUT_OF_MEMORY));
3885 return false;
3886 }
3887 }
3888
3889 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
3890 width, height);
3891}
3892
Jamie Madillc1d770e2017-04-13 17:31:24 -04003893bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
3894{
3895 if (!ValidFramebufferTarget(target))
3896 {
3897 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3898 return false;
3899 }
3900
3901 return true;
3902}
3903
3904bool ValidateClearColor(ValidationContext *context,
3905 GLclampf red,
3906 GLclampf green,
3907 GLclampf blue,
3908 GLclampf alpha)
3909{
3910 return true;
3911}
3912
3913bool ValidateClearDepthf(ValidationContext *context, GLclampf depth)
3914{
3915 return true;
3916}
3917
3918bool ValidateClearStencil(ValidationContext *context, GLint s)
3919{
3920 return true;
3921}
3922
3923bool ValidateColorMask(ValidationContext *context,
3924 GLboolean red,
3925 GLboolean green,
3926 GLboolean blue,
3927 GLboolean alpha)
3928{
3929 return true;
3930}
3931
3932bool ValidateCompileShader(ValidationContext *context, GLuint shader)
3933{
3934 return true;
3935}
3936
3937bool ValidateCreateProgram(ValidationContext *context)
3938{
3939 return true;
3940}
3941
3942bool ValidateCullFace(ValidationContext *context, GLenum mode)
3943{
3944 switch (mode)
3945 {
3946 case GL_FRONT:
3947 case GL_BACK:
3948 case GL_FRONT_AND_BACK:
3949 break;
3950
3951 default:
3952 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
3953 return false;
3954 }
3955
3956 return true;
3957}
3958
3959bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
3960{
3961 if (program == 0)
3962 {
3963 return false;
3964 }
3965
3966 if (!context->getProgram(program))
3967 {
3968 if (context->getShader(program))
3969 {
3970 context->handleError(
3971 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
3972 return false;
3973 }
3974 else
3975 {
3976 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
3977 return false;
3978 }
3979 }
3980
3981 return true;
3982}
3983
3984bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
3985{
3986 if (shader == 0)
3987 {
3988 return false;
3989 }
3990
3991 if (!context->getShader(shader))
3992 {
3993 if (context->getProgram(shader))
3994 {
3995 context->handleError(
3996 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
3997 return false;
3998 }
3999 else
4000 {
4001 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4002 return false;
4003 }
4004 }
4005
4006 return true;
4007}
4008
4009bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4010{
4011 switch (func)
4012 {
4013 case GL_NEVER:
4014 case GL_ALWAYS:
4015 case GL_LESS:
4016 case GL_LEQUAL:
4017 case GL_EQUAL:
4018 case GL_GREATER:
4019 case GL_GEQUAL:
4020 case GL_NOTEQUAL:
4021 break;
4022
4023 default:
4024 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4025 return false;
4026 }
4027
4028 return true;
4029}
4030
4031bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4032{
4033 return true;
4034}
4035
4036bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4037{
4038 Program *programObject = GetValidProgram(context, program);
4039 if (!programObject)
4040 {
4041 return false;
4042 }
4043
4044 Shader *shaderObject = GetValidShader(context, shader);
4045 if (!shaderObject)
4046 {
4047 return false;
4048 }
4049
4050 const Shader *attachedShader = nullptr;
4051
4052 switch (shaderObject->getType())
4053 {
4054 case GL_VERTEX_SHADER:
4055 {
4056 attachedShader = programObject->getAttachedVertexShader();
4057 break;
4058 }
4059 case GL_FRAGMENT_SHADER:
4060 {
4061 attachedShader = programObject->getAttachedFragmentShader();
4062 break;
4063 }
4064 case GL_COMPUTE_SHADER:
4065 {
4066 attachedShader = programObject->getAttachedComputeShader();
4067 break;
4068 }
4069 default:
4070 UNREACHABLE();
4071 return false;
4072 }
4073
4074 if (attachedShader != shaderObject)
4075 {
4076 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4077 return false;
4078 }
4079
4080 return true;
4081}
4082
4083bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4084{
4085 if (index >= MAX_VERTEX_ATTRIBS)
4086 {
4087 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4088 return false;
4089 }
4090
4091 return true;
4092}
4093
4094bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4095{
4096 if (index >= MAX_VERTEX_ATTRIBS)
4097 {
4098 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4099 return false;
4100 }
4101
4102 return true;
4103}
4104
4105bool ValidateFinish(ValidationContext *context)
4106{
4107 return true;
4108}
4109
4110bool ValidateFlush(ValidationContext *context)
4111{
4112 return true;
4113}
4114
4115bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4116{
4117 switch (mode)
4118 {
4119 case GL_CW:
4120 case GL_CCW:
4121 break;
4122 default:
4123 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4124 return false;
4125 }
4126
4127 return true;
4128}
4129
4130bool ValidateGetActiveAttrib(ValidationContext *context,
4131 GLuint program,
4132 GLuint index,
4133 GLsizei bufsize,
4134 GLsizei *length,
4135 GLint *size,
4136 GLenum *type,
4137 GLchar *name)
4138{
4139 if (bufsize < 0)
4140 {
4141 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4142 return false;
4143 }
4144
4145 Program *programObject = GetValidProgram(context, program);
4146
4147 if (!programObject)
4148 {
4149 return false;
4150 }
4151
4152 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4153 {
4154 context->handleError(
4155 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4156 return false;
4157 }
4158
4159 return true;
4160}
4161
4162bool ValidateGetActiveUniform(ValidationContext *context,
4163 GLuint program,
4164 GLuint index,
4165 GLsizei bufsize,
4166 GLsizei *length,
4167 GLint *size,
4168 GLenum *type,
4169 GLchar *name)
4170{
4171 if (bufsize < 0)
4172 {
4173 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4174 return false;
4175 }
4176
4177 Program *programObject = GetValidProgram(context, program);
4178
4179 if (!programObject)
4180 {
4181 return false;
4182 }
4183
4184 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4185 {
4186 context->handleError(
4187 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4188 return false;
4189 }
4190
4191 return true;
4192}
4193
4194bool ValidateGetAttachedShaders(ValidationContext *context,
4195 GLuint program,
4196 GLsizei maxcount,
4197 GLsizei *count,
4198 GLuint *shaders)
4199{
4200 if (maxcount < 0)
4201 {
4202 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4203 return false;
4204 }
4205
4206 Program *programObject = GetValidProgram(context, program);
4207
4208 if (!programObject)
4209 {
4210 return false;
4211 }
4212
4213 return true;
4214}
4215
4216bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4217{
4218 Program *programObject = GetValidProgram(context, program);
4219
4220 if (!programObject)
4221 {
4222 return false;
4223 }
4224
4225 if (!programObject->isLinked())
4226 {
4227 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4228 return false;
4229 }
4230
4231 return true;
4232}
4233
4234bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4235{
4236 GLenum nativeType;
4237 unsigned int numParams = 0;
4238 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4239}
4240
4241bool ValidateGetError(ValidationContext *context)
4242{
4243 return true;
4244}
4245
4246bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4247{
4248 GLenum nativeType;
4249 unsigned int numParams = 0;
4250 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4251}
4252
4253bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4254{
4255 GLenum nativeType;
4256 unsigned int numParams = 0;
4257 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4258}
4259
4260bool ValidateGetProgramInfoLog(ValidationContext *context,
4261 GLuint program,
4262 GLsizei bufsize,
4263 GLsizei *length,
4264 GLchar *infolog)
4265{
4266 if (bufsize < 0)
4267 {
4268 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4269 return false;
4270 }
4271
4272 Program *programObject = GetValidProgram(context, program);
4273 if (!programObject)
4274 {
4275 return false;
4276 }
4277
4278 return true;
4279}
4280
4281bool ValidateGetShaderInfoLog(ValidationContext *context,
4282 GLuint shader,
4283 GLsizei bufsize,
4284 GLsizei *length,
4285 GLchar *infolog)
4286{
4287 if (bufsize < 0)
4288 {
4289 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4290 return false;
4291 }
4292
4293 Shader *shaderObject = GetValidShader(context, shader);
4294 if (!shaderObject)
4295 {
4296 return false;
4297 }
4298
4299 return true;
4300}
4301
4302bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4303 GLenum shadertype,
4304 GLenum precisiontype,
4305 GLint *range,
4306 GLint *precision)
4307{
4308 switch (shadertype)
4309 {
4310 case GL_VERTEX_SHADER:
4311 case GL_FRAGMENT_SHADER:
4312 break;
4313 case GL_COMPUTE_SHADER:
4314 context->handleError(
4315 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4316 return false;
4317 default:
4318 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4319 return false;
4320 }
4321
4322 switch (precisiontype)
4323 {
4324 case GL_LOW_FLOAT:
4325 case GL_MEDIUM_FLOAT:
4326 case GL_HIGH_FLOAT:
4327 case GL_LOW_INT:
4328 case GL_MEDIUM_INT:
4329 case GL_HIGH_INT:
4330 break;
4331
4332 default:
4333 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4334 return false;
4335 }
4336
4337 return true;
4338}
4339
4340bool ValidateGetShaderSource(ValidationContext *context,
4341 GLuint shader,
4342 GLsizei bufsize,
4343 GLsizei *length,
4344 GLchar *source)
4345{
4346 if (bufsize < 0)
4347 {
4348 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4349 return false;
4350 }
4351
4352 Shader *shaderObject = GetValidShader(context, shader);
4353 if (!shaderObject)
4354 {
4355 return false;
4356 }
4357
4358 return true;
4359}
4360
4361bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4362{
4363 if (strstr(name, "gl_") == name)
4364 {
4365 return false;
4366 }
4367
4368 Program *programObject = GetValidProgram(context, program);
4369
4370 if (!programObject)
4371 {
4372 return false;
4373 }
4374
4375 if (!programObject->isLinked())
4376 {
4377 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4378 return false;
4379 }
4380
4381 return true;
4382}
4383
4384bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4385{
4386 switch (mode)
4387 {
4388 case GL_FASTEST:
4389 case GL_NICEST:
4390 case GL_DONT_CARE:
4391 break;
4392
4393 default:
4394 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4395 return false;
4396 }
4397
4398 switch (target)
4399 {
4400 case GL_GENERATE_MIPMAP_HINT:
4401 break;
4402
4403 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4404 if (!context->getExtensions().standardDerivatives)
4405 {
4406 context->handleError(
4407 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4408 return false;
4409 }
4410 break;
4411
4412 default:
4413 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4414 return false;
4415 }
4416
4417 return true;
4418}
4419
4420bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4421{
4422 return true;
4423}
4424
4425bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4426{
4427 return true;
4428}
4429
4430bool ValidateIsProgram(ValidationContext *context, GLuint program)
4431{
4432 return true;
4433}
4434
4435bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4436{
4437 return true;
4438}
4439
4440bool ValidateIsShader(ValidationContext *context, GLuint shader)
4441{
4442 return true;
4443}
4444
4445bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4446{
4447 return true;
4448}
4449
4450bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4451{
4452 if (context->getClientMajorVersion() < 3)
4453 {
4454 switch (pname)
4455 {
4456 case GL_UNPACK_IMAGE_HEIGHT:
4457 case GL_UNPACK_SKIP_IMAGES:
4458 context->handleError(Error(GL_INVALID_ENUM));
4459 return false;
4460
4461 case GL_UNPACK_ROW_LENGTH:
4462 case GL_UNPACK_SKIP_ROWS:
4463 case GL_UNPACK_SKIP_PIXELS:
4464 if (!context->getExtensions().unpackSubimage)
4465 {
4466 context->handleError(Error(GL_INVALID_ENUM));
4467 return false;
4468 }
4469 break;
4470
4471 case GL_PACK_ROW_LENGTH:
4472 case GL_PACK_SKIP_ROWS:
4473 case GL_PACK_SKIP_PIXELS:
4474 if (!context->getExtensions().packSubimage)
4475 {
4476 context->handleError(Error(GL_INVALID_ENUM));
4477 return false;
4478 }
4479 break;
4480 }
4481 }
4482
4483 if (param < 0)
4484 {
4485 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4486 return false;
4487 }
4488
4489 switch (pname)
4490 {
4491 case GL_UNPACK_ALIGNMENT:
4492 if (param != 1 && param != 2 && param != 4 && param != 8)
4493 {
4494 context->handleError(Error(GL_INVALID_VALUE));
4495 return false;
4496 }
4497 break;
4498
4499 case GL_PACK_ALIGNMENT:
4500 if (param != 1 && param != 2 && param != 4 && param != 8)
4501 {
4502 context->handleError(Error(GL_INVALID_VALUE));
4503 return false;
4504 }
4505 break;
4506
4507 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4508 case GL_UNPACK_ROW_LENGTH:
4509 case GL_UNPACK_IMAGE_HEIGHT:
4510 case GL_UNPACK_SKIP_IMAGES:
4511 case GL_UNPACK_SKIP_ROWS:
4512 case GL_UNPACK_SKIP_PIXELS:
4513 case GL_PACK_ROW_LENGTH:
4514 case GL_PACK_SKIP_ROWS:
4515 case GL_PACK_SKIP_PIXELS:
4516 break;
4517
4518 default:
4519 context->handleError(Error(GL_INVALID_ENUM));
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
4526bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4527{
4528 return true;
4529}
4530
4531bool ValidateReleaseShaderCompiler(ValidationContext *context)
4532{
4533 return true;
4534}
4535
4536bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert)
4537{
4538 return true;
4539}
4540
4541bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4542{
4543 if (width < 0 || height < 0)
4544 {
4545 context->handleError(
4546 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4547 return false;
4548 }
4549
4550 return true;
4551}
4552
4553bool ValidateShaderBinary(ValidationContext *context,
4554 GLsizei n,
4555 const GLuint *shaders,
4556 GLenum binaryformat,
4557 const GLvoid *binary,
4558 GLsizei length)
4559{
4560 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4561 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4562 shaderBinaryFormats.end())
4563 {
4564 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4565 return false;
4566 }
4567
4568 return true;
4569}
4570
4571bool ValidateShaderSource(ValidationContext *context,
4572 GLuint shader,
4573 GLsizei count,
4574 const GLchar *const *string,
4575 const GLint *length)
4576{
4577 if (count < 0)
4578 {
4579 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4580 return false;
4581 }
4582
4583 Shader *shaderObject = GetValidShader(context, shader);
4584 if (!shaderObject)
4585 {
4586 return false;
4587 }
4588
4589 return true;
4590}
4591
4592bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4593{
4594 if (!IsValidStencilFunc(func))
4595 {
4596 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4597 return false;
4598 }
4599
4600 return true;
4601}
4602
4603bool ValidateStencilFuncSeparate(ValidationContext *context,
4604 GLenum face,
4605 GLenum func,
4606 GLint ref,
4607 GLuint mask)
4608{
4609 if (!IsValidStencilFace(face))
4610 {
4611 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4612 return false;
4613 }
4614
4615 if (!IsValidStencilFunc(func))
4616 {
4617 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4618 return false;
4619 }
4620
4621 return true;
4622}
4623
4624bool ValidateStencilMask(ValidationContext *context, GLuint mask)
4625{
4626 return true;
4627}
4628
4629bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
4630{
4631 if (!IsValidStencilFace(face))
4632 {
4633 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4634 return false;
4635 }
4636
4637 return true;
4638}
4639
4640bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
4641{
4642 if (!IsValidStencilOp(fail))
4643 {
4644 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
4645 return false;
4646 }
4647
4648 if (!IsValidStencilOp(zfail))
4649 {
4650 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
4651 return false;
4652 }
4653
4654 if (!IsValidStencilOp(zpass))
4655 {
4656 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
4657 return false;
4658 }
4659
4660 return true;
4661}
4662
4663bool ValidateStencilOpSeparate(ValidationContext *context,
4664 GLenum face,
4665 GLenum fail,
4666 GLenum zfail,
4667 GLenum zpass)
4668{
4669 if (!IsValidStencilFace(face))
4670 {
4671 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4672 return false;
4673 }
4674
4675 return ValidateStencilOp(context, fail, zfail, zpass);
4676}
4677
4678bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
4679{
4680 return ValidateUniform(context, GL_FLOAT, location, 1);
4681}
4682
4683bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4684{
4685 return ValidateUniform(context, GL_FLOAT, location, count);
4686}
4687
4688bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
4689{
4690 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
4691}
4692
4693bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4694{
4695 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
4696}
4697
4698bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
4699{
4700 return ValidateUniform(context, GL_INT_VEC2, location, 1);
4701}
4702
4703bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4704{
4705 return ValidateUniform(context, GL_INT_VEC2, location, count);
4706}
4707
4708bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
4709{
4710 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
4711}
4712
4713bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4714{
4715 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
4716}
4717
4718bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
4719{
4720 return ValidateUniform(context, GL_INT_VEC3, location, 1);
4721}
4722
4723bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4724{
4725 return ValidateUniform(context, GL_INT_VEC3, location, count);
4726}
4727
4728bool ValidateUniform4f(ValidationContext *context,
4729 GLint location,
4730 GLfloat x,
4731 GLfloat y,
4732 GLfloat z,
4733 GLfloat w)
4734{
4735 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
4736}
4737
4738bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4739{
4740 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
4741}
4742
4743bool ValidateUniform4i(ValidationContext *context,
4744 GLint location,
4745 GLint x,
4746 GLint y,
4747 GLint z,
4748 GLint w)
4749{
4750 return ValidateUniform(context, GL_INT_VEC4, location, 1);
4751}
4752
4753bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4754{
4755 return ValidateUniform(context, GL_INT_VEC4, location, count);
4756}
4757
4758bool ValidateUniformMatrix2fv(ValidationContext *context,
4759 GLint location,
4760 GLsizei count,
4761 GLboolean transpose,
4762 const GLfloat *value)
4763{
4764 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
4765}
4766
4767bool ValidateUniformMatrix3fv(ValidationContext *context,
4768 GLint location,
4769 GLsizei count,
4770 GLboolean transpose,
4771 const GLfloat *value)
4772{
4773 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
4774}
4775
4776bool ValidateUniformMatrix4fv(ValidationContext *context,
4777 GLint location,
4778 GLsizei count,
4779 GLboolean transpose,
4780 const GLfloat *value)
4781{
4782 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
4783}
4784
4785bool ValidateValidateProgram(ValidationContext *context, GLuint program)
4786{
4787 Program *programObject = GetValidProgram(context, program);
4788
4789 if (!programObject)
4790 {
4791 return false;
4792 }
4793
4794 return true;
4795}
4796
4797bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
4798{
4799 if (index >= MAX_VERTEX_ATTRIBS)
4800 {
4801 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
4802 return false;
4803 }
4804
4805 return true;
4806}
4807
4808bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
4809{
4810 return ValidateVertexAttribIndex(context, index);
4811}
4812
4813bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
4814{
4815 return ValidateVertexAttribIndex(context, index);
4816}
4817
4818bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
4819{
4820 return ValidateVertexAttribIndex(context, index);
4821}
4822
4823bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
4824{
4825 return ValidateVertexAttribIndex(context, index);
4826}
4827
4828bool ValidateVertexAttrib3f(ValidationContext *context,
4829 GLuint index,
4830 GLfloat x,
4831 GLfloat y,
4832 GLfloat z)
4833{
4834 return ValidateVertexAttribIndex(context, index);
4835}
4836
4837bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
4838{
4839 return ValidateVertexAttribIndex(context, index);
4840}
4841
4842bool ValidateVertexAttrib4f(ValidationContext *context,
4843 GLuint index,
4844 GLfloat x,
4845 GLfloat y,
4846 GLfloat z,
4847 GLfloat w)
4848{
4849 return ValidateVertexAttribIndex(context, index);
4850}
4851
4852bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
4853{
4854 return ValidateVertexAttribIndex(context, index);
4855}
4856
4857bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4858{
4859 if (width < 0 || height < 0)
4860 {
4861 context->handleError(
4862 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
4863 return false;
4864 }
4865
4866 return true;
4867}
4868
4869bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
4870{
4871 return ValidateDrawArraysCommon(context, mode, first, count, 1);
4872}
4873
Jamie Madillc29968b2016-01-20 11:17:23 -05004874} // namespace gl