blob: f3639cd26d4b94351f71019285f0150ed353e547 [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{
Geoff Langca271392017-04-05 12:30:00 -0400211 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700212 {
213 case GL_ALPHA:
214 case GL_LUMINANCE:
215 case GL_LUMINANCE_ALPHA:
216 case GL_RGB:
217 case GL_RGBA:
218 return true;
219
220 case GL_RED:
221 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
222
223 case GL_BGRA_EXT:
224 return context->getExtensions().textureFormatBGRA8888;
225
226 default:
227 return false;
228 }
229}
230
231bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
232{
233 switch (internalFormat)
234 {
235 case GL_RGB:
236 case GL_RGBA:
237 break;
238
239 case GL_BGRA_EXT:
240 return context->getExtensions().textureFormatBGRA8888;
241
242 default:
243 return false;
244 }
245
246 switch (type)
247 {
248 case GL_UNSIGNED_BYTE:
249 break;
250
251 default:
252 return false;
253 }
254
255 return true;
256}
257
258bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
259{
260 switch (target)
261 {
262 case GL_TEXTURE_2D:
263 return true;
264
265 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
266 // supported
267
268 default:
269 return false;
270 }
271}
272
273bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
274{
275 if (IsValidCopyTextureDestinationTarget(context, target))
276 {
277 return true;
278 }
279
280 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
281 // supported
282
283 return false;
284}
285
Jamie Madillc1d770e2017-04-13 17:31:24 -0400286bool IsValidStencilFunc(GLenum func)
287{
288 switch (func)
289 {
290 case GL_NEVER:
291 case GL_ALWAYS:
292 case GL_LESS:
293 case GL_LEQUAL:
294 case GL_EQUAL:
295 case GL_GEQUAL:
296 case GL_GREATER:
297 case GL_NOTEQUAL:
298 return true;
299
300 default:
301 return false;
302 }
303}
304
305bool IsValidStencilFace(GLenum face)
306{
307 switch (face)
308 {
309 case GL_FRONT:
310 case GL_BACK:
311 case GL_FRONT_AND_BACK:
312 return true;
313
314 default:
315 return false;
316 }
317}
318
319bool IsValidStencilOp(GLenum op)
320{
321 switch (op)
322 {
323 case GL_ZERO:
324 case GL_KEEP:
325 case GL_REPLACE:
326 case GL_INCR:
327 case GL_DECR:
328 case GL_INVERT:
329 case GL_INCR_WRAP:
330 case GL_DECR_WRAP:
331 return true;
332
333 default:
334 return false;
335 }
336}
337
Jamie Madillc29968b2016-01-20 11:17:23 -0500338} // anonymous namespace
339
Geoff Langff5b2d52016-09-07 11:32:23 -0400340bool ValidateES2TexImageParameters(Context *context,
341 GLenum target,
342 GLint level,
343 GLenum internalformat,
344 bool isCompressed,
345 bool isSubImage,
346 GLint xoffset,
347 GLint yoffset,
348 GLsizei width,
349 GLsizei height,
350 GLint border,
351 GLenum format,
352 GLenum type,
353 GLsizei imageSize,
354 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400355{
Jamie Madill6f38f822014-06-06 17:12:20 -0400356 if (!ValidTexture2DDestinationTarget(context, target))
357 {
Jamie Madill437fa652016-05-03 15:13:24 -0400358 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400359 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400360 }
361
Austin Kinross08528e12015-10-07 16:24:40 -0700362 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 {
Jamie Madill437fa652016-05-03 15:13:24 -0400364 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400366 }
367
He Yunchaoced53ae2016-11-29 15:00:51 +0800368 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400369 std::numeric_limits<GLsizei>::max() - yoffset < height)
370 {
Jamie Madill437fa652016-05-03 15:13:24 -0400371 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 }
374
Geoff Lang005df412013-10-16 14:12:50 -0400375 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376 {
Jamie Madill437fa652016-05-03 15:13:24 -0400377 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 }
380
Geoff Langaae65a42014-05-26 12:43:44 -0400381 const gl::Caps &caps = context->getCaps();
382
Geoff Langa9be0dc2014-12-17 12:34:40 -0500383 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500385 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
386 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400387 {
Jamie Madill437fa652016-05-03 15:13:24 -0400388 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500391 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500392 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500393 {
394 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 {
Jamie Madill437fa652016-05-03 15:13:24 -0400396 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400399
Geoff Langa9be0dc2014-12-17 12:34:40 -0500400 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
401 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
402 {
Jamie Madill437fa652016-05-03 15:13:24 -0400403 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500404 return false;
405 }
406 }
407 else
408 {
Jamie Madill437fa652016-05-03 15:13:24 -0400409 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400411 }
412
He Yunchaoced53ae2016-11-29 15:00:51 +0800413 gl::Texture *texture =
414 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400415 if (!texture)
416 {
Jamie Madill437fa652016-05-03 15:13:24 -0400417 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 }
420
Geoff Langa9be0dc2014-12-17 12:34:40 -0500421 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 {
Geoff Langca271392017-04-05 12:30:00 -0400423 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
424 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500425 {
426 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
427 return false;
428 }
429
Geoff Langa9be0dc2014-12-17 12:34:40 -0500430 if (format != GL_NONE)
431 {
Geoff Langca271392017-04-05 12:30:00 -0400432 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
433 textureInternalFormat.sizedInternalFormat)
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 =
Geoff Langca271392017-04-05 12:30:00 -0400466 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
467 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 switch (actualInternalFormat)
469 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800470 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
471 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
472 if (!context->getExtensions().textureCompressionDXT1)
473 {
474 context->handleError(Error(GL_INVALID_ENUM));
475 return false;
476 }
477 break;
478 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
479 if (!context->getExtensions().textureCompressionDXT1)
480 {
481 context->handleError(Error(GL_INVALID_ENUM));
482 return false;
483 }
484 break;
485 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
486 if (!context->getExtensions().textureCompressionDXT5)
487 {
488 context->handleError(Error(GL_INVALID_ENUM));
489 return false;
490 }
491 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800492 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
493 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
494 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
495 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
496 if (!context->getExtensions().textureCompressionS3TCsRGB)
497 {
498 context->handleError(Error(GL_INVALID_ENUM));
499 return false;
500 }
501 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800502 case GL_ETC1_RGB8_OES:
503 if (!context->getExtensions().compressedETC1RGB8Texture)
504 {
505 context->handleError(Error(GL_INVALID_ENUM));
506 return false;
507 }
508 break;
509 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800510 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
511 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
512 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
513 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800514 if (!context->getExtensions().lossyETCDecode)
515 {
516 context->handleError(Error(
517 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
518 return false;
519 }
520 break;
521 default:
522 context->handleError(
523 Error(GL_INVALID_ENUM,
524 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400525 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400526 }
Geoff Lang966c9402017-04-18 12:38:27 -0400527
528 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -0400529 {
Geoff Lang966c9402017-04-18 12:38:27 -0400530 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
531 height, texture->getWidth(target, level),
532 texture->getHeight(target, level)))
533 {
534 context->handleError(
535 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
536 return false;
537 }
538
539 if (format != actualInternalFormat)
540 {
541 context->handleError(Error(
542 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
543 return false;
544 }
545 }
546 else
547 {
548 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
549 {
550 context->handleError(
551 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
552 return false;
553 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400554 }
555 }
556 else
557 {
558 // validate <type> by itself (used as secondary key below)
559 switch (type)
560 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800561 case GL_UNSIGNED_BYTE:
562 case GL_UNSIGNED_SHORT_5_6_5:
563 case GL_UNSIGNED_SHORT_4_4_4_4:
564 case GL_UNSIGNED_SHORT_5_5_5_1:
565 case GL_UNSIGNED_SHORT:
566 case GL_UNSIGNED_INT:
567 case GL_UNSIGNED_INT_24_8_OES:
568 case GL_HALF_FLOAT_OES:
569 case GL_FLOAT:
570 break;
571 default:
572 context->handleError(Error(GL_INVALID_ENUM));
573 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400574 }
575
576 // validate <format> + <type> combinations
577 // - invalid <format> -> sets INVALID_ENUM
578 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
579 switch (format)
580 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800581 case GL_ALPHA:
582 case GL_LUMINANCE:
583 case GL_LUMINANCE_ALPHA:
584 switch (type)
585 {
586 case GL_UNSIGNED_BYTE:
587 case GL_FLOAT:
588 case GL_HALF_FLOAT_OES:
589 break;
590 default:
591 context->handleError(Error(GL_INVALID_OPERATION));
592 return false;
593 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400594 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800595 case GL_RED:
596 case GL_RG:
597 if (!context->getExtensions().textureRG)
598 {
599 context->handleError(Error(GL_INVALID_ENUM));
600 return false;
601 }
602 switch (type)
603 {
604 case GL_UNSIGNED_BYTE:
605 case GL_FLOAT:
606 case GL_HALF_FLOAT_OES:
607 break;
608 default:
609 context->handleError(Error(GL_INVALID_OPERATION));
610 return false;
611 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400612 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800613 case GL_RGB:
614 switch (type)
615 {
616 case GL_UNSIGNED_BYTE:
617 case GL_UNSIGNED_SHORT_5_6_5:
618 case GL_FLOAT:
619 case GL_HALF_FLOAT_OES:
620 break;
621 default:
622 context->handleError(Error(GL_INVALID_OPERATION));
623 return false;
624 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400625 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800626 case GL_RGBA:
627 switch (type)
628 {
629 case GL_UNSIGNED_BYTE:
630 case GL_UNSIGNED_SHORT_4_4_4_4:
631 case GL_UNSIGNED_SHORT_5_5_5_1:
632 case GL_FLOAT:
633 case GL_HALF_FLOAT_OES:
634 break;
635 default:
636 context->handleError(Error(GL_INVALID_OPERATION));
637 return false;
638 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400639 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800640 case GL_BGRA_EXT:
641 switch (type)
642 {
643 case GL_UNSIGNED_BYTE:
644 break;
645 default:
646 context->handleError(Error(GL_INVALID_OPERATION));
647 return false;
648 }
649 break;
650 case GL_SRGB_EXT:
651 case GL_SRGB_ALPHA_EXT:
652 if (!context->getExtensions().sRGB)
653 {
654 context->handleError(Error(GL_INVALID_ENUM));
655 return false;
656 }
657 switch (type)
658 {
659 case GL_UNSIGNED_BYTE:
660 break;
661 default:
662 context->handleError(Error(GL_INVALID_OPERATION));
663 return false;
664 }
665 break;
666 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
667 // handled below
668 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
669 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
670 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
671 break;
672 case GL_DEPTH_COMPONENT:
673 switch (type)
674 {
675 case GL_UNSIGNED_SHORT:
676 case GL_UNSIGNED_INT:
677 break;
678 default:
679 context->handleError(Error(GL_INVALID_OPERATION));
680 return false;
681 }
682 break;
683 case GL_DEPTH_STENCIL_OES:
684 switch (type)
685 {
686 case GL_UNSIGNED_INT_24_8_OES:
687 break;
688 default:
689 context->handleError(Error(GL_INVALID_OPERATION));
690 return false;
691 }
692 break;
693 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400694 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400695 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696 }
697
698 switch (format)
699 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800700 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
701 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
702 if (context->getExtensions().textureCompressionDXT1)
703 {
704 context->handleError(Error(GL_INVALID_OPERATION));
705 return false;
706 }
707 else
708 {
709 context->handleError(Error(GL_INVALID_ENUM));
710 return false;
711 }
712 break;
713 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
714 if (context->getExtensions().textureCompressionDXT3)
715 {
716 context->handleError(Error(GL_INVALID_OPERATION));
717 return false;
718 }
719 else
720 {
721 context->handleError(Error(GL_INVALID_ENUM));
722 return false;
723 }
724 break;
725 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
726 if (context->getExtensions().textureCompressionDXT5)
727 {
728 context->handleError(Error(GL_INVALID_OPERATION));
729 return false;
730 }
731 else
732 {
733 context->handleError(Error(GL_INVALID_ENUM));
734 return false;
735 }
736 break;
737 case GL_ETC1_RGB8_OES:
738 if (context->getExtensions().compressedETC1RGB8Texture)
739 {
740 context->handleError(Error(GL_INVALID_OPERATION));
741 return false;
742 }
743 else
744 {
745 context->handleError(Error(GL_INVALID_ENUM));
746 return false;
747 }
748 break;
749 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800750 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
751 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
752 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
753 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800754 if (context->getExtensions().lossyETCDecode)
755 {
756 context->handleError(
757 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -0800758 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +0800759 return false;
760 }
761 else
762 {
763 context->handleError(Error(
764 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
765 return false;
766 }
767 break;
768 case GL_DEPTH_COMPONENT:
769 case GL_DEPTH_STENCIL_OES:
770 if (!context->getExtensions().depthTextures)
771 {
772 context->handleError(Error(GL_INVALID_VALUE));
773 return false;
774 }
775 if (target != GL_TEXTURE_2D)
776 {
777 context->handleError(Error(GL_INVALID_OPERATION));
778 return false;
779 }
780 // OES_depth_texture supports loading depth data and multiple levels,
781 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +0800782 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 {
784 context->handleError(Error(GL_INVALID_OPERATION));
785 return false;
786 }
787 break;
788 default:
789 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 }
791
792 if (type == GL_FLOAT)
793 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400794 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 {
Jamie Madill437fa652016-05-03 15:13:24 -0400796 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400797 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 }
799 }
800 else if (type == GL_HALF_FLOAT_OES)
801 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400802 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 {
Jamie Madill437fa652016-05-03 15:13:24 -0400804 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400805 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400806 }
807 }
808 }
809
Geoff Langff5b2d52016-09-07 11:32:23 -0400810 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
811 imageSize))
812 {
813 return false;
814 }
815
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400816 return true;
817}
818
He Yunchaoced53ae2016-11-29 15:00:51 +0800819bool ValidateES2TexStorageParameters(Context *context,
820 GLenum target,
821 GLsizei levels,
822 GLenum internalformat,
823 GLsizei width,
824 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825{
826 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
827 {
Jamie Madill437fa652016-05-03 15:13:24 -0400828 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 }
831
832 if (width < 1 || height < 1 || levels < 1)
833 {
Jamie Madill437fa652016-05-03 15:13:24 -0400834 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400836 }
837
838 if (target == GL_TEXTURE_CUBE_MAP && width != height)
839 {
Jamie Madill437fa652016-05-03 15:13:24 -0400840 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400841 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 }
843
844 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
845 {
Jamie Madill437fa652016-05-03 15:13:24 -0400846 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400847 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848 }
849
Geoff Langca271392017-04-05 12:30:00 -0400850 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400851 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400852 {
Jamie Madill437fa652016-05-03 15:13:24 -0400853 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400854 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 }
856
Geoff Langaae65a42014-05-26 12:43:44 -0400857 const gl::Caps &caps = context->getCaps();
858
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 switch (target)
860 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800861 case GL_TEXTURE_2D:
862 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
863 static_cast<GLuint>(height) > caps.max2DTextureSize)
864 {
865 context->handleError(Error(GL_INVALID_VALUE));
866 return false;
867 }
868 break;
869 case GL_TEXTURE_CUBE_MAP:
870 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
871 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
872 {
873 context->handleError(Error(GL_INVALID_VALUE));
874 return false;
875 }
876 break;
877 default:
878 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400879 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400880 }
881
Geoff Langc0b9ef42014-07-02 10:02:37 -0400882 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400883 {
884 if (!gl::isPow2(width) || !gl::isPow2(height))
885 {
Jamie Madill437fa652016-05-03 15:13:24 -0400886 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400887 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400888 }
889 }
890
891 switch (internalformat)
892 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800893 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
894 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
895 if (!context->getExtensions().textureCompressionDXT1)
896 {
897 context->handleError(Error(GL_INVALID_ENUM));
898 return false;
899 }
900 break;
901 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
902 if (!context->getExtensions().textureCompressionDXT3)
903 {
904 context->handleError(Error(GL_INVALID_ENUM));
905 return false;
906 }
907 break;
908 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
909 if (!context->getExtensions().textureCompressionDXT5)
910 {
911 context->handleError(Error(GL_INVALID_ENUM));
912 return false;
913 }
914 break;
915 case GL_ETC1_RGB8_OES:
916 if (!context->getExtensions().compressedETC1RGB8Texture)
917 {
918 context->handleError(Error(GL_INVALID_ENUM));
919 return false;
920 }
921 break;
922 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800923 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
924 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
925 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
926 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800927 if (!context->getExtensions().lossyETCDecode)
928 {
929 context->handleError(
930 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
931 return false;
932 }
933 break;
934 case GL_RGBA32F_EXT:
935 case GL_RGB32F_EXT:
936 case GL_ALPHA32F_EXT:
937 case GL_LUMINANCE32F_EXT:
938 case GL_LUMINANCE_ALPHA32F_EXT:
939 if (!context->getExtensions().textureFloat)
940 {
941 context->handleError(Error(GL_INVALID_ENUM));
942 return false;
943 }
944 break;
945 case GL_RGBA16F_EXT:
946 case GL_RGB16F_EXT:
947 case GL_ALPHA16F_EXT:
948 case GL_LUMINANCE16F_EXT:
949 case GL_LUMINANCE_ALPHA16F_EXT:
950 if (!context->getExtensions().textureHalfFloat)
951 {
952 context->handleError(Error(GL_INVALID_ENUM));
953 return false;
954 }
955 break;
956 case GL_R8_EXT:
957 case GL_RG8_EXT:
958 case GL_R16F_EXT:
959 case GL_RG16F_EXT:
960 case GL_R32F_EXT:
961 case GL_RG32F_EXT:
962 if (!context->getExtensions().textureRG)
963 {
964 context->handleError(Error(GL_INVALID_ENUM));
965 return false;
966 }
967 break;
968 case GL_DEPTH_COMPONENT16:
969 case GL_DEPTH_COMPONENT32_OES:
970 case GL_DEPTH24_STENCIL8_OES:
971 if (!context->getExtensions().depthTextures)
972 {
973 context->handleError(Error(GL_INVALID_ENUM));
974 return false;
975 }
976 if (target != GL_TEXTURE_2D)
977 {
978 context->handleError(Error(GL_INVALID_OPERATION));
979 return false;
980 }
981 // ANGLE_depth_texture only supports 1-level textures
982 if (levels != 1)
983 {
984 context->handleError(Error(GL_INVALID_OPERATION));
985 return false;
986 }
987 break;
988 default:
989 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400990 }
991
Geoff Lang691e58c2014-12-19 17:03:25 -0500992 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400993 if (!texture || texture->id() == 0)
994 {
Jamie Madill437fa652016-05-03 15:13:24 -0400995 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400996 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997 }
998
Geoff Lang69cce582015-09-17 13:20:36 -0400999 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000 {
Jamie Madill437fa652016-05-03 15:13:24 -04001001 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001002 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001003 }
1004
1005 return true;
1006}
1007
He Yunchaoced53ae2016-11-29 15:00:51 +08001008bool ValidateDiscardFramebufferEXT(Context *context,
1009 GLenum target,
1010 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001011 const GLenum *attachments)
1012{
Jamie Madillc29968b2016-01-20 11:17:23 -05001013 if (!context->getExtensions().discardFramebuffer)
1014 {
Jamie Madill437fa652016-05-03 15:13:24 -04001015 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001016 return false;
1017 }
1018
Austin Kinross08332632015-05-05 13:35:47 -07001019 bool defaultFramebuffer = false;
1020
1021 switch (target)
1022 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001023 case GL_FRAMEBUFFER:
1024 defaultFramebuffer =
1025 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1026 break;
1027 default:
1028 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1029 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001030 }
1031
He Yunchaoced53ae2016-11-29 15:00:51 +08001032 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1033 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001034}
1035
Austin Kinrossbc781f32015-10-26 09:27:38 -07001036bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1037{
1038 if (!context->getExtensions().vertexArrayObject)
1039 {
Jamie Madill437fa652016-05-03 15:13:24 -04001040 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001041 return false;
1042 }
1043
1044 return ValidateBindVertexArrayBase(context, array);
1045}
1046
1047bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1048{
1049 if (!context->getExtensions().vertexArrayObject)
1050 {
Jamie Madill437fa652016-05-03 15:13:24 -04001051 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001052 return false;
1053 }
1054
Olli Etuaho41997e72016-03-10 13:38:39 +02001055 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001056}
1057
1058bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1059{
1060 if (!context->getExtensions().vertexArrayObject)
1061 {
Jamie Madill437fa652016-05-03 15:13:24 -04001062 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001063 return false;
1064 }
1065
Olli Etuaho41997e72016-03-10 13:38:39 +02001066 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001067}
1068
1069bool ValidateIsVertexArrayOES(Context *context)
1070{
1071 if (!context->getExtensions().vertexArrayObject)
1072 {
Jamie Madill437fa652016-05-03 15:13:24 -04001073 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001074 return false;
1075 }
1076
1077 return true;
1078}
Geoff Langc5629752015-12-07 16:29:04 -05001079
1080bool ValidateProgramBinaryOES(Context *context,
1081 GLuint program,
1082 GLenum binaryFormat,
1083 const void *binary,
1084 GLint length)
1085{
1086 if (!context->getExtensions().getProgramBinary)
1087 {
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001089 return false;
1090 }
1091
1092 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1093}
1094
1095bool ValidateGetProgramBinaryOES(Context *context,
1096 GLuint program,
1097 GLsizei bufSize,
1098 GLsizei *length,
1099 GLenum *binaryFormat,
1100 void *binary)
1101{
1102 if (!context->getExtensions().getProgramBinary)
1103 {
Jamie Madill437fa652016-05-03 15:13:24 -04001104 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001105 return false;
1106 }
1107
1108 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1109}
Geoff Lange102fee2015-12-10 11:23:30 -05001110
Geoff Lang70d0f492015-12-10 17:45:46 -05001111static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1112{
1113 switch (source)
1114 {
1115 case GL_DEBUG_SOURCE_API:
1116 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1117 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1118 case GL_DEBUG_SOURCE_OTHER:
1119 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1120 return !mustBeThirdPartyOrApplication;
1121
1122 case GL_DEBUG_SOURCE_THIRD_PARTY:
1123 case GL_DEBUG_SOURCE_APPLICATION:
1124 return true;
1125
1126 default:
1127 return false;
1128 }
1129}
1130
1131static bool ValidDebugType(GLenum type)
1132{
1133 switch (type)
1134 {
1135 case GL_DEBUG_TYPE_ERROR:
1136 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1137 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1138 case GL_DEBUG_TYPE_PERFORMANCE:
1139 case GL_DEBUG_TYPE_PORTABILITY:
1140 case GL_DEBUG_TYPE_OTHER:
1141 case GL_DEBUG_TYPE_MARKER:
1142 case GL_DEBUG_TYPE_PUSH_GROUP:
1143 case GL_DEBUG_TYPE_POP_GROUP:
1144 return true;
1145
1146 default:
1147 return false;
1148 }
1149}
1150
1151static bool ValidDebugSeverity(GLenum severity)
1152{
1153 switch (severity)
1154 {
1155 case GL_DEBUG_SEVERITY_HIGH:
1156 case GL_DEBUG_SEVERITY_MEDIUM:
1157 case GL_DEBUG_SEVERITY_LOW:
1158 case GL_DEBUG_SEVERITY_NOTIFICATION:
1159 return true;
1160
1161 default:
1162 return false;
1163 }
1164}
1165
Geoff Lange102fee2015-12-10 11:23:30 -05001166bool ValidateDebugMessageControlKHR(Context *context,
1167 GLenum source,
1168 GLenum type,
1169 GLenum severity,
1170 GLsizei count,
1171 const GLuint *ids,
1172 GLboolean enabled)
1173{
1174 if (!context->getExtensions().debug)
1175 {
Jamie Madill437fa652016-05-03 15:13:24 -04001176 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001177 return false;
1178 }
1179
Geoff Lang70d0f492015-12-10 17:45:46 -05001180 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1181 {
Jamie Madill437fa652016-05-03 15:13:24 -04001182 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001183 return false;
1184 }
1185
1186 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001189 return false;
1190 }
1191
1192 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1193 {
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001195 return false;
1196 }
1197
1198 if (count > 0)
1199 {
1200 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1201 {
Jamie Madill437fa652016-05-03 15:13:24 -04001202 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001203 GL_INVALID_OPERATION,
1204 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1205 return false;
1206 }
1207
1208 if (severity != GL_DONT_CARE)
1209 {
Jamie Madill437fa652016-05-03 15:13:24 -04001210 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001211 Error(GL_INVALID_OPERATION,
1212 "If count is greater than zero, severity must be GL_DONT_CARE."));
1213 return false;
1214 }
1215 }
1216
Geoff Lange102fee2015-12-10 11:23:30 -05001217 return true;
1218}
1219
1220bool ValidateDebugMessageInsertKHR(Context *context,
1221 GLenum source,
1222 GLenum type,
1223 GLuint id,
1224 GLenum severity,
1225 GLsizei length,
1226 const GLchar *buf)
1227{
1228 if (!context->getExtensions().debug)
1229 {
Jamie Madill437fa652016-05-03 15:13:24 -04001230 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001231 return false;
1232 }
1233
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001234 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001235 {
1236 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1237 // not generate an error.
1238 return false;
1239 }
1240
1241 if (!ValidDebugSeverity(severity))
1242 {
Jamie Madill437fa652016-05-03 15:13:24 -04001243 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001244 return false;
1245 }
1246
1247 if (!ValidDebugType(type))
1248 {
Jamie Madill437fa652016-05-03 15:13:24 -04001249 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001250 return false;
1251 }
1252
1253 if (!ValidDebugSource(source, true))
1254 {
Jamie Madill437fa652016-05-03 15:13:24 -04001255 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001256 return false;
1257 }
1258
1259 size_t messageLength = (length < 0) ? strlen(buf) : length;
1260 if (messageLength > context->getExtensions().maxDebugMessageLength)
1261 {
Jamie Madill437fa652016-05-03 15:13:24 -04001262 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001263 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1264 return false;
1265 }
1266
Geoff Lange102fee2015-12-10 11:23:30 -05001267 return true;
1268}
1269
1270bool ValidateDebugMessageCallbackKHR(Context *context,
1271 GLDEBUGPROCKHR callback,
1272 const void *userParam)
1273{
1274 if (!context->getExtensions().debug)
1275 {
Jamie Madill437fa652016-05-03 15:13:24 -04001276 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001277 return false;
1278 }
1279
Geoff Lange102fee2015-12-10 11:23:30 -05001280 return true;
1281}
1282
1283bool ValidateGetDebugMessageLogKHR(Context *context,
1284 GLuint count,
1285 GLsizei bufSize,
1286 GLenum *sources,
1287 GLenum *types,
1288 GLuint *ids,
1289 GLenum *severities,
1290 GLsizei *lengths,
1291 GLchar *messageLog)
1292{
1293 if (!context->getExtensions().debug)
1294 {
Jamie Madill437fa652016-05-03 15:13:24 -04001295 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001296 return false;
1297 }
1298
Geoff Lang70d0f492015-12-10 17:45:46 -05001299 if (bufSize < 0 && messageLog != nullptr)
1300 {
Jamie Madill437fa652016-05-03 15:13:24 -04001301 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001302 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1303 return false;
1304 }
1305
Geoff Lange102fee2015-12-10 11:23:30 -05001306 return true;
1307}
1308
1309bool ValidatePushDebugGroupKHR(Context *context,
1310 GLenum source,
1311 GLuint id,
1312 GLsizei length,
1313 const GLchar *message)
1314{
1315 if (!context->getExtensions().debug)
1316 {
Jamie Madill437fa652016-05-03 15:13:24 -04001317 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001318 return false;
1319 }
1320
Geoff Lang70d0f492015-12-10 17:45:46 -05001321 if (!ValidDebugSource(source, true))
1322 {
Jamie Madill437fa652016-05-03 15:13:24 -04001323 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001324 return false;
1325 }
1326
1327 size_t messageLength = (length < 0) ? strlen(message) : length;
1328 if (messageLength > context->getExtensions().maxDebugMessageLength)
1329 {
Jamie Madill437fa652016-05-03 15:13:24 -04001330 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001331 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1332 return false;
1333 }
1334
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001335 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001336 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1337 {
Jamie Madill437fa652016-05-03 15:13:24 -04001338 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001339 Error(GL_STACK_OVERFLOW,
1340 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1341 return false;
1342 }
1343
Geoff Lange102fee2015-12-10 11:23:30 -05001344 return true;
1345}
1346
1347bool ValidatePopDebugGroupKHR(Context *context)
1348{
1349 if (!context->getExtensions().debug)
1350 {
Jamie Madill437fa652016-05-03 15:13:24 -04001351 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001352 return false;
1353 }
1354
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001355 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001356 if (currentStackSize <= 1)
1357 {
Jamie Madill437fa652016-05-03 15:13:24 -04001358 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001359 return false;
1360 }
1361
1362 return true;
1363}
1364
1365static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1366{
1367 switch (identifier)
1368 {
1369 case GL_BUFFER:
1370 if (context->getBuffer(name) == nullptr)
1371 {
Jamie Madill437fa652016-05-03 15:13:24 -04001372 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001373 return false;
1374 }
1375 return true;
1376
1377 case GL_SHADER:
1378 if (context->getShader(name) == nullptr)
1379 {
Jamie Madill437fa652016-05-03 15:13:24 -04001380 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001381 return false;
1382 }
1383 return true;
1384
1385 case GL_PROGRAM:
1386 if (context->getProgram(name) == nullptr)
1387 {
Jamie Madill437fa652016-05-03 15:13:24 -04001388 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001389 return false;
1390 }
1391 return true;
1392
1393 case GL_VERTEX_ARRAY:
1394 if (context->getVertexArray(name) == nullptr)
1395 {
Jamie Madill437fa652016-05-03 15:13:24 -04001396 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001397 return false;
1398 }
1399 return true;
1400
1401 case GL_QUERY:
1402 if (context->getQuery(name) == nullptr)
1403 {
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001405 return false;
1406 }
1407 return true;
1408
1409 case GL_TRANSFORM_FEEDBACK:
1410 if (context->getTransformFeedback(name) == nullptr)
1411 {
Jamie Madill437fa652016-05-03 15:13:24 -04001412 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001413 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1414 return false;
1415 }
1416 return true;
1417
1418 case GL_SAMPLER:
1419 if (context->getSampler(name) == nullptr)
1420 {
Jamie Madill437fa652016-05-03 15:13:24 -04001421 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001422 return false;
1423 }
1424 return true;
1425
1426 case GL_TEXTURE:
1427 if (context->getTexture(name) == nullptr)
1428 {
Jamie Madill437fa652016-05-03 15:13:24 -04001429 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001430 return false;
1431 }
1432 return true;
1433
1434 case GL_RENDERBUFFER:
1435 if (context->getRenderbuffer(name) == nullptr)
1436 {
Jamie Madill437fa652016-05-03 15:13:24 -04001437 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001438 return false;
1439 }
1440 return true;
1441
1442 case GL_FRAMEBUFFER:
1443 if (context->getFramebuffer(name) == nullptr)
1444 {
Jamie Madill437fa652016-05-03 15:13:24 -04001445 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001446 return false;
1447 }
1448 return true;
1449
1450 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001451 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001452 return false;
1453 }
Geoff Lange102fee2015-12-10 11:23:30 -05001454}
1455
Martin Radev9d901792016-07-15 15:58:58 +03001456static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1457{
1458 size_t labelLength = 0;
1459
1460 if (length < 0)
1461 {
1462 if (label != nullptr)
1463 {
1464 labelLength = strlen(label);
1465 }
1466 }
1467 else
1468 {
1469 labelLength = static_cast<size_t>(length);
1470 }
1471
1472 if (labelLength > context->getExtensions().maxLabelLength)
1473 {
1474 context->handleError(
1475 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1476 return false;
1477 }
1478
1479 return true;
1480}
1481
Geoff Lange102fee2015-12-10 11:23:30 -05001482bool ValidateObjectLabelKHR(Context *context,
1483 GLenum identifier,
1484 GLuint name,
1485 GLsizei length,
1486 const GLchar *label)
1487{
1488 if (!context->getExtensions().debug)
1489 {
Jamie Madill437fa652016-05-03 15:13:24 -04001490 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001491 return false;
1492 }
1493
Geoff Lang70d0f492015-12-10 17:45:46 -05001494 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1495 {
1496 return false;
1497 }
1498
Martin Radev9d901792016-07-15 15:58:58 +03001499 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001500 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001501 return false;
1502 }
1503
Geoff Lange102fee2015-12-10 11:23:30 -05001504 return true;
1505}
1506
1507bool ValidateGetObjectLabelKHR(Context *context,
1508 GLenum identifier,
1509 GLuint name,
1510 GLsizei bufSize,
1511 GLsizei *length,
1512 GLchar *label)
1513{
1514 if (!context->getExtensions().debug)
1515 {
Jamie Madill437fa652016-05-03 15:13:24 -04001516 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001517 return false;
1518 }
1519
Geoff Lang70d0f492015-12-10 17:45:46 -05001520 if (bufSize < 0)
1521 {
Jamie Madill437fa652016-05-03 15:13:24 -04001522 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001523 return false;
1524 }
1525
1526 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1527 {
1528 return false;
1529 }
1530
Martin Radev9d901792016-07-15 15:58:58 +03001531 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001532}
1533
1534static bool ValidateObjectPtrName(Context *context, const void *ptr)
1535{
1536 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1537 {
Jamie Madill437fa652016-05-03 15:13:24 -04001538 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001539 return false;
1540 }
1541
Geoff Lange102fee2015-12-10 11:23:30 -05001542 return true;
1543}
1544
1545bool ValidateObjectPtrLabelKHR(Context *context,
1546 const void *ptr,
1547 GLsizei length,
1548 const GLchar *label)
1549{
1550 if (!context->getExtensions().debug)
1551 {
Jamie Madill437fa652016-05-03 15:13:24 -04001552 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001553 return false;
1554 }
1555
Geoff Lang70d0f492015-12-10 17:45:46 -05001556 if (!ValidateObjectPtrName(context, ptr))
1557 {
1558 return false;
1559 }
1560
Martin Radev9d901792016-07-15 15:58:58 +03001561 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001562 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001563 return false;
1564 }
1565
Geoff Lange102fee2015-12-10 11:23:30 -05001566 return true;
1567}
1568
1569bool ValidateGetObjectPtrLabelKHR(Context *context,
1570 const void *ptr,
1571 GLsizei bufSize,
1572 GLsizei *length,
1573 GLchar *label)
1574{
1575 if (!context->getExtensions().debug)
1576 {
Jamie Madill437fa652016-05-03 15:13:24 -04001577 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001578 return false;
1579 }
1580
Geoff Lang70d0f492015-12-10 17:45:46 -05001581 if (bufSize < 0)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 return false;
1585 }
1586
1587 if (!ValidateObjectPtrName(context, ptr))
1588 {
1589 return false;
1590 }
1591
Martin Radev9d901792016-07-15 15:58:58 +03001592 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001593}
1594
1595bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1596{
1597 if (!context->getExtensions().debug)
1598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001600 return false;
1601 }
1602
Geoff Lang70d0f492015-12-10 17:45:46 -05001603 // TODO: represent this in Context::getQueryParameterInfo.
1604 switch (pname)
1605 {
1606 case GL_DEBUG_CALLBACK_FUNCTION:
1607 case GL_DEBUG_CALLBACK_USER_PARAM:
1608 break;
1609
1610 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001611 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001612 return false;
1613 }
1614
Geoff Lange102fee2015-12-10 11:23:30 -05001615 return true;
1616}
Jamie Madillc29968b2016-01-20 11:17:23 -05001617
1618bool ValidateBlitFramebufferANGLE(Context *context,
1619 GLint srcX0,
1620 GLint srcY0,
1621 GLint srcX1,
1622 GLint srcY1,
1623 GLint dstX0,
1624 GLint dstY0,
1625 GLint dstX1,
1626 GLint dstY1,
1627 GLbitfield mask,
1628 GLenum filter)
1629{
1630 if (!context->getExtensions().framebufferBlit)
1631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001633 return false;
1634 }
1635
1636 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1637 {
1638 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001640 GL_INVALID_OPERATION,
1641 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1642 return false;
1643 }
1644
1645 if (filter == GL_LINEAR)
1646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001648 return false;
1649 }
1650
Jamie Madill51f40ec2016-06-15 14:06:00 -04001651 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1652 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001653
1654 if (mask & GL_COLOR_BUFFER_BIT)
1655 {
1656 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1657 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1658
1659 if (readColorAttachment && drawColorAttachment)
1660 {
1661 if (!(readColorAttachment->type() == GL_TEXTURE &&
1662 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1663 readColorAttachment->type() != GL_RENDERBUFFER &&
1664 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1665 {
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001667 return false;
1668 }
1669
Geoff Langa15472a2015-08-11 11:48:03 -04001670 for (size_t drawbufferIdx = 0;
1671 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001672 {
Geoff Langa15472a2015-08-11 11:48:03 -04001673 const FramebufferAttachment *attachment =
1674 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1675 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001676 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001677 if (!(attachment->type() == GL_TEXTURE &&
1678 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1679 attachment->type() != GL_RENDERBUFFER &&
1680 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1681 {
Jamie Madill437fa652016-05-03 15:13:24 -04001682 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001683 return false;
1684 }
1685
1686 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001687 if (!Format::SameSized(attachment->getFormat(),
1688 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001691 return false;
1692 }
1693 }
1694 }
1695
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001696 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001697 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1698 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1699 {
Jamie Madill437fa652016-05-03 15:13:24 -04001700 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001701 return false;
1702 }
1703 }
1704 }
1705
1706 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1707 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1708 for (size_t i = 0; i < 2; i++)
1709 {
1710 if (mask & masks[i])
1711 {
1712 const FramebufferAttachment *readBuffer =
1713 readFramebuffer->getAttachment(attachments[i]);
1714 const FramebufferAttachment *drawBuffer =
1715 drawFramebuffer->getAttachment(attachments[i]);
1716
1717 if (readBuffer && drawBuffer)
1718 {
1719 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1720 dstX0, dstY0, dstX1, dstY1))
1721 {
1722 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05001723 context->handleError(Error(GL_INVALID_OPERATION,
1724 "Only whole-buffer depth and stencil blits are "
1725 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 return false;
1727 }
1728
1729 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001732 return false;
1733 }
1734 }
1735 }
1736 }
1737
1738 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1739 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001740}
Jamie Madillc29968b2016-01-20 11:17:23 -05001741
1742bool ValidateClear(ValidationContext *context, GLbitfield mask)
1743{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001744 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001745 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 return false;
1749 }
1750
1751 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1752 {
Jamie Madill437fa652016-05-03 15:13:24 -04001753 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001754 return false;
1755 }
1756
Geoff Lang76e65652017-03-27 14:58:02 -04001757 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
1758 {
1759 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1760 GL_SIGNED_NORMALIZED};
1761
1762 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
1763 drawBufferIdx++)
1764 {
1765 if (!ValidateWebGLFramebufferAttachmentClearType(
1766 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
1767 {
1768 return false;
1769 }
1770 }
1771 }
1772
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 return true;
1774}
1775
1776bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1777{
1778 if (!context->getExtensions().drawBuffers)
1779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 return ValidateDrawBuffersBase(context, n, bufs);
1785}
1786
Jamie Madill73a84962016-02-12 09:27:23 -05001787bool ValidateTexImage2D(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 const GLvoid *pixels)
1797{
Martin Radev1be913c2016-07-11 17:59:16 +03001798 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001799 {
1800 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001801 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001802 }
1803
Martin Radev1be913c2016-07-11 17:59:16 +03001804 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001805 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001806 0, 0, width, height, 1, border, format, type, -1,
1807 pixels);
1808}
1809
1810bool ValidateTexImage2DRobust(Context *context,
1811 GLenum target,
1812 GLint level,
1813 GLint internalformat,
1814 GLsizei width,
1815 GLsizei height,
1816 GLint border,
1817 GLenum format,
1818 GLenum type,
1819 GLsizei bufSize,
1820 const GLvoid *pixels)
1821{
1822 if (!ValidateRobustEntryPoint(context, bufSize))
1823 {
1824 return false;
1825 }
1826
1827 if (context->getClientMajorVersion() < 3)
1828 {
1829 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1830 0, 0, width, height, border, format, type, bufSize,
1831 pixels);
1832 }
1833
1834 ASSERT(context->getClientMajorVersion() >= 3);
1835 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1836 0, 0, width, height, 1, border, format, type, bufSize,
1837 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001838}
1839
1840bool ValidateTexSubImage2D(Context *context,
1841 GLenum target,
1842 GLint level,
1843 GLint xoffset,
1844 GLint yoffset,
1845 GLsizei width,
1846 GLsizei height,
1847 GLenum format,
1848 GLenum type,
1849 const GLvoid *pixels)
1850{
1851
Martin Radev1be913c2016-07-11 17:59:16 +03001852 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001853 {
1854 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001855 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001856 }
1857
Martin Radev1be913c2016-07-11 17:59:16 +03001858 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001859 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001860 yoffset, 0, width, height, 1, 0, format, type, -1,
1861 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001862}
1863
Geoff Langc52f6f12016-10-14 10:18:00 -04001864bool ValidateTexSubImage2DRobustANGLE(Context *context,
1865 GLenum target,
1866 GLint level,
1867 GLint xoffset,
1868 GLint yoffset,
1869 GLsizei width,
1870 GLsizei height,
1871 GLenum format,
1872 GLenum type,
1873 GLsizei bufSize,
1874 const GLvoid *pixels)
1875{
1876 if (!ValidateRobustEntryPoint(context, bufSize))
1877 {
1878 return false;
1879 }
1880
1881 if (context->getClientMajorVersion() < 3)
1882 {
1883 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1884 yoffset, width, height, 0, format, type, bufSize,
1885 pixels);
1886 }
1887
1888 ASSERT(context->getClientMajorVersion() >= 3);
1889 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1890 yoffset, 0, width, height, 1, 0, format, type, bufSize,
1891 pixels);
1892}
1893
Jamie Madill73a84962016-02-12 09:27:23 -05001894bool ValidateCompressedTexImage2D(Context *context,
1895 GLenum target,
1896 GLint level,
1897 GLenum internalformat,
1898 GLsizei width,
1899 GLsizei height,
1900 GLint border,
1901 GLsizei imageSize,
1902 const GLvoid *data)
1903{
Martin Radev1be913c2016-07-11 17:59:16 +03001904 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001905 {
1906 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001907 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001908 {
1909 return false;
1910 }
1911 }
1912 else
1913 {
Martin Radev1be913c2016-07-11 17:59:16 +03001914 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001915 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001916 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001917 data))
1918 {
1919 return false;
1920 }
1921 }
1922
Geoff Langca271392017-04-05 12:30:00 -04001923 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001924 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001925 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001926 if (blockSizeOrErr.isError())
1927 {
1928 context->handleError(blockSizeOrErr.getError());
1929 return false;
1930 }
1931
1932 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001933 {
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001935 return false;
1936 }
1937
1938 return true;
1939}
1940
Corentin Wallezb2931602017-04-11 15:58:57 -04001941bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
1942 GLenum target,
1943 GLint level,
1944 GLenum internalformat,
1945 GLsizei width,
1946 GLsizei height,
1947 GLint border,
1948 GLsizei imageSize,
1949 GLsizei dataSize,
1950 const GLvoid *data)
1951{
1952 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1953 {
1954 return false;
1955 }
1956
1957 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
1958 border, imageSize, data);
1959}
1960bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
1961 GLenum target,
1962 GLint level,
1963 GLint xoffset,
1964 GLint yoffset,
1965 GLsizei width,
1966 GLsizei height,
1967 GLenum format,
1968 GLsizei imageSize,
1969 GLsizei dataSize,
1970 const GLvoid *data)
1971{
1972 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1973 {
1974 return false;
1975 }
1976
1977 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
1978 format, imageSize, data);
1979}
1980
Jamie Madill73a84962016-02-12 09:27:23 -05001981bool ValidateCompressedTexSubImage2D(Context *context,
1982 GLenum target,
1983 GLint level,
1984 GLint xoffset,
1985 GLint yoffset,
1986 GLsizei width,
1987 GLsizei height,
1988 GLenum format,
1989 GLsizei imageSize,
1990 const GLvoid *data)
1991{
Martin Radev1be913c2016-07-11 17:59:16 +03001992 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001993 {
1994 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04001995 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001996 {
1997 return false;
1998 }
1999 }
2000 else
2001 {
Martin Radev1be913c2016-07-11 17:59:16 +03002002 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002003 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002004 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002005 data))
2006 {
2007 return false;
2008 }
2009 }
2010
Geoff Langca271392017-04-05 12:30:00 -04002011 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002012 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002013 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002014 if (blockSizeOrErr.isError())
2015 {
2016 context->handleError(blockSizeOrErr.getError());
2017 return false;
2018 }
2019
2020 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002021 {
Jamie Madill437fa652016-05-03 15:13:24 -04002022 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002023 return false;
2024 }
2025
2026 return true;
2027}
2028
Olli Etuaho4f667482016-03-30 15:56:35 +03002029bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2030{
Geoff Lang496c02d2016-10-20 11:38:11 -07002031 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002032}
2033
2034bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2035{
2036 if (!context->getExtensions().mapBuffer)
2037 {
Jamie Madill437fa652016-05-03 15:13:24 -04002038 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002039 return false;
2040 }
2041
2042 if (!ValidBufferTarget(context, target))
2043 {
Jamie Madill437fa652016-05-03 15:13:24 -04002044 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002045 return false;
2046 }
2047
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002048 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002049
2050 if (buffer == nullptr)
2051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002053 return false;
2054 }
2055
2056 if (access != GL_WRITE_ONLY_OES)
2057 {
Jamie Madill437fa652016-05-03 15:13:24 -04002058 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002059 return false;
2060 }
2061
2062 if (buffer->isMapped())
2063 {
Jamie Madill437fa652016-05-03 15:13:24 -04002064 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002065 return false;
2066 }
2067
2068 return true;
2069}
2070
2071bool ValidateUnmapBufferOES(Context *context, GLenum target)
2072{
2073 if (!context->getExtensions().mapBuffer)
2074 {
Jamie Madill437fa652016-05-03 15:13:24 -04002075 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002076 return false;
2077 }
2078
2079 return ValidateUnmapBufferBase(context, target);
2080}
2081
2082bool ValidateMapBufferRangeEXT(Context *context,
2083 GLenum target,
2084 GLintptr offset,
2085 GLsizeiptr length,
2086 GLbitfield access)
2087{
2088 if (!context->getExtensions().mapBufferRange)
2089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002091 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2092 return false;
2093 }
2094
2095 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2096}
2097
2098bool ValidateFlushMappedBufferRangeEXT(Context *context,
2099 GLenum target,
2100 GLintptr offset,
2101 GLsizeiptr length)
2102{
2103 if (!context->getExtensions().mapBufferRange)
2104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002106 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2107 return false;
2108 }
2109
2110 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2111}
2112
Ian Ewell54f87462016-03-10 13:47:21 -05002113bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2114{
2115 Texture *textureObject = context->getTexture(texture);
2116 if (textureObject && textureObject->getTarget() != target && texture != 0)
2117 {
Jamie Madill437fa652016-05-03 15:13:24 -04002118 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002119 return false;
2120 }
2121
Geoff Langf41a7152016-09-19 15:11:17 -04002122 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2123 !context->isTextureGenerated(texture))
2124 {
2125 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2126 return false;
2127 }
2128
Ian Ewell54f87462016-03-10 13:47:21 -05002129 switch (target)
2130 {
2131 case GL_TEXTURE_2D:
2132 case GL_TEXTURE_CUBE_MAP:
2133 break;
2134
2135 case GL_TEXTURE_3D:
2136 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002137 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002138 {
Jamie Madill437fa652016-05-03 15:13:24 -04002139 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002140 return false;
2141 }
2142 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002143
2144 case GL_TEXTURE_2D_MULTISAMPLE:
2145 if (context->getClientVersion() < Version(3, 1))
2146 {
2147 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2148 return false;
2149 }
Geoff Lang3b573612016-10-31 14:08:10 -04002150 break;
2151
Ian Ewell54f87462016-03-10 13:47:21 -05002152 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002153 if (!context->getExtensions().eglImageExternal &&
2154 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002157 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2158 return false;
2159 }
2160 break;
2161 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002162 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002163 return false;
2164 }
2165
2166 return true;
2167}
2168
Geoff Langd8605522016-04-13 10:19:12 -04002169bool ValidateBindUniformLocationCHROMIUM(Context *context,
2170 GLuint program,
2171 GLint location,
2172 const GLchar *name)
2173{
2174 if (!context->getExtensions().bindUniformLocation)
2175 {
Jamie Madill437fa652016-05-03 15:13:24 -04002176 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002177 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2178 return false;
2179 }
2180
2181 Program *programObject = GetValidProgram(context, program);
2182 if (!programObject)
2183 {
2184 return false;
2185 }
2186
2187 if (location < 0)
2188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002190 return false;
2191 }
2192
2193 const Caps &caps = context->getCaps();
2194 if (static_cast<size_t>(location) >=
2195 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2196 {
Jamie Madill437fa652016-05-03 15:13:24 -04002197 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002198 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2199 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2200 return false;
2201 }
2202
2203 if (strncmp(name, "gl_", 3) == 0)
2204 {
Jamie Madill437fa652016-05-03 15:13:24 -04002205 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002206 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2207 return false;
2208 }
2209
2210 return true;
2211}
2212
Jamie Madille2e406c2016-06-02 13:04:10 -04002213bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002214{
2215 if (!context->getExtensions().framebufferMixedSamples)
2216 {
2217 context->handleError(
2218 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2219 return false;
2220 }
2221 switch (components)
2222 {
2223 case GL_RGB:
2224 case GL_RGBA:
2225 case GL_ALPHA:
2226 case GL_NONE:
2227 break;
2228 default:
2229 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002230 Error(GL_INVALID_ENUM,
2231 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002232 return false;
2233 }
2234
2235 return true;
2236}
2237
Sami Väisänene45e53b2016-05-25 10:36:04 +03002238// CHROMIUM_path_rendering
2239
2240bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2241{
2242 if (!context->getExtensions().pathRendering)
2243 {
2244 context->handleError(
2245 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2246 return false;
2247 }
2248 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2249 {
2250 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2251 return false;
2252 }
2253 if (matrix == nullptr)
2254 {
2255 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2256 return false;
2257 }
2258 return true;
2259}
2260
2261bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2262{
2263 if (!context->getExtensions().pathRendering)
2264 {
2265 context->handleError(
2266 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2267 return false;
2268 }
2269 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2270 {
2271 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2272 return false;
2273 }
2274 return true;
2275}
2276
2277bool ValidateGenPaths(Context *context, GLsizei range)
2278{
2279 if (!context->getExtensions().pathRendering)
2280 {
2281 context->handleError(
2282 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2283 return false;
2284 }
2285
2286 // range = 0 is undefined in NV_path_rendering.
2287 // we add stricter semantic check here and require a non zero positive range.
2288 if (range <= 0)
2289 {
2290 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2291 return false;
2292 }
2293
2294 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2295 {
2296 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2297 return false;
2298 }
2299
2300 return true;
2301}
2302
2303bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2304{
2305 if (!context->getExtensions().pathRendering)
2306 {
2307 context->handleError(
2308 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2309 return false;
2310 }
2311
2312 // range = 0 is undefined in NV_path_rendering.
2313 // we add stricter semantic check here and require a non zero positive range.
2314 if (range <= 0)
2315 {
2316 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2317 return false;
2318 }
2319
2320 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2321 checkedRange += range;
2322
2323 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2324 {
2325 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2326 return false;
2327 }
2328 return true;
2329}
2330
2331bool ValidatePathCommands(Context *context,
2332 GLuint path,
2333 GLsizei numCommands,
2334 const GLubyte *commands,
2335 GLsizei numCoords,
2336 GLenum coordType,
2337 const void *coords)
2338{
2339 if (!context->getExtensions().pathRendering)
2340 {
2341 context->handleError(
2342 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2343 return false;
2344 }
2345 if (!context->hasPath(path))
2346 {
2347 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2348 return false;
2349 }
2350
2351 if (numCommands < 0)
2352 {
2353 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2354 return false;
2355 }
2356 else if (numCommands > 0)
2357 {
2358 if (!commands)
2359 {
2360 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2361 return false;
2362 }
2363 }
2364
2365 if (numCoords < 0)
2366 {
2367 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2368 return false;
2369 }
2370 else if (numCoords > 0)
2371 {
2372 if (!coords)
2373 {
2374 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2375 return false;
2376 }
2377 }
2378
2379 std::uint32_t coordTypeSize = 0;
2380 switch (coordType)
2381 {
2382 case GL_BYTE:
2383 coordTypeSize = sizeof(GLbyte);
2384 break;
2385
2386 case GL_UNSIGNED_BYTE:
2387 coordTypeSize = sizeof(GLubyte);
2388 break;
2389
2390 case GL_SHORT:
2391 coordTypeSize = sizeof(GLshort);
2392 break;
2393
2394 case GL_UNSIGNED_SHORT:
2395 coordTypeSize = sizeof(GLushort);
2396 break;
2397
2398 case GL_FLOAT:
2399 coordTypeSize = sizeof(GLfloat);
2400 break;
2401
2402 default:
2403 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2404 return false;
2405 }
2406
2407 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2408 checkedSize += (coordTypeSize * numCoords);
2409 if (!checkedSize.IsValid())
2410 {
2411 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2412 return false;
2413 }
2414
2415 // early return skips command data validation when it doesn't exist.
2416 if (!commands)
2417 return true;
2418
2419 GLsizei expectedNumCoords = 0;
2420 for (GLsizei i = 0; i < numCommands; ++i)
2421 {
2422 switch (commands[i])
2423 {
2424 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2425 break;
2426 case GL_MOVE_TO_CHROMIUM:
2427 case GL_LINE_TO_CHROMIUM:
2428 expectedNumCoords += 2;
2429 break;
2430 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2431 expectedNumCoords += 4;
2432 break;
2433 case GL_CUBIC_CURVE_TO_CHROMIUM:
2434 expectedNumCoords += 6;
2435 break;
2436 case GL_CONIC_CURVE_TO_CHROMIUM:
2437 expectedNumCoords += 5;
2438 break;
2439 default:
2440 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2441 return false;
2442 }
2443 }
2444 if (expectedNumCoords != numCoords)
2445 {
2446 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2447 return false;
2448 }
2449
2450 return true;
2451}
2452
2453bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2454{
2455 if (!context->getExtensions().pathRendering)
2456 {
2457 context->handleError(
2458 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2459 return false;
2460 }
2461 if (!context->hasPath(path))
2462 {
2463 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2464 return false;
2465 }
2466
2467 switch (pname)
2468 {
2469 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2470 if (value < 0.0f)
2471 {
2472 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2473 return false;
2474 }
2475 break;
2476 case GL_PATH_END_CAPS_CHROMIUM:
2477 switch (static_cast<GLenum>(value))
2478 {
2479 case GL_FLAT_CHROMIUM:
2480 case GL_SQUARE_CHROMIUM:
2481 case GL_ROUND_CHROMIUM:
2482 break;
2483 default:
2484 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2485 return false;
2486 }
2487 break;
2488 case GL_PATH_JOIN_STYLE_CHROMIUM:
2489 switch (static_cast<GLenum>(value))
2490 {
2491 case GL_MITER_REVERT_CHROMIUM:
2492 case GL_BEVEL_CHROMIUM:
2493 case GL_ROUND_CHROMIUM:
2494 break;
2495 default:
2496 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2497 return false;
2498 }
2499 case GL_PATH_MITER_LIMIT_CHROMIUM:
2500 if (value < 0.0f)
2501 {
2502 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2503 return false;
2504 }
2505 break;
2506
2507 case GL_PATH_STROKE_BOUND_CHROMIUM:
2508 // no errors, only clamping.
2509 break;
2510
2511 default:
2512 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2513 return false;
2514 }
2515 return true;
2516}
2517
2518bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2519{
2520 if (!context->getExtensions().pathRendering)
2521 {
2522 context->handleError(
2523 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2524 return false;
2525 }
2526
2527 if (!context->hasPath(path))
2528 {
2529 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2530 return false;
2531 }
2532 if (!value)
2533 {
2534 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2535 return false;
2536 }
2537
2538 switch (pname)
2539 {
2540 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2541 case GL_PATH_END_CAPS_CHROMIUM:
2542 case GL_PATH_JOIN_STYLE_CHROMIUM:
2543 case GL_PATH_MITER_LIMIT_CHROMIUM:
2544 case GL_PATH_STROKE_BOUND_CHROMIUM:
2545 break;
2546
2547 default:
2548 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2549 return false;
2550 }
2551
2552 return true;
2553}
2554
2555bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2556{
2557 if (!context->getExtensions().pathRendering)
2558 {
2559 context->handleError(
2560 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2561 return false;
2562 }
2563
2564 switch (func)
2565 {
2566 case GL_NEVER:
2567 case GL_ALWAYS:
2568 case GL_LESS:
2569 case GL_LEQUAL:
2570 case GL_EQUAL:
2571 case GL_GEQUAL:
2572 case GL_GREATER:
2573 case GL_NOTEQUAL:
2574 break;
2575 default:
2576 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2577 return false;
2578 }
2579
2580 return true;
2581}
2582
2583// Note that the spec specifies that for the path drawing commands
2584// if the path object is not an existing path object the command
2585// does nothing and no error is generated.
2586// However if the path object exists but has not been specified any
2587// commands then an error is generated.
2588
2589bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2590{
2591 if (!context->getExtensions().pathRendering)
2592 {
2593 context->handleError(
2594 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2595 return false;
2596 }
2597 if (context->hasPath(path) && !context->hasPathData(path))
2598 {
2599 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2600 return false;
2601 }
2602
2603 switch (fillMode)
2604 {
2605 case GL_COUNT_UP_CHROMIUM:
2606 case GL_COUNT_DOWN_CHROMIUM:
2607 break;
2608 default:
2609 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2610 return false;
2611 }
2612
2613 if (!isPow2(mask + 1))
2614 {
2615 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2616 return false;
2617 }
2618
2619 return true;
2620}
2621
2622bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2623{
2624 if (!context->getExtensions().pathRendering)
2625 {
2626 context->handleError(
2627 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2628 return false;
2629 }
2630 if (context->hasPath(path) && !context->hasPathData(path))
2631 {
2632 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2633 return false;
2634 }
2635
2636 return true;
2637}
2638
2639bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2640{
2641 if (!context->getExtensions().pathRendering)
2642 {
2643 context->handleError(
2644 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2645 return false;
2646 }
2647 if (context->hasPath(path) && !context->hasPathData(path))
2648 {
2649 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2650 return false;
2651 }
2652
2653 switch (coverMode)
2654 {
2655 case GL_CONVEX_HULL_CHROMIUM:
2656 case GL_BOUNDING_BOX_CHROMIUM:
2657 break;
2658 default:
2659 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2660 return false;
2661 }
2662 return true;
2663}
2664
2665bool ValidateStencilThenCoverFillPath(Context *context,
2666 GLuint path,
2667 GLenum fillMode,
2668 GLuint mask,
2669 GLenum coverMode)
2670{
2671 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2672 ValidateCoverPath(context, path, coverMode);
2673}
2674
2675bool ValidateStencilThenCoverStrokePath(Context *context,
2676 GLuint path,
2677 GLint reference,
2678 GLuint mask,
2679 GLenum coverMode)
2680{
2681 return ValidateStencilStrokePath(context, path, reference, mask) &&
2682 ValidateCoverPath(context, path, coverMode);
2683}
2684
2685bool ValidateIsPath(Context *context)
2686{
2687 if (!context->getExtensions().pathRendering)
2688 {
2689 context->handleError(
2690 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2691 return false;
2692 }
2693 return true;
2694}
2695
Sami Väisänend59ca052016-06-21 16:10:00 +03002696bool ValidateCoverFillPathInstanced(Context *context,
2697 GLsizei numPaths,
2698 GLenum pathNameType,
2699 const void *paths,
2700 GLuint pathBase,
2701 GLenum coverMode,
2702 GLenum transformType,
2703 const GLfloat *transformValues)
2704{
2705 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2706 transformType, transformValues))
2707 return false;
2708
2709 switch (coverMode)
2710 {
2711 case GL_CONVEX_HULL_CHROMIUM:
2712 case GL_BOUNDING_BOX_CHROMIUM:
2713 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2714 break;
2715 default:
2716 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2717 return false;
2718 }
2719
2720 return true;
2721}
2722
2723bool ValidateCoverStrokePathInstanced(Context *context,
2724 GLsizei numPaths,
2725 GLenum pathNameType,
2726 const void *paths,
2727 GLuint pathBase,
2728 GLenum coverMode,
2729 GLenum transformType,
2730 const GLfloat *transformValues)
2731{
2732 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2733 transformType, transformValues))
2734 return false;
2735
2736 switch (coverMode)
2737 {
2738 case GL_CONVEX_HULL_CHROMIUM:
2739 case GL_BOUNDING_BOX_CHROMIUM:
2740 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2741 break;
2742 default:
2743 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2744 return false;
2745 }
2746
2747 return true;
2748}
2749
2750bool ValidateStencilFillPathInstanced(Context *context,
2751 GLsizei numPaths,
2752 GLenum pathNameType,
2753 const void *paths,
2754 GLuint pathBase,
2755 GLenum fillMode,
2756 GLuint mask,
2757 GLenum transformType,
2758 const GLfloat *transformValues)
2759{
2760
2761 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2762 transformType, transformValues))
2763 return false;
2764
2765 switch (fillMode)
2766 {
2767 case GL_COUNT_UP_CHROMIUM:
2768 case GL_COUNT_DOWN_CHROMIUM:
2769 break;
2770 default:
2771 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2772 return false;
2773 }
2774 if (!isPow2(mask + 1))
2775 {
2776 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2777 return false;
2778 }
2779 return true;
2780}
2781
2782bool ValidateStencilStrokePathInstanced(Context *context,
2783 GLsizei numPaths,
2784 GLenum pathNameType,
2785 const void *paths,
2786 GLuint pathBase,
2787 GLint reference,
2788 GLuint mask,
2789 GLenum transformType,
2790 const GLfloat *transformValues)
2791{
2792 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2793 transformType, transformValues))
2794 return false;
2795
2796 // no more validation here.
2797
2798 return true;
2799}
2800
2801bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2802 GLsizei numPaths,
2803 GLenum pathNameType,
2804 const void *paths,
2805 GLuint pathBase,
2806 GLenum fillMode,
2807 GLuint mask,
2808 GLenum coverMode,
2809 GLenum transformType,
2810 const GLfloat *transformValues)
2811{
2812 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2813 transformType, transformValues))
2814 return false;
2815
2816 switch (coverMode)
2817 {
2818 case GL_CONVEX_HULL_CHROMIUM:
2819 case GL_BOUNDING_BOX_CHROMIUM:
2820 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2821 break;
2822 default:
2823 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2824 return false;
2825 }
2826
2827 switch (fillMode)
2828 {
2829 case GL_COUNT_UP_CHROMIUM:
2830 case GL_COUNT_DOWN_CHROMIUM:
2831 break;
2832 default:
2833 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2834 return false;
2835 }
2836 if (!isPow2(mask + 1))
2837 {
2838 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2839 return false;
2840 }
2841
2842 return true;
2843}
2844
2845bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2846 GLsizei numPaths,
2847 GLenum pathNameType,
2848 const void *paths,
2849 GLuint pathBase,
2850 GLint reference,
2851 GLuint mask,
2852 GLenum coverMode,
2853 GLenum transformType,
2854 const GLfloat *transformValues)
2855{
2856 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2857 transformType, transformValues))
2858 return false;
2859
2860 switch (coverMode)
2861 {
2862 case GL_CONVEX_HULL_CHROMIUM:
2863 case GL_BOUNDING_BOX_CHROMIUM:
2864 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2865 break;
2866 default:
2867 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2868 return false;
2869 }
2870
2871 return true;
2872}
2873
Sami Väisänen46eaa942016-06-29 10:26:37 +03002874bool ValidateBindFragmentInputLocation(Context *context,
2875 GLuint program,
2876 GLint location,
2877 const GLchar *name)
2878{
2879 if (!context->getExtensions().pathRendering)
2880 {
2881 context->handleError(
2882 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2883 return false;
2884 }
2885
2886 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2887 if (location >= MaxLocation)
2888 {
2889 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2890 return false;
2891 }
2892
2893 const auto *programObject = context->getProgram(program);
2894 if (!programObject)
2895 {
2896 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2897 return false;
2898 }
2899
2900 if (!name)
2901 {
2902 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2903 return false;
2904 }
2905
2906 if (angle::BeginsWith(name, "gl_"))
2907 {
2908 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2909 return false;
2910 }
2911
2912 return true;
2913}
2914
2915bool ValidateProgramPathFragmentInputGen(Context *context,
2916 GLuint program,
2917 GLint location,
2918 GLenum genMode,
2919 GLint components,
2920 const GLfloat *coeffs)
2921{
2922 if (!context->getExtensions().pathRendering)
2923 {
2924 context->handleError(
2925 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2926 return false;
2927 }
2928
2929 const auto *programObject = context->getProgram(program);
2930 if (!programObject || programObject->isFlaggedForDeletion())
2931 {
2932 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2933 return false;
2934 }
2935
2936 if (!programObject->isLinked())
2937 {
2938 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2939 return false;
2940 }
2941
2942 switch (genMode)
2943 {
2944 case GL_NONE:
2945 if (components != 0)
2946 {
2947 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2948 return false;
2949 }
2950 break;
2951
2952 case GL_OBJECT_LINEAR_CHROMIUM:
2953 case GL_EYE_LINEAR_CHROMIUM:
2954 case GL_CONSTANT_CHROMIUM:
2955 if (components < 1 || components > 4)
2956 {
2957 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2958 return false;
2959 }
2960 if (!coeffs)
2961 {
2962 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2963 return false;
2964 }
2965 break;
2966
2967 default:
2968 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2969 return false;
2970 }
2971
2972 // If the location is -1 then the command is silently ignored
2973 // and no further validation is needed.
2974 if (location == -1)
2975 return true;
2976
2977 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2978
2979 if (!binding.valid)
2980 {
2981 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
2982 return false;
2983 }
2984
2985 if (binding.type != GL_NONE)
2986 {
2987 GLint expectedComponents = 0;
2988 switch (binding.type)
2989 {
2990 case GL_FLOAT:
2991 expectedComponents = 1;
2992 break;
2993 case GL_FLOAT_VEC2:
2994 expectedComponents = 2;
2995 break;
2996 case GL_FLOAT_VEC3:
2997 expectedComponents = 3;
2998 break;
2999 case GL_FLOAT_VEC4:
3000 expectedComponents = 4;
3001 break;
3002 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003003 context->handleError(
3004 Error(GL_INVALID_OPERATION,
3005 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003006 return false;
3007 }
3008 if (expectedComponents != components && genMode != GL_NONE)
3009 {
3010 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3011 return false;
3012 }
3013 }
3014 return true;
3015}
3016
Geoff Lang97073d12016-04-20 10:42:34 -07003017bool ValidateCopyTextureCHROMIUM(Context *context,
3018 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003019 GLint sourceLevel,
3020 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003021 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003022 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003023 GLint internalFormat,
3024 GLenum destType,
3025 GLboolean unpackFlipY,
3026 GLboolean unpackPremultiplyAlpha,
3027 GLboolean unpackUnmultiplyAlpha)
3028{
3029 if (!context->getExtensions().copyTexture)
3030 {
3031 context->handleError(
3032 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3033 return false;
3034 }
3035
3036 const gl::Texture *source = context->getTexture(sourceId);
3037 if (source == nullptr)
3038 {
3039 context->handleError(
3040 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3041 return false;
3042 }
3043
3044 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3045 {
3046 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3047 return false;
3048 }
3049
3050 GLenum sourceTarget = source->getTarget();
3051 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3052 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3053 {
3054 context->handleError(
3055 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3056 return false;
3057 }
3058
Geoff Langca271392017-04-05 12:30:00 -04003059 const gl::InternalFormat &sourceFormat = *source->getFormat(sourceTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003060 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3061 {
3062 context->handleError(
3063 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3064 return false;
3065 }
3066
3067 const gl::Texture *dest = context->getTexture(destId);
3068 if (dest == nullptr)
3069 {
3070 context->handleError(
3071 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3072 return false;
3073 }
3074
3075 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3076 {
3077 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3078 return false;
3079 }
3080
3081 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3082 {
3083 context->handleError(
3084 Error(GL_INVALID_OPERATION,
3085 "Destination internal format and type combination is not valid."));
3086 return false;
3087 }
3088
3089 if (dest->getImmutableFormat())
3090 {
3091 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3092 return false;
3093 }
3094
3095 return true;
3096}
3097
3098bool ValidateCopySubTextureCHROMIUM(Context *context,
3099 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003100 GLint sourceLevel,
3101 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003102 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003103 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003104 GLint xoffset,
3105 GLint yoffset,
3106 GLint x,
3107 GLint y,
3108 GLsizei width,
3109 GLsizei height,
3110 GLboolean unpackFlipY,
3111 GLboolean unpackPremultiplyAlpha,
3112 GLboolean unpackUnmultiplyAlpha)
3113{
3114 if (!context->getExtensions().copyTexture)
3115 {
3116 context->handleError(
3117 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3118 return false;
3119 }
3120
3121 const gl::Texture *source = context->getTexture(sourceId);
3122 if (source == nullptr)
3123 {
3124 context->handleError(
3125 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3126 return false;
3127 }
3128
3129 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3130 {
3131 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3132 return false;
3133 }
3134
3135 GLenum sourceTarget = source->getTarget();
3136 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3137 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3138 {
3139 context->handleError(
3140 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3141 return false;
3142 }
3143
3144 if (x < 0 || y < 0)
3145 {
3146 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3147 return false;
3148 }
3149
3150 if (width < 0 || height < 0)
3151 {
3152 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3153 return false;
3154 }
3155
3156 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3157 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3158 {
3159 context->handleError(
3160 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3161 return false;
3162 }
3163
3164 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
Geoff Langca271392017-04-05 12:30:00 -04003165 if (!IsValidCopyTextureFormat(context, sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003166 {
3167 context->handleError(
3168 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3169 return false;
3170 }
3171
3172 const gl::Texture *dest = context->getTexture(destId);
3173 if (dest == nullptr)
3174 {
3175 context->handleError(
3176 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3177 return false;
3178 }
3179
3180 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3181 {
3182 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3183 return false;
3184 }
3185
Geoff Lang97073d12016-04-20 10:42:34 -07003186 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3187 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3188 {
3189 context->handleError(
3190 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3191 return false;
3192 }
3193
Geoff Langca271392017-04-05 12:30:00 -04003194 const gl::InternalFormat &destFormat = *dest->getFormat(destTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003195 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3196 {
3197 context->handleError(
3198 Error(GL_INVALID_OPERATION,
3199 "Destination internal format and type combination is not valid."));
3200 return false;
3201 }
3202
3203 if (xoffset < 0 || yoffset < 0)
3204 {
3205 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3206 return false;
3207 }
3208
3209 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3210 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3211 {
3212 context->handleError(
3213 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3214 return false;
3215 }
3216
3217 return true;
3218}
3219
Geoff Lang47110bf2016-04-20 11:13:22 -07003220bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3221{
3222 if (!context->getExtensions().copyCompressedTexture)
3223 {
3224 context->handleError(Error(GL_INVALID_OPERATION,
3225 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3226 return false;
3227 }
3228
3229 const gl::Texture *source = context->getTexture(sourceId);
3230 if (source == nullptr)
3231 {
3232 context->handleError(
3233 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3234 return false;
3235 }
3236
3237 if (source->getTarget() != GL_TEXTURE_2D)
3238 {
3239 context->handleError(
3240 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3241 return false;
3242 }
3243
3244 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3245 {
3246 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3247 return false;
3248 }
3249
3250 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3251 if (!sourceFormat.info->compressed)
3252 {
3253 context->handleError(
3254 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3255 return false;
3256 }
3257
3258 const gl::Texture *dest = context->getTexture(destId);
3259 if (dest == nullptr)
3260 {
3261 context->handleError(
3262 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3263 return false;
3264 }
3265
3266 if (dest->getTarget() != GL_TEXTURE_2D)
3267 {
3268 context->handleError(
3269 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3270 return false;
3271 }
3272
3273 if (dest->getImmutableFormat())
3274 {
3275 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3276 return false;
3277 }
3278
3279 return true;
3280}
3281
Martin Radev4c4c8e72016-08-04 12:25:34 +03003282bool ValidateCreateShader(Context *context, GLenum type)
3283{
3284 switch (type)
3285 {
3286 case GL_VERTEX_SHADER:
3287 case GL_FRAGMENT_SHADER:
3288 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003289
Martin Radev4c4c8e72016-08-04 12:25:34 +03003290 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003291 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003292 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003293 context->handleError(
3294 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3295 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003296 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003297 break;
3298
Martin Radev4c4c8e72016-08-04 12:25:34 +03003299 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003300 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003301 return false;
3302 }
Jamie Madill29639852016-09-02 15:00:09 -04003303
3304 return true;
3305}
3306
3307bool ValidateBufferData(ValidationContext *context,
3308 GLenum target,
3309 GLsizeiptr size,
3310 const GLvoid *data,
3311 GLenum usage)
3312{
3313 if (size < 0)
3314 {
3315 context->handleError(Error(GL_INVALID_VALUE));
3316 return false;
3317 }
3318
3319 switch (usage)
3320 {
3321 case GL_STREAM_DRAW:
3322 case GL_STATIC_DRAW:
3323 case GL_DYNAMIC_DRAW:
3324 break;
3325
3326 case GL_STREAM_READ:
3327 case GL_STREAM_COPY:
3328 case GL_STATIC_READ:
3329 case GL_STATIC_COPY:
3330 case GL_DYNAMIC_READ:
3331 case GL_DYNAMIC_COPY:
3332 if (context->getClientMajorVersion() < 3)
3333 {
3334 context->handleError(Error(GL_INVALID_ENUM));
3335 return false;
3336 }
3337 break;
3338
3339 default:
3340 context->handleError(Error(GL_INVALID_ENUM));
3341 return false;
3342 }
3343
3344 if (!ValidBufferTarget(context, target))
3345 {
3346 context->handleError(Error(GL_INVALID_ENUM));
3347 return false;
3348 }
3349
3350 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3351
3352 if (!buffer)
3353 {
3354 context->handleError(Error(GL_INVALID_OPERATION));
3355 return false;
3356 }
3357
3358 return true;
3359}
3360
3361bool ValidateBufferSubData(ValidationContext *context,
3362 GLenum target,
3363 GLintptr offset,
3364 GLsizeiptr size,
3365 const GLvoid *data)
3366{
3367 if (size < 0 || offset < 0)
3368 {
3369 context->handleError(Error(GL_INVALID_VALUE));
3370 return false;
3371 }
3372
3373 if (!ValidBufferTarget(context, target))
3374 {
3375 context->handleError(Error(GL_INVALID_ENUM));
3376 return false;
3377 }
3378
3379 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3380
3381 if (!buffer)
3382 {
3383 context->handleError(Error(GL_INVALID_OPERATION));
3384 return false;
3385 }
3386
3387 if (buffer->isMapped())
3388 {
3389 context->handleError(Error(GL_INVALID_OPERATION));
3390 return false;
3391 }
3392
3393 // Check for possible overflow of size + offset
3394 angle::CheckedNumeric<size_t> checkedSize(size);
3395 checkedSize += offset;
3396 if (!checkedSize.IsValid())
3397 {
3398 context->handleError(Error(GL_OUT_OF_MEMORY));
3399 return false;
3400 }
3401
3402 if (size + offset > buffer->getSize())
3403 {
3404 context->handleError(Error(GL_INVALID_VALUE));
3405 return false;
3406 }
3407
Martin Radev4c4c8e72016-08-04 12:25:34 +03003408 return true;
3409}
3410
Geoff Langc339c4e2016-11-29 10:37:36 -05003411bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003412{
Geoff Langc339c4e2016-11-29 10:37:36 -05003413 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003414 {
3415 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003416 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003417 return false;
3418 }
3419
3420 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3421 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003422 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003423 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003424 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003425 return false;
3426 }
3427
3428 return true;
3429}
3430
Jamie Madillef300b12016-10-07 15:12:09 -04003431bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3432{
3433 if (texture < GL_TEXTURE0 ||
3434 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3435 {
3436 context->handleError(Error(GL_INVALID_ENUM));
3437 return false;
3438 }
3439
3440 return true;
3441}
3442
3443bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3444{
3445 Program *programObject = GetValidProgram(context, program);
3446 if (!programObject)
3447 {
3448 return false;
3449 }
3450
3451 Shader *shaderObject = GetValidShader(context, shader);
3452 if (!shaderObject)
3453 {
3454 return false;
3455 }
3456
3457 switch (shaderObject->getType())
3458 {
3459 case GL_VERTEX_SHADER:
3460 {
3461 if (programObject->getAttachedVertexShader())
3462 {
3463 context->handleError(Error(GL_INVALID_OPERATION));
3464 return false;
3465 }
3466 break;
3467 }
3468 case GL_FRAGMENT_SHADER:
3469 {
3470 if (programObject->getAttachedFragmentShader())
3471 {
3472 context->handleError(Error(GL_INVALID_OPERATION));
3473 return false;
3474 }
3475 break;
3476 }
3477 case GL_COMPUTE_SHADER:
3478 {
3479 if (programObject->getAttachedComputeShader())
3480 {
3481 context->handleError(Error(GL_INVALID_OPERATION));
3482 return false;
3483 }
3484 break;
3485 }
3486 default:
3487 UNREACHABLE();
3488 break;
3489 }
3490
3491 return true;
3492}
3493
Jamie Madill01a80ee2016-11-07 12:06:18 -05003494bool ValidateBindAttribLocation(ValidationContext *context,
3495 GLuint program,
3496 GLuint index,
3497 const GLchar *name)
3498{
3499 if (index >= MAX_VERTEX_ATTRIBS)
3500 {
3501 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3502 return false;
3503 }
3504
3505 if (strncmp(name, "gl_", 3) == 0)
3506 {
3507 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3508 return false;
3509 }
3510
3511 return GetValidProgram(context, program) != nullptr;
3512}
3513
3514bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3515{
3516 if (!ValidBufferTarget(context, target))
3517 {
3518 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3519 return false;
3520 }
3521
3522 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3523 !context->isBufferGenerated(buffer))
3524 {
3525 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3526 return false;
3527 }
3528
3529 return true;
3530}
3531
3532bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3533{
3534 if (!ValidFramebufferTarget(target))
3535 {
3536 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3537 return false;
3538 }
3539
3540 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3541 !context->isFramebufferGenerated(framebuffer))
3542 {
3543 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3544 return false;
3545 }
3546
3547 return true;
3548}
3549
3550bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3551{
3552 if (target != GL_RENDERBUFFER)
3553 {
3554 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3555 return false;
3556 }
3557
3558 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3559 !context->isRenderbufferGenerated(renderbuffer))
3560 {
3561 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3562 return false;
3563 }
3564
3565 return true;
3566}
3567
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003568static bool ValidBlendEquationMode(GLenum mode)
3569{
3570 switch (mode)
3571 {
3572 case GL_FUNC_ADD:
3573 case GL_FUNC_SUBTRACT:
3574 case GL_FUNC_REVERSE_SUBTRACT:
3575 case GL_MIN:
3576 case GL_MAX:
3577 return true;
3578
3579 default:
3580 return false;
3581 }
3582}
3583
Jamie Madillc1d770e2017-04-13 17:31:24 -04003584bool ValidateBlendColor(ValidationContext *context,
3585 GLclampf red,
3586 GLclampf green,
3587 GLclampf blue,
3588 GLclampf alpha)
3589{
3590 return true;
3591}
3592
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003593bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3594{
3595 if (!ValidBlendEquationMode(mode))
3596 {
3597 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3598 return false;
3599 }
3600
3601 return true;
3602}
3603
3604bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3605{
3606 if (!ValidBlendEquationMode(modeRGB))
3607 {
3608 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3609 return false;
3610 }
3611
3612 if (!ValidBlendEquationMode(modeAlpha))
3613 {
3614 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3615 return false;
3616 }
3617
3618 return true;
3619}
3620
3621bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3622{
3623 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3624}
3625
3626static bool ValidSrcBlendFunc(GLenum srcBlend)
3627{
3628 switch (srcBlend)
3629 {
3630 case GL_ZERO:
3631 case GL_ONE:
3632 case GL_SRC_COLOR:
3633 case GL_ONE_MINUS_SRC_COLOR:
3634 case GL_DST_COLOR:
3635 case GL_ONE_MINUS_DST_COLOR:
3636 case GL_SRC_ALPHA:
3637 case GL_ONE_MINUS_SRC_ALPHA:
3638 case GL_DST_ALPHA:
3639 case GL_ONE_MINUS_DST_ALPHA:
3640 case GL_CONSTANT_COLOR:
3641 case GL_ONE_MINUS_CONSTANT_COLOR:
3642 case GL_CONSTANT_ALPHA:
3643 case GL_ONE_MINUS_CONSTANT_ALPHA:
3644 case GL_SRC_ALPHA_SATURATE:
3645 return true;
3646
3647 default:
3648 return false;
3649 }
3650}
3651
3652static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3653{
3654 switch (dstBlend)
3655 {
3656 case GL_ZERO:
3657 case GL_ONE:
3658 case GL_SRC_COLOR:
3659 case GL_ONE_MINUS_SRC_COLOR:
3660 case GL_DST_COLOR:
3661 case GL_ONE_MINUS_DST_COLOR:
3662 case GL_SRC_ALPHA:
3663 case GL_ONE_MINUS_SRC_ALPHA:
3664 case GL_DST_ALPHA:
3665 case GL_ONE_MINUS_DST_ALPHA:
3666 case GL_CONSTANT_COLOR:
3667 case GL_ONE_MINUS_CONSTANT_COLOR:
3668 case GL_CONSTANT_ALPHA:
3669 case GL_ONE_MINUS_CONSTANT_ALPHA:
3670 return true;
3671
3672 case GL_SRC_ALPHA_SATURATE:
3673 return (contextMajorVersion >= 3);
3674
3675 default:
3676 return false;
3677 }
3678}
3679
3680bool ValidateBlendFuncSeparate(ValidationContext *context,
3681 GLenum srcRGB,
3682 GLenum dstRGB,
3683 GLenum srcAlpha,
3684 GLenum dstAlpha)
3685{
3686 if (!ValidSrcBlendFunc(srcRGB))
3687 {
3688 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3689 return false;
3690 }
3691
3692 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3693 {
3694 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3695 return false;
3696 }
3697
3698 if (!ValidSrcBlendFunc(srcAlpha))
3699 {
3700 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3701 return false;
3702 }
3703
3704 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3705 {
3706 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3707 return false;
3708 }
3709
Frank Henigman146e8a12017-03-02 23:22:37 -05003710 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3711 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003712 {
3713 bool constantColorUsed =
3714 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3715 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3716
3717 bool constantAlphaUsed =
3718 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3719 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3720
3721 if (constantColorUsed && constantAlphaUsed)
3722 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003723 const char *msg;
3724 if (context->getExtensions().webglCompatibility)
3725 {
3726 msg =
3727 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3728 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3729 }
3730 else
3731 {
3732 msg =
3733 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3734 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3735 "implementation.";
3736 ERR() << msg;
3737 }
3738 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003739 return false;
3740 }
3741 }
3742
3743 return true;
3744}
3745
Geoff Langc339c4e2016-11-29 10:37:36 -05003746bool ValidateGetString(Context *context, GLenum name)
3747{
3748 switch (name)
3749 {
3750 case GL_VENDOR:
3751 case GL_RENDERER:
3752 case GL_VERSION:
3753 case GL_SHADING_LANGUAGE_VERSION:
3754 case GL_EXTENSIONS:
3755 break;
3756
3757 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3758 if (!context->getExtensions().requestExtension)
3759 {
3760 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3761 return false;
3762 }
3763 break;
3764
3765 default:
3766 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3767 return false;
3768 }
3769
3770 return true;
3771}
3772
Geoff Lang47c48082016-12-07 15:38:13 -05003773bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3774{
3775 if (width <= 0.0f || isNaN(width))
3776 {
3777 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3778 return false;
3779 }
3780
3781 return true;
3782}
3783
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003784bool ValidateVertexAttribPointer(ValidationContext *context,
3785 GLuint index,
3786 GLint size,
3787 GLenum type,
3788 GLboolean normalized,
3789 GLsizei stride,
3790 const GLvoid *ptr)
3791{
Shao80957d92017-02-20 21:25:59 +08003792 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003793 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003794 return false;
3795 }
3796
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003797 if (stride < 0)
3798 {
Shao80957d92017-02-20 21:25:59 +08003799 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003800 return false;
3801 }
3802
Shao80957d92017-02-20 21:25:59 +08003803 const Caps &caps = context->getCaps();
3804 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003805 {
Shao80957d92017-02-20 21:25:59 +08003806 if (stride > caps.maxVertexAttribStride)
3807 {
3808 context->handleError(
3809 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
3810 return false;
3811 }
3812
3813 if (index >= caps.maxVertexAttribBindings)
3814 {
3815 context->handleError(
3816 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
3817 return false;
3818 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003819 }
3820
3821 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3822 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3823 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3824 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003825 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3826 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08003827 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003828 {
3829 context->handleError(
3830 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08003831 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003832 return false;
3833 }
3834
3835 if (context->getExtensions().webglCompatibility)
3836 {
3837 // WebGL 1.0 [Section 6.14] Fixed point support
3838 // The WebGL API does not support the GL_FIXED data type.
3839 if (type == GL_FIXED)
3840 {
3841 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3842 return false;
3843 }
3844
Geoff Lang2d62ab72017-03-23 16:54:40 -04003845 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003846 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003847 return false;
3848 }
3849 }
3850
3851 return true;
3852}
3853
Frank Henigman6137ddc2017-02-10 18:55:07 -05003854bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
3855{
3856 if (context->getExtensions().webglCompatibility && zNear > zFar)
3857 {
3858 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
3859 return false;
3860 }
3861
3862 return true;
3863}
3864
Jamie Madille8fb6402017-02-14 17:56:40 -05003865bool ValidateRenderbufferStorage(ValidationContext *context,
3866 GLenum target,
3867 GLenum internalformat,
3868 GLsizei width,
3869 GLsizei height)
3870{
3871 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
3872 height);
3873}
3874
3875bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
3876 GLenum target,
3877 GLsizei samples,
3878 GLenum internalformat,
3879 GLsizei width,
3880 GLsizei height)
3881{
3882 if (!context->getExtensions().framebufferMultisample)
3883 {
3884 context->handleError(
3885 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
3886 return false;
3887 }
3888
3889 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
3890 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
3891 // generated.
3892 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
3893 {
3894 context->handleError(Error(GL_INVALID_VALUE));
3895 return false;
3896 }
3897
3898 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
3899 // the specified storage. This is different than ES 3.0 in which a sample number higher
3900 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
3901 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
3902 if (context->getClientMajorVersion() >= 3)
3903 {
3904 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3905 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3906 {
3907 context->handleError(Error(GL_OUT_OF_MEMORY));
3908 return false;
3909 }
3910 }
3911
3912 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
3913 width, height);
3914}
3915
Jamie Madillc1d770e2017-04-13 17:31:24 -04003916bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
3917{
3918 if (!ValidFramebufferTarget(target))
3919 {
3920 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3921 return false;
3922 }
3923
3924 return true;
3925}
3926
3927bool ValidateClearColor(ValidationContext *context,
3928 GLclampf red,
3929 GLclampf green,
3930 GLclampf blue,
3931 GLclampf alpha)
3932{
3933 return true;
3934}
3935
3936bool ValidateClearDepthf(ValidationContext *context, GLclampf depth)
3937{
3938 return true;
3939}
3940
3941bool ValidateClearStencil(ValidationContext *context, GLint s)
3942{
3943 return true;
3944}
3945
3946bool ValidateColorMask(ValidationContext *context,
3947 GLboolean red,
3948 GLboolean green,
3949 GLboolean blue,
3950 GLboolean alpha)
3951{
3952 return true;
3953}
3954
3955bool ValidateCompileShader(ValidationContext *context, GLuint shader)
3956{
3957 return true;
3958}
3959
3960bool ValidateCreateProgram(ValidationContext *context)
3961{
3962 return true;
3963}
3964
3965bool ValidateCullFace(ValidationContext *context, GLenum mode)
3966{
3967 switch (mode)
3968 {
3969 case GL_FRONT:
3970 case GL_BACK:
3971 case GL_FRONT_AND_BACK:
3972 break;
3973
3974 default:
3975 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
3976 return false;
3977 }
3978
3979 return true;
3980}
3981
3982bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
3983{
3984 if (program == 0)
3985 {
3986 return false;
3987 }
3988
3989 if (!context->getProgram(program))
3990 {
3991 if (context->getShader(program))
3992 {
3993 context->handleError(
3994 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
3995 return false;
3996 }
3997 else
3998 {
3999 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4000 return false;
4001 }
4002 }
4003
4004 return true;
4005}
4006
4007bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4008{
4009 if (shader == 0)
4010 {
4011 return false;
4012 }
4013
4014 if (!context->getShader(shader))
4015 {
4016 if (context->getProgram(shader))
4017 {
4018 context->handleError(
4019 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4020 return false;
4021 }
4022 else
4023 {
4024 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4025 return false;
4026 }
4027 }
4028
4029 return true;
4030}
4031
4032bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4033{
4034 switch (func)
4035 {
4036 case GL_NEVER:
4037 case GL_ALWAYS:
4038 case GL_LESS:
4039 case GL_LEQUAL:
4040 case GL_EQUAL:
4041 case GL_GREATER:
4042 case GL_GEQUAL:
4043 case GL_NOTEQUAL:
4044 break;
4045
4046 default:
4047 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4048 return false;
4049 }
4050
4051 return true;
4052}
4053
4054bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4055{
4056 return true;
4057}
4058
4059bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4060{
4061 Program *programObject = GetValidProgram(context, program);
4062 if (!programObject)
4063 {
4064 return false;
4065 }
4066
4067 Shader *shaderObject = GetValidShader(context, shader);
4068 if (!shaderObject)
4069 {
4070 return false;
4071 }
4072
4073 const Shader *attachedShader = nullptr;
4074
4075 switch (shaderObject->getType())
4076 {
4077 case GL_VERTEX_SHADER:
4078 {
4079 attachedShader = programObject->getAttachedVertexShader();
4080 break;
4081 }
4082 case GL_FRAGMENT_SHADER:
4083 {
4084 attachedShader = programObject->getAttachedFragmentShader();
4085 break;
4086 }
4087 case GL_COMPUTE_SHADER:
4088 {
4089 attachedShader = programObject->getAttachedComputeShader();
4090 break;
4091 }
4092 default:
4093 UNREACHABLE();
4094 return false;
4095 }
4096
4097 if (attachedShader != shaderObject)
4098 {
4099 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4100 return false;
4101 }
4102
4103 return true;
4104}
4105
4106bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4107{
4108 if (index >= MAX_VERTEX_ATTRIBS)
4109 {
4110 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4111 return false;
4112 }
4113
4114 return true;
4115}
4116
4117bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4118{
4119 if (index >= MAX_VERTEX_ATTRIBS)
4120 {
4121 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4122 return false;
4123 }
4124
4125 return true;
4126}
4127
4128bool ValidateFinish(ValidationContext *context)
4129{
4130 return true;
4131}
4132
4133bool ValidateFlush(ValidationContext *context)
4134{
4135 return true;
4136}
4137
4138bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4139{
4140 switch (mode)
4141 {
4142 case GL_CW:
4143 case GL_CCW:
4144 break;
4145 default:
4146 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4147 return false;
4148 }
4149
4150 return true;
4151}
4152
4153bool ValidateGetActiveAttrib(ValidationContext *context,
4154 GLuint program,
4155 GLuint index,
4156 GLsizei bufsize,
4157 GLsizei *length,
4158 GLint *size,
4159 GLenum *type,
4160 GLchar *name)
4161{
4162 if (bufsize < 0)
4163 {
4164 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4165 return false;
4166 }
4167
4168 Program *programObject = GetValidProgram(context, program);
4169
4170 if (!programObject)
4171 {
4172 return false;
4173 }
4174
4175 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4176 {
4177 context->handleError(
4178 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4179 return false;
4180 }
4181
4182 return true;
4183}
4184
4185bool ValidateGetActiveUniform(ValidationContext *context,
4186 GLuint program,
4187 GLuint index,
4188 GLsizei bufsize,
4189 GLsizei *length,
4190 GLint *size,
4191 GLenum *type,
4192 GLchar *name)
4193{
4194 if (bufsize < 0)
4195 {
4196 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4197 return false;
4198 }
4199
4200 Program *programObject = GetValidProgram(context, program);
4201
4202 if (!programObject)
4203 {
4204 return false;
4205 }
4206
4207 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4208 {
4209 context->handleError(
4210 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4211 return false;
4212 }
4213
4214 return true;
4215}
4216
4217bool ValidateGetAttachedShaders(ValidationContext *context,
4218 GLuint program,
4219 GLsizei maxcount,
4220 GLsizei *count,
4221 GLuint *shaders)
4222{
4223 if (maxcount < 0)
4224 {
4225 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4226 return false;
4227 }
4228
4229 Program *programObject = GetValidProgram(context, program);
4230
4231 if (!programObject)
4232 {
4233 return false;
4234 }
4235
4236 return true;
4237}
4238
4239bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4240{
4241 Program *programObject = GetValidProgram(context, program);
4242
4243 if (!programObject)
4244 {
4245 return false;
4246 }
4247
4248 if (!programObject->isLinked())
4249 {
4250 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4251 return false;
4252 }
4253
4254 return true;
4255}
4256
4257bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4258{
4259 GLenum nativeType;
4260 unsigned int numParams = 0;
4261 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4262}
4263
4264bool ValidateGetError(ValidationContext *context)
4265{
4266 return true;
4267}
4268
4269bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4270{
4271 GLenum nativeType;
4272 unsigned int numParams = 0;
4273 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4274}
4275
4276bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4277{
4278 GLenum nativeType;
4279 unsigned int numParams = 0;
4280 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4281}
4282
4283bool ValidateGetProgramInfoLog(ValidationContext *context,
4284 GLuint program,
4285 GLsizei bufsize,
4286 GLsizei *length,
4287 GLchar *infolog)
4288{
4289 if (bufsize < 0)
4290 {
4291 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4292 return false;
4293 }
4294
4295 Program *programObject = GetValidProgram(context, program);
4296 if (!programObject)
4297 {
4298 return false;
4299 }
4300
4301 return true;
4302}
4303
4304bool ValidateGetShaderInfoLog(ValidationContext *context,
4305 GLuint shader,
4306 GLsizei bufsize,
4307 GLsizei *length,
4308 GLchar *infolog)
4309{
4310 if (bufsize < 0)
4311 {
4312 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4313 return false;
4314 }
4315
4316 Shader *shaderObject = GetValidShader(context, shader);
4317 if (!shaderObject)
4318 {
4319 return false;
4320 }
4321
4322 return true;
4323}
4324
4325bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4326 GLenum shadertype,
4327 GLenum precisiontype,
4328 GLint *range,
4329 GLint *precision)
4330{
4331 switch (shadertype)
4332 {
4333 case GL_VERTEX_SHADER:
4334 case GL_FRAGMENT_SHADER:
4335 break;
4336 case GL_COMPUTE_SHADER:
4337 context->handleError(
4338 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4339 return false;
4340 default:
4341 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4342 return false;
4343 }
4344
4345 switch (precisiontype)
4346 {
4347 case GL_LOW_FLOAT:
4348 case GL_MEDIUM_FLOAT:
4349 case GL_HIGH_FLOAT:
4350 case GL_LOW_INT:
4351 case GL_MEDIUM_INT:
4352 case GL_HIGH_INT:
4353 break;
4354
4355 default:
4356 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4357 return false;
4358 }
4359
4360 return true;
4361}
4362
4363bool ValidateGetShaderSource(ValidationContext *context,
4364 GLuint shader,
4365 GLsizei bufsize,
4366 GLsizei *length,
4367 GLchar *source)
4368{
4369 if (bufsize < 0)
4370 {
4371 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4372 return false;
4373 }
4374
4375 Shader *shaderObject = GetValidShader(context, shader);
4376 if (!shaderObject)
4377 {
4378 return false;
4379 }
4380
4381 return true;
4382}
4383
4384bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4385{
4386 if (strstr(name, "gl_") == name)
4387 {
4388 return false;
4389 }
4390
4391 Program *programObject = GetValidProgram(context, program);
4392
4393 if (!programObject)
4394 {
4395 return false;
4396 }
4397
4398 if (!programObject->isLinked())
4399 {
4400 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4401 return false;
4402 }
4403
4404 return true;
4405}
4406
4407bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4408{
4409 switch (mode)
4410 {
4411 case GL_FASTEST:
4412 case GL_NICEST:
4413 case GL_DONT_CARE:
4414 break;
4415
4416 default:
4417 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4418 return false;
4419 }
4420
4421 switch (target)
4422 {
4423 case GL_GENERATE_MIPMAP_HINT:
4424 break;
4425
4426 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4427 if (!context->getExtensions().standardDerivatives)
4428 {
4429 context->handleError(
4430 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4431 return false;
4432 }
4433 break;
4434
4435 default:
4436 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4437 return false;
4438 }
4439
4440 return true;
4441}
4442
4443bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4444{
4445 return true;
4446}
4447
4448bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4449{
4450 return true;
4451}
4452
4453bool ValidateIsProgram(ValidationContext *context, GLuint program)
4454{
4455 return true;
4456}
4457
4458bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4459{
4460 return true;
4461}
4462
4463bool ValidateIsShader(ValidationContext *context, GLuint shader)
4464{
4465 return true;
4466}
4467
4468bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4469{
4470 return true;
4471}
4472
4473bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4474{
4475 if (context->getClientMajorVersion() < 3)
4476 {
4477 switch (pname)
4478 {
4479 case GL_UNPACK_IMAGE_HEIGHT:
4480 case GL_UNPACK_SKIP_IMAGES:
4481 context->handleError(Error(GL_INVALID_ENUM));
4482 return false;
4483
4484 case GL_UNPACK_ROW_LENGTH:
4485 case GL_UNPACK_SKIP_ROWS:
4486 case GL_UNPACK_SKIP_PIXELS:
4487 if (!context->getExtensions().unpackSubimage)
4488 {
4489 context->handleError(Error(GL_INVALID_ENUM));
4490 return false;
4491 }
4492 break;
4493
4494 case GL_PACK_ROW_LENGTH:
4495 case GL_PACK_SKIP_ROWS:
4496 case GL_PACK_SKIP_PIXELS:
4497 if (!context->getExtensions().packSubimage)
4498 {
4499 context->handleError(Error(GL_INVALID_ENUM));
4500 return false;
4501 }
4502 break;
4503 }
4504 }
4505
4506 if (param < 0)
4507 {
4508 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4509 return false;
4510 }
4511
4512 switch (pname)
4513 {
4514 case GL_UNPACK_ALIGNMENT:
4515 if (param != 1 && param != 2 && param != 4 && param != 8)
4516 {
4517 context->handleError(Error(GL_INVALID_VALUE));
4518 return false;
4519 }
4520 break;
4521
4522 case GL_PACK_ALIGNMENT:
4523 if (param != 1 && param != 2 && param != 4 && param != 8)
4524 {
4525 context->handleError(Error(GL_INVALID_VALUE));
4526 return false;
4527 }
4528 break;
4529
4530 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4531 case GL_UNPACK_ROW_LENGTH:
4532 case GL_UNPACK_IMAGE_HEIGHT:
4533 case GL_UNPACK_SKIP_IMAGES:
4534 case GL_UNPACK_SKIP_ROWS:
4535 case GL_UNPACK_SKIP_PIXELS:
4536 case GL_PACK_ROW_LENGTH:
4537 case GL_PACK_SKIP_ROWS:
4538 case GL_PACK_SKIP_PIXELS:
4539 break;
4540
4541 default:
4542 context->handleError(Error(GL_INVALID_ENUM));
4543 return false;
4544 }
4545
4546 return true;
4547}
4548
4549bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4550{
4551 return true;
4552}
4553
4554bool ValidateReleaseShaderCompiler(ValidationContext *context)
4555{
4556 return true;
4557}
4558
4559bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert)
4560{
4561 return true;
4562}
4563
4564bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4565{
4566 if (width < 0 || height < 0)
4567 {
4568 context->handleError(
4569 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4570 return false;
4571 }
4572
4573 return true;
4574}
4575
4576bool ValidateShaderBinary(ValidationContext *context,
4577 GLsizei n,
4578 const GLuint *shaders,
4579 GLenum binaryformat,
4580 const GLvoid *binary,
4581 GLsizei length)
4582{
4583 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4584 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4585 shaderBinaryFormats.end())
4586 {
4587 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4588 return false;
4589 }
4590
4591 return true;
4592}
4593
4594bool ValidateShaderSource(ValidationContext *context,
4595 GLuint shader,
4596 GLsizei count,
4597 const GLchar *const *string,
4598 const GLint *length)
4599{
4600 if (count < 0)
4601 {
4602 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4603 return false;
4604 }
4605
4606 Shader *shaderObject = GetValidShader(context, shader);
4607 if (!shaderObject)
4608 {
4609 return false;
4610 }
4611
4612 return true;
4613}
4614
4615bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4616{
4617 if (!IsValidStencilFunc(func))
4618 {
4619 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4620 return false;
4621 }
4622
4623 return true;
4624}
4625
4626bool ValidateStencilFuncSeparate(ValidationContext *context,
4627 GLenum face,
4628 GLenum func,
4629 GLint ref,
4630 GLuint mask)
4631{
4632 if (!IsValidStencilFace(face))
4633 {
4634 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4635 return false;
4636 }
4637
4638 if (!IsValidStencilFunc(func))
4639 {
4640 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4641 return false;
4642 }
4643
4644 return true;
4645}
4646
4647bool ValidateStencilMask(ValidationContext *context, GLuint mask)
4648{
4649 return true;
4650}
4651
4652bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
4653{
4654 if (!IsValidStencilFace(face))
4655 {
4656 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4657 return false;
4658 }
4659
4660 return true;
4661}
4662
4663bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
4664{
4665 if (!IsValidStencilOp(fail))
4666 {
4667 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
4668 return false;
4669 }
4670
4671 if (!IsValidStencilOp(zfail))
4672 {
4673 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
4674 return false;
4675 }
4676
4677 if (!IsValidStencilOp(zpass))
4678 {
4679 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
4680 return false;
4681 }
4682
4683 return true;
4684}
4685
4686bool ValidateStencilOpSeparate(ValidationContext *context,
4687 GLenum face,
4688 GLenum fail,
4689 GLenum zfail,
4690 GLenum zpass)
4691{
4692 if (!IsValidStencilFace(face))
4693 {
4694 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4695 return false;
4696 }
4697
4698 return ValidateStencilOp(context, fail, zfail, zpass);
4699}
4700
4701bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
4702{
4703 return ValidateUniform(context, GL_FLOAT, location, 1);
4704}
4705
4706bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4707{
4708 return ValidateUniform(context, GL_FLOAT, location, count);
4709}
4710
4711bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
4712{
4713 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
4714}
4715
4716bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4717{
4718 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
4719}
4720
4721bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
4722{
4723 return ValidateUniform(context, GL_INT_VEC2, location, 1);
4724}
4725
4726bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4727{
4728 return ValidateUniform(context, GL_INT_VEC2, location, count);
4729}
4730
4731bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
4732{
4733 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
4734}
4735
4736bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4737{
4738 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
4739}
4740
4741bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
4742{
4743 return ValidateUniform(context, GL_INT_VEC3, location, 1);
4744}
4745
4746bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4747{
4748 return ValidateUniform(context, GL_INT_VEC3, location, count);
4749}
4750
4751bool ValidateUniform4f(ValidationContext *context,
4752 GLint location,
4753 GLfloat x,
4754 GLfloat y,
4755 GLfloat z,
4756 GLfloat w)
4757{
4758 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
4759}
4760
4761bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4762{
4763 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
4764}
4765
4766bool ValidateUniform4i(ValidationContext *context,
4767 GLint location,
4768 GLint x,
4769 GLint y,
4770 GLint z,
4771 GLint w)
4772{
4773 return ValidateUniform(context, GL_INT_VEC4, location, 1);
4774}
4775
4776bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4777{
4778 return ValidateUniform(context, GL_INT_VEC4, location, count);
4779}
4780
4781bool ValidateUniformMatrix2fv(ValidationContext *context,
4782 GLint location,
4783 GLsizei count,
4784 GLboolean transpose,
4785 const GLfloat *value)
4786{
4787 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
4788}
4789
4790bool ValidateUniformMatrix3fv(ValidationContext *context,
4791 GLint location,
4792 GLsizei count,
4793 GLboolean transpose,
4794 const GLfloat *value)
4795{
4796 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
4797}
4798
4799bool ValidateUniformMatrix4fv(ValidationContext *context,
4800 GLint location,
4801 GLsizei count,
4802 GLboolean transpose,
4803 const GLfloat *value)
4804{
4805 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
4806}
4807
4808bool ValidateValidateProgram(ValidationContext *context, GLuint program)
4809{
4810 Program *programObject = GetValidProgram(context, program);
4811
4812 if (!programObject)
4813 {
4814 return false;
4815 }
4816
4817 return true;
4818}
4819
4820bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
4821{
4822 if (index >= MAX_VERTEX_ATTRIBS)
4823 {
4824 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
4825 return false;
4826 }
4827
4828 return true;
4829}
4830
4831bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
4832{
4833 return ValidateVertexAttribIndex(context, index);
4834}
4835
4836bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
4837{
4838 return ValidateVertexAttribIndex(context, index);
4839}
4840
4841bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
4842{
4843 return ValidateVertexAttribIndex(context, index);
4844}
4845
4846bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
4847{
4848 return ValidateVertexAttribIndex(context, index);
4849}
4850
4851bool ValidateVertexAttrib3f(ValidationContext *context,
4852 GLuint index,
4853 GLfloat x,
4854 GLfloat y,
4855 GLfloat z)
4856{
4857 return ValidateVertexAttribIndex(context, index);
4858}
4859
4860bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
4861{
4862 return ValidateVertexAttribIndex(context, index);
4863}
4864
4865bool ValidateVertexAttrib4f(ValidationContext *context,
4866 GLuint index,
4867 GLfloat x,
4868 GLfloat y,
4869 GLfloat z,
4870 GLfloat w)
4871{
4872 return ValidateVertexAttribIndex(context, index);
4873}
4874
4875bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
4876{
4877 return ValidateVertexAttribIndex(context, index);
4878}
4879
4880bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4881{
4882 if (width < 0 || height < 0)
4883 {
4884 context->handleError(
4885 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
4886 return false;
4887 }
4888
4889 return true;
4890}
4891
4892bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
4893{
4894 return ValidateDrawArraysCommon(context, mode, first, count, 1);
4895}
4896
Jamie Madillc29968b2016-01-20 11:17:23 -05004897} // namespace gl