blob: 657522cc28d886bb9b265d383fe5c85ed677455f [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 Lang44ff5a72017-02-03 15:15:43 -0500527 if (!ValidCompressedImageSize(context, actualInternalFormat, xoffset, yoffset, width,
528 height))
tmartino0ccd5ae2015-10-01 14:33:14 -0400529 {
Jamie Madill437fa652016-05-03 15:13:24 -0400530 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400531 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400532 }
533 }
534 else
535 {
536 // validate <type> by itself (used as secondary key below)
537 switch (type)
538 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800539 case GL_UNSIGNED_BYTE:
540 case GL_UNSIGNED_SHORT_5_6_5:
541 case GL_UNSIGNED_SHORT_4_4_4_4:
542 case GL_UNSIGNED_SHORT_5_5_5_1:
543 case GL_UNSIGNED_SHORT:
544 case GL_UNSIGNED_INT:
545 case GL_UNSIGNED_INT_24_8_OES:
546 case GL_HALF_FLOAT_OES:
547 case GL_FLOAT:
548 break;
549 default:
550 context->handleError(Error(GL_INVALID_ENUM));
551 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400552 }
553
554 // validate <format> + <type> combinations
555 // - invalid <format> -> sets INVALID_ENUM
556 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
557 switch (format)
558 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800559 case GL_ALPHA:
560 case GL_LUMINANCE:
561 case GL_LUMINANCE_ALPHA:
562 switch (type)
563 {
564 case GL_UNSIGNED_BYTE:
565 case GL_FLOAT:
566 case GL_HALF_FLOAT_OES:
567 break;
568 default:
569 context->handleError(Error(GL_INVALID_OPERATION));
570 return false;
571 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400572 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800573 case GL_RED:
574 case GL_RG:
575 if (!context->getExtensions().textureRG)
576 {
577 context->handleError(Error(GL_INVALID_ENUM));
578 return false;
579 }
580 switch (type)
581 {
582 case GL_UNSIGNED_BYTE:
583 case GL_FLOAT:
584 case GL_HALF_FLOAT_OES:
585 break;
586 default:
587 context->handleError(Error(GL_INVALID_OPERATION));
588 return false;
589 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400590 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800591 case GL_RGB:
592 switch (type)
593 {
594 case GL_UNSIGNED_BYTE:
595 case GL_UNSIGNED_SHORT_5_6_5:
596 case GL_FLOAT:
597 case GL_HALF_FLOAT_OES:
598 break;
599 default:
600 context->handleError(Error(GL_INVALID_OPERATION));
601 return false;
602 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400603 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800604 case GL_RGBA:
605 switch (type)
606 {
607 case GL_UNSIGNED_BYTE:
608 case GL_UNSIGNED_SHORT_4_4_4_4:
609 case GL_UNSIGNED_SHORT_5_5_5_1:
610 case GL_FLOAT:
611 case GL_HALF_FLOAT_OES:
612 break;
613 default:
614 context->handleError(Error(GL_INVALID_OPERATION));
615 return false;
616 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400617 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800618 case GL_BGRA_EXT:
619 switch (type)
620 {
621 case GL_UNSIGNED_BYTE:
622 break;
623 default:
624 context->handleError(Error(GL_INVALID_OPERATION));
625 return false;
626 }
627 break;
628 case GL_SRGB_EXT:
629 case GL_SRGB_ALPHA_EXT:
630 if (!context->getExtensions().sRGB)
631 {
632 context->handleError(Error(GL_INVALID_ENUM));
633 return false;
634 }
635 switch (type)
636 {
637 case GL_UNSIGNED_BYTE:
638 break;
639 default:
640 context->handleError(Error(GL_INVALID_OPERATION));
641 return false;
642 }
643 break;
644 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
645 // handled below
646 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
647 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
648 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
649 break;
650 case GL_DEPTH_COMPONENT:
651 switch (type)
652 {
653 case GL_UNSIGNED_SHORT:
654 case GL_UNSIGNED_INT:
655 break;
656 default:
657 context->handleError(Error(GL_INVALID_OPERATION));
658 return false;
659 }
660 break;
661 case GL_DEPTH_STENCIL_OES:
662 switch (type)
663 {
664 case GL_UNSIGNED_INT_24_8_OES:
665 break;
666 default:
667 context->handleError(Error(GL_INVALID_OPERATION));
668 return false;
669 }
670 break;
671 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400672 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400673 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400674 }
675
676 switch (format)
677 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800678 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
679 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
680 if (context->getExtensions().textureCompressionDXT1)
681 {
682 context->handleError(Error(GL_INVALID_OPERATION));
683 return false;
684 }
685 else
686 {
687 context->handleError(Error(GL_INVALID_ENUM));
688 return false;
689 }
690 break;
691 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
692 if (context->getExtensions().textureCompressionDXT3)
693 {
694 context->handleError(Error(GL_INVALID_OPERATION));
695 return false;
696 }
697 else
698 {
699 context->handleError(Error(GL_INVALID_ENUM));
700 return false;
701 }
702 break;
703 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
704 if (context->getExtensions().textureCompressionDXT5)
705 {
706 context->handleError(Error(GL_INVALID_OPERATION));
707 return false;
708 }
709 else
710 {
711 context->handleError(Error(GL_INVALID_ENUM));
712 return false;
713 }
714 break;
715 case GL_ETC1_RGB8_OES:
716 if (context->getExtensions().compressedETC1RGB8Texture)
717 {
718 context->handleError(Error(GL_INVALID_OPERATION));
719 return false;
720 }
721 else
722 {
723 context->handleError(Error(GL_INVALID_ENUM));
724 return false;
725 }
726 break;
727 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800728 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
729 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
730 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
731 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800732 if (context->getExtensions().lossyETCDecode)
733 {
734 context->handleError(
735 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -0800736 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +0800737 return false;
738 }
739 else
740 {
741 context->handleError(Error(
742 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
743 return false;
744 }
745 break;
746 case GL_DEPTH_COMPONENT:
747 case GL_DEPTH_STENCIL_OES:
748 if (!context->getExtensions().depthTextures)
749 {
750 context->handleError(Error(GL_INVALID_VALUE));
751 return false;
752 }
753 if (target != GL_TEXTURE_2D)
754 {
755 context->handleError(Error(GL_INVALID_OPERATION));
756 return false;
757 }
758 // OES_depth_texture supports loading depth data and multiple levels,
759 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +0800760 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +0800761 {
762 context->handleError(Error(GL_INVALID_OPERATION));
763 return false;
764 }
765 break;
766 default:
767 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 }
769
770 if (type == GL_FLOAT)
771 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400772 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400773 {
Jamie Madill437fa652016-05-03 15:13:24 -0400774 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400775 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 }
777 }
778 else if (type == GL_HALF_FLOAT_OES)
779 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400780 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400781 {
Jamie Madill437fa652016-05-03 15:13:24 -0400782 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400783 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784 }
785 }
786 }
787
Geoff Langff5b2d52016-09-07 11:32:23 -0400788 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
789 imageSize))
790 {
791 return false;
792 }
793
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 return true;
795}
796
He Yunchaoced53ae2016-11-29 15:00:51 +0800797bool ValidateES2TexStorageParameters(Context *context,
798 GLenum target,
799 GLsizei levels,
800 GLenum internalformat,
801 GLsizei width,
802 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803{
804 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
805 {
Jamie Madill437fa652016-05-03 15:13:24 -0400806 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400807 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808 }
809
810 if (width < 1 || height < 1 || levels < 1)
811 {
Jamie Madill437fa652016-05-03 15:13:24 -0400812 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400813 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 }
815
816 if (target == GL_TEXTURE_CUBE_MAP && width != height)
817 {
Jamie Madill437fa652016-05-03 15:13:24 -0400818 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400819 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400820 }
821
822 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
823 {
Jamie Madill437fa652016-05-03 15:13:24 -0400824 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400825 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 }
827
Geoff Langca271392017-04-05 12:30:00 -0400828 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400829 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 {
Jamie Madill437fa652016-05-03 15:13:24 -0400831 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400832 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400833 }
834
Geoff Langaae65a42014-05-26 12:43:44 -0400835 const gl::Caps &caps = context->getCaps();
836
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400837 switch (target)
838 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800839 case GL_TEXTURE_2D:
840 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
841 static_cast<GLuint>(height) > caps.max2DTextureSize)
842 {
843 context->handleError(Error(GL_INVALID_VALUE));
844 return false;
845 }
846 break;
847 case GL_TEXTURE_CUBE_MAP:
848 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
849 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
850 {
851 context->handleError(Error(GL_INVALID_VALUE));
852 return false;
853 }
854 break;
855 default:
856 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859
Geoff Langc0b9ef42014-07-02 10:02:37 -0400860 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400861 {
862 if (!gl::isPow2(width) || !gl::isPow2(height))
863 {
Jamie Madill437fa652016-05-03 15:13:24 -0400864 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400865 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 }
867 }
868
869 switch (internalformat)
870 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800871 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
872 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
873 if (!context->getExtensions().textureCompressionDXT1)
874 {
875 context->handleError(Error(GL_INVALID_ENUM));
876 return false;
877 }
878 break;
879 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
880 if (!context->getExtensions().textureCompressionDXT3)
881 {
882 context->handleError(Error(GL_INVALID_ENUM));
883 return false;
884 }
885 break;
886 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
887 if (!context->getExtensions().textureCompressionDXT5)
888 {
889 context->handleError(Error(GL_INVALID_ENUM));
890 return false;
891 }
892 break;
893 case GL_ETC1_RGB8_OES:
894 if (!context->getExtensions().compressedETC1RGB8Texture)
895 {
896 context->handleError(Error(GL_INVALID_ENUM));
897 return false;
898 }
899 break;
900 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800901 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
902 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
903 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
904 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800905 if (!context->getExtensions().lossyETCDecode)
906 {
907 context->handleError(
908 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
909 return false;
910 }
911 break;
912 case GL_RGBA32F_EXT:
913 case GL_RGB32F_EXT:
914 case GL_ALPHA32F_EXT:
915 case GL_LUMINANCE32F_EXT:
916 case GL_LUMINANCE_ALPHA32F_EXT:
917 if (!context->getExtensions().textureFloat)
918 {
919 context->handleError(Error(GL_INVALID_ENUM));
920 return false;
921 }
922 break;
923 case GL_RGBA16F_EXT:
924 case GL_RGB16F_EXT:
925 case GL_ALPHA16F_EXT:
926 case GL_LUMINANCE16F_EXT:
927 case GL_LUMINANCE_ALPHA16F_EXT:
928 if (!context->getExtensions().textureHalfFloat)
929 {
930 context->handleError(Error(GL_INVALID_ENUM));
931 return false;
932 }
933 break;
934 case GL_R8_EXT:
935 case GL_RG8_EXT:
936 case GL_R16F_EXT:
937 case GL_RG16F_EXT:
938 case GL_R32F_EXT:
939 case GL_RG32F_EXT:
940 if (!context->getExtensions().textureRG)
941 {
942 context->handleError(Error(GL_INVALID_ENUM));
943 return false;
944 }
945 break;
946 case GL_DEPTH_COMPONENT16:
947 case GL_DEPTH_COMPONENT32_OES:
948 case GL_DEPTH24_STENCIL8_OES:
949 if (!context->getExtensions().depthTextures)
950 {
951 context->handleError(Error(GL_INVALID_ENUM));
952 return false;
953 }
954 if (target != GL_TEXTURE_2D)
955 {
956 context->handleError(Error(GL_INVALID_OPERATION));
957 return false;
958 }
959 // ANGLE_depth_texture only supports 1-level textures
960 if (levels != 1)
961 {
962 context->handleError(Error(GL_INVALID_OPERATION));
963 return false;
964 }
965 break;
966 default:
967 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 }
969
Geoff Lang691e58c2014-12-19 17:03:25 -0500970 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400971 if (!texture || texture->id() == 0)
972 {
Jamie Madill437fa652016-05-03 15:13:24 -0400973 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400975 }
976
Geoff Lang69cce582015-09-17 13:20:36 -0400977 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400978 {
Jamie Madill437fa652016-05-03 15:13:24 -0400979 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400980 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400981 }
982
983 return true;
984}
985
He Yunchaoced53ae2016-11-29 15:00:51 +0800986bool ValidateDiscardFramebufferEXT(Context *context,
987 GLenum target,
988 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -0700989 const GLenum *attachments)
990{
Jamie Madillc29968b2016-01-20 11:17:23 -0500991 if (!context->getExtensions().discardFramebuffer)
992 {
Jamie Madill437fa652016-05-03 15:13:24 -0400993 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -0500994 return false;
995 }
996
Austin Kinross08332632015-05-05 13:35:47 -0700997 bool defaultFramebuffer = false;
998
999 switch (target)
1000 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001001 case GL_FRAMEBUFFER:
1002 defaultFramebuffer =
1003 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1004 break;
1005 default:
1006 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1007 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001008 }
1009
He Yunchaoced53ae2016-11-29 15:00:51 +08001010 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1011 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001012}
1013
Austin Kinrossbc781f32015-10-26 09:27:38 -07001014bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1015{
1016 if (!context->getExtensions().vertexArrayObject)
1017 {
Jamie Madill437fa652016-05-03 15:13:24 -04001018 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001019 return false;
1020 }
1021
1022 return ValidateBindVertexArrayBase(context, array);
1023}
1024
1025bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1026{
1027 if (!context->getExtensions().vertexArrayObject)
1028 {
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001030 return false;
1031 }
1032
Olli Etuaho41997e72016-03-10 13:38:39 +02001033 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001034}
1035
1036bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
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
Olli Etuaho41997e72016-03-10 13:38:39 +02001044 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001045}
1046
1047bool ValidateIsVertexArrayOES(Context *context)
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
1055 return true;
1056}
Geoff Langc5629752015-12-07 16:29:04 -05001057
1058bool ValidateProgramBinaryOES(Context *context,
1059 GLuint program,
1060 GLenum binaryFormat,
1061 const void *binary,
1062 GLint length)
1063{
1064 if (!context->getExtensions().getProgramBinary)
1065 {
Jamie Madill437fa652016-05-03 15:13:24 -04001066 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001067 return false;
1068 }
1069
1070 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1071}
1072
1073bool ValidateGetProgramBinaryOES(Context *context,
1074 GLuint program,
1075 GLsizei bufSize,
1076 GLsizei *length,
1077 GLenum *binaryFormat,
1078 void *binary)
1079{
1080 if (!context->getExtensions().getProgramBinary)
1081 {
Jamie Madill437fa652016-05-03 15:13:24 -04001082 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001083 return false;
1084 }
1085
1086 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1087}
Geoff Lange102fee2015-12-10 11:23:30 -05001088
Geoff Lang70d0f492015-12-10 17:45:46 -05001089static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1090{
1091 switch (source)
1092 {
1093 case GL_DEBUG_SOURCE_API:
1094 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1095 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1096 case GL_DEBUG_SOURCE_OTHER:
1097 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1098 return !mustBeThirdPartyOrApplication;
1099
1100 case GL_DEBUG_SOURCE_THIRD_PARTY:
1101 case GL_DEBUG_SOURCE_APPLICATION:
1102 return true;
1103
1104 default:
1105 return false;
1106 }
1107}
1108
1109static bool ValidDebugType(GLenum type)
1110{
1111 switch (type)
1112 {
1113 case GL_DEBUG_TYPE_ERROR:
1114 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1115 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1116 case GL_DEBUG_TYPE_PERFORMANCE:
1117 case GL_DEBUG_TYPE_PORTABILITY:
1118 case GL_DEBUG_TYPE_OTHER:
1119 case GL_DEBUG_TYPE_MARKER:
1120 case GL_DEBUG_TYPE_PUSH_GROUP:
1121 case GL_DEBUG_TYPE_POP_GROUP:
1122 return true;
1123
1124 default:
1125 return false;
1126 }
1127}
1128
1129static bool ValidDebugSeverity(GLenum severity)
1130{
1131 switch (severity)
1132 {
1133 case GL_DEBUG_SEVERITY_HIGH:
1134 case GL_DEBUG_SEVERITY_MEDIUM:
1135 case GL_DEBUG_SEVERITY_LOW:
1136 case GL_DEBUG_SEVERITY_NOTIFICATION:
1137 return true;
1138
1139 default:
1140 return false;
1141 }
1142}
1143
Geoff Lange102fee2015-12-10 11:23:30 -05001144bool ValidateDebugMessageControlKHR(Context *context,
1145 GLenum source,
1146 GLenum type,
1147 GLenum severity,
1148 GLsizei count,
1149 const GLuint *ids,
1150 GLboolean enabled)
1151{
1152 if (!context->getExtensions().debug)
1153 {
Jamie Madill437fa652016-05-03 15:13:24 -04001154 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001155 return false;
1156 }
1157
Geoff Lang70d0f492015-12-10 17:45:46 -05001158 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1159 {
Jamie Madill437fa652016-05-03 15:13:24 -04001160 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001161 return false;
1162 }
1163
1164 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1165 {
Jamie Madill437fa652016-05-03 15:13:24 -04001166 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001167 return false;
1168 }
1169
1170 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1171 {
Jamie Madill437fa652016-05-03 15:13:24 -04001172 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001173 return false;
1174 }
1175
1176 if (count > 0)
1177 {
1178 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1179 {
Jamie Madill437fa652016-05-03 15:13:24 -04001180 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001181 GL_INVALID_OPERATION,
1182 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1183 return false;
1184 }
1185
1186 if (severity != GL_DONT_CARE)
1187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001189 Error(GL_INVALID_OPERATION,
1190 "If count is greater than zero, severity must be GL_DONT_CARE."));
1191 return false;
1192 }
1193 }
1194
Geoff Lange102fee2015-12-10 11:23:30 -05001195 return true;
1196}
1197
1198bool ValidateDebugMessageInsertKHR(Context *context,
1199 GLenum source,
1200 GLenum type,
1201 GLuint id,
1202 GLenum severity,
1203 GLsizei length,
1204 const GLchar *buf)
1205{
1206 if (!context->getExtensions().debug)
1207 {
Jamie Madill437fa652016-05-03 15:13:24 -04001208 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001209 return false;
1210 }
1211
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001212 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001213 {
1214 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1215 // not generate an error.
1216 return false;
1217 }
1218
1219 if (!ValidDebugSeverity(severity))
1220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001222 return false;
1223 }
1224
1225 if (!ValidDebugType(type))
1226 {
Jamie Madill437fa652016-05-03 15:13:24 -04001227 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001228 return false;
1229 }
1230
1231 if (!ValidDebugSource(source, true))
1232 {
Jamie Madill437fa652016-05-03 15:13:24 -04001233 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001234 return false;
1235 }
1236
1237 size_t messageLength = (length < 0) ? strlen(buf) : length;
1238 if (messageLength > context->getExtensions().maxDebugMessageLength)
1239 {
Jamie Madill437fa652016-05-03 15:13:24 -04001240 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001241 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1242 return false;
1243 }
1244
Geoff Lange102fee2015-12-10 11:23:30 -05001245 return true;
1246}
1247
1248bool ValidateDebugMessageCallbackKHR(Context *context,
1249 GLDEBUGPROCKHR callback,
1250 const void *userParam)
1251{
1252 if (!context->getExtensions().debug)
1253 {
Jamie Madill437fa652016-05-03 15:13:24 -04001254 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001255 return false;
1256 }
1257
Geoff Lange102fee2015-12-10 11:23:30 -05001258 return true;
1259}
1260
1261bool ValidateGetDebugMessageLogKHR(Context *context,
1262 GLuint count,
1263 GLsizei bufSize,
1264 GLenum *sources,
1265 GLenum *types,
1266 GLuint *ids,
1267 GLenum *severities,
1268 GLsizei *lengths,
1269 GLchar *messageLog)
1270{
1271 if (!context->getExtensions().debug)
1272 {
Jamie Madill437fa652016-05-03 15:13:24 -04001273 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001274 return false;
1275 }
1276
Geoff Lang70d0f492015-12-10 17:45:46 -05001277 if (bufSize < 0 && messageLog != nullptr)
1278 {
Jamie Madill437fa652016-05-03 15:13:24 -04001279 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001280 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1281 return false;
1282 }
1283
Geoff Lange102fee2015-12-10 11:23:30 -05001284 return true;
1285}
1286
1287bool ValidatePushDebugGroupKHR(Context *context,
1288 GLenum source,
1289 GLuint id,
1290 GLsizei length,
1291 const GLchar *message)
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 (!ValidDebugSource(source, true))
1300 {
Jamie Madill437fa652016-05-03 15:13:24 -04001301 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001302 return false;
1303 }
1304
1305 size_t messageLength = (length < 0) ? strlen(message) : length;
1306 if (messageLength > context->getExtensions().maxDebugMessageLength)
1307 {
Jamie Madill437fa652016-05-03 15:13:24 -04001308 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001309 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1310 return false;
1311 }
1312
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001313 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001314 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1315 {
Jamie Madill437fa652016-05-03 15:13:24 -04001316 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001317 Error(GL_STACK_OVERFLOW,
1318 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1319 return false;
1320 }
1321
Geoff Lange102fee2015-12-10 11:23:30 -05001322 return true;
1323}
1324
1325bool ValidatePopDebugGroupKHR(Context *context)
1326{
1327 if (!context->getExtensions().debug)
1328 {
Jamie Madill437fa652016-05-03 15:13:24 -04001329 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001330 return false;
1331 }
1332
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001333 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001334 if (currentStackSize <= 1)
1335 {
Jamie Madill437fa652016-05-03 15:13:24 -04001336 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001337 return false;
1338 }
1339
1340 return true;
1341}
1342
1343static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1344{
1345 switch (identifier)
1346 {
1347 case GL_BUFFER:
1348 if (context->getBuffer(name) == nullptr)
1349 {
Jamie Madill437fa652016-05-03 15:13:24 -04001350 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001351 return false;
1352 }
1353 return true;
1354
1355 case GL_SHADER:
1356 if (context->getShader(name) == nullptr)
1357 {
Jamie Madill437fa652016-05-03 15:13:24 -04001358 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001359 return false;
1360 }
1361 return true;
1362
1363 case GL_PROGRAM:
1364 if (context->getProgram(name) == nullptr)
1365 {
Jamie Madill437fa652016-05-03 15:13:24 -04001366 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001367 return false;
1368 }
1369 return true;
1370
1371 case GL_VERTEX_ARRAY:
1372 if (context->getVertexArray(name) == nullptr)
1373 {
Jamie Madill437fa652016-05-03 15:13:24 -04001374 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001375 return false;
1376 }
1377 return true;
1378
1379 case GL_QUERY:
1380 if (context->getQuery(name) == nullptr)
1381 {
Jamie Madill437fa652016-05-03 15:13:24 -04001382 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001383 return false;
1384 }
1385 return true;
1386
1387 case GL_TRANSFORM_FEEDBACK:
1388 if (context->getTransformFeedback(name) == nullptr)
1389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001391 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1392 return false;
1393 }
1394 return true;
1395
1396 case GL_SAMPLER:
1397 if (context->getSampler(name) == nullptr)
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001400 return false;
1401 }
1402 return true;
1403
1404 case GL_TEXTURE:
1405 if (context->getTexture(name) == nullptr)
1406 {
Jamie Madill437fa652016-05-03 15:13:24 -04001407 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001408 return false;
1409 }
1410 return true;
1411
1412 case GL_RENDERBUFFER:
1413 if (context->getRenderbuffer(name) == nullptr)
1414 {
Jamie Madill437fa652016-05-03 15:13:24 -04001415 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001416 return false;
1417 }
1418 return true;
1419
1420 case GL_FRAMEBUFFER:
1421 if (context->getFramebuffer(name) == nullptr)
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001424 return false;
1425 }
1426 return true;
1427
1428 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001429 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001430 return false;
1431 }
Geoff Lange102fee2015-12-10 11:23:30 -05001432}
1433
Martin Radev9d901792016-07-15 15:58:58 +03001434static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1435{
1436 size_t labelLength = 0;
1437
1438 if (length < 0)
1439 {
1440 if (label != nullptr)
1441 {
1442 labelLength = strlen(label);
1443 }
1444 }
1445 else
1446 {
1447 labelLength = static_cast<size_t>(length);
1448 }
1449
1450 if (labelLength > context->getExtensions().maxLabelLength)
1451 {
1452 context->handleError(
1453 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1454 return false;
1455 }
1456
1457 return true;
1458}
1459
Geoff Lange102fee2015-12-10 11:23:30 -05001460bool ValidateObjectLabelKHR(Context *context,
1461 GLenum identifier,
1462 GLuint name,
1463 GLsizei length,
1464 const GLchar *label)
1465{
1466 if (!context->getExtensions().debug)
1467 {
Jamie Madill437fa652016-05-03 15:13:24 -04001468 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001469 return false;
1470 }
1471
Geoff Lang70d0f492015-12-10 17:45:46 -05001472 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1473 {
1474 return false;
1475 }
1476
Martin Radev9d901792016-07-15 15:58:58 +03001477 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001478 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001479 return false;
1480 }
1481
Geoff Lange102fee2015-12-10 11:23:30 -05001482 return true;
1483}
1484
1485bool ValidateGetObjectLabelKHR(Context *context,
1486 GLenum identifier,
1487 GLuint name,
1488 GLsizei bufSize,
1489 GLsizei *length,
1490 GLchar *label)
1491{
1492 if (!context->getExtensions().debug)
1493 {
Jamie Madill437fa652016-05-03 15:13:24 -04001494 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001495 return false;
1496 }
1497
Geoff Lang70d0f492015-12-10 17:45:46 -05001498 if (bufSize < 0)
1499 {
Jamie Madill437fa652016-05-03 15:13:24 -04001500 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001501 return false;
1502 }
1503
1504 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1505 {
1506 return false;
1507 }
1508
Martin Radev9d901792016-07-15 15:58:58 +03001509 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001510}
1511
1512static bool ValidateObjectPtrName(Context *context, const void *ptr)
1513{
1514 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1515 {
Jamie Madill437fa652016-05-03 15:13:24 -04001516 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001517 return false;
1518 }
1519
Geoff Lange102fee2015-12-10 11:23:30 -05001520 return true;
1521}
1522
1523bool ValidateObjectPtrLabelKHR(Context *context,
1524 const void *ptr,
1525 GLsizei length,
1526 const GLchar *label)
1527{
1528 if (!context->getExtensions().debug)
1529 {
Jamie Madill437fa652016-05-03 15:13:24 -04001530 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001531 return false;
1532 }
1533
Geoff Lang70d0f492015-12-10 17:45:46 -05001534 if (!ValidateObjectPtrName(context, ptr))
1535 {
1536 return false;
1537 }
1538
Martin Radev9d901792016-07-15 15:58:58 +03001539 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001540 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001541 return false;
1542 }
1543
Geoff Lange102fee2015-12-10 11:23:30 -05001544 return true;
1545}
1546
1547bool ValidateGetObjectPtrLabelKHR(Context *context,
1548 const void *ptr,
1549 GLsizei bufSize,
1550 GLsizei *length,
1551 GLchar *label)
1552{
1553 if (!context->getExtensions().debug)
1554 {
Jamie Madill437fa652016-05-03 15:13:24 -04001555 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001556 return false;
1557 }
1558
Geoff Lang70d0f492015-12-10 17:45:46 -05001559 if (bufSize < 0)
1560 {
Jamie Madill437fa652016-05-03 15:13:24 -04001561 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001562 return false;
1563 }
1564
1565 if (!ValidateObjectPtrName(context, ptr))
1566 {
1567 return false;
1568 }
1569
Martin Radev9d901792016-07-15 15:58:58 +03001570 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001571}
1572
1573bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
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 // TODO: represent this in Context::getQueryParameterInfo.
1582 switch (pname)
1583 {
1584 case GL_DEBUG_CALLBACK_FUNCTION:
1585 case GL_DEBUG_CALLBACK_USER_PARAM:
1586 break;
1587
1588 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001589 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001590 return false;
1591 }
1592
Geoff Lange102fee2015-12-10 11:23:30 -05001593 return true;
1594}
Jamie Madillc29968b2016-01-20 11:17:23 -05001595
1596bool ValidateBlitFramebufferANGLE(Context *context,
1597 GLint srcX0,
1598 GLint srcY0,
1599 GLint srcX1,
1600 GLint srcY1,
1601 GLint dstX0,
1602 GLint dstY0,
1603 GLint dstX1,
1604 GLint dstY1,
1605 GLbitfield mask,
1606 GLenum filter)
1607{
1608 if (!context->getExtensions().framebufferBlit)
1609 {
Jamie Madill437fa652016-05-03 15:13:24 -04001610 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 return false;
1612 }
1613
1614 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1615 {
1616 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001617 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001618 GL_INVALID_OPERATION,
1619 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1620 return false;
1621 }
1622
1623 if (filter == GL_LINEAR)
1624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001626 return false;
1627 }
1628
Jamie Madill51f40ec2016-06-15 14:06:00 -04001629 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1630 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001631
1632 if (mask & GL_COLOR_BUFFER_BIT)
1633 {
1634 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1635 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1636
1637 if (readColorAttachment && drawColorAttachment)
1638 {
1639 if (!(readColorAttachment->type() == GL_TEXTURE &&
1640 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1641 readColorAttachment->type() != GL_RENDERBUFFER &&
1642 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1643 {
Jamie Madill437fa652016-05-03 15:13:24 -04001644 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001645 return false;
1646 }
1647
Geoff Langa15472a2015-08-11 11:48:03 -04001648 for (size_t drawbufferIdx = 0;
1649 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001650 {
Geoff Langa15472a2015-08-11 11:48:03 -04001651 const FramebufferAttachment *attachment =
1652 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1653 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001654 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001655 if (!(attachment->type() == GL_TEXTURE &&
1656 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1657 attachment->type() != GL_RENDERBUFFER &&
1658 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1659 {
Jamie Madill437fa652016-05-03 15:13:24 -04001660 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001661 return false;
1662 }
1663
1664 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001665 if (!Format::SameSized(attachment->getFormat(),
1666 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001667 {
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001669 return false;
1670 }
1671 }
1672 }
1673
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001674 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001675 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1676 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1677 {
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001679 return false;
1680 }
1681 }
1682 }
1683
1684 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1685 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1686 for (size_t i = 0; i < 2; i++)
1687 {
1688 if (mask & masks[i])
1689 {
1690 const FramebufferAttachment *readBuffer =
1691 readFramebuffer->getAttachment(attachments[i]);
1692 const FramebufferAttachment *drawBuffer =
1693 drawFramebuffer->getAttachment(attachments[i]);
1694
1695 if (readBuffer && drawBuffer)
1696 {
1697 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1698 dstX0, dstY0, dstX1, dstY1))
1699 {
1700 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05001701 context->handleError(Error(GL_INVALID_OPERATION,
1702 "Only whole-buffer depth and stencil blits are "
1703 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001704 return false;
1705 }
1706
1707 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1708 {
Jamie Madill437fa652016-05-03 15:13:24 -04001709 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001710 return false;
1711 }
1712 }
1713 }
1714 }
1715
1716 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1717 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718}
Jamie Madillc29968b2016-01-20 11:17:23 -05001719
1720bool ValidateClear(ValidationContext *context, GLbitfield mask)
1721{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001722 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001723 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 return false;
1727 }
1728
1729 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001732 return false;
1733 }
1734
Geoff Lang76e65652017-03-27 14:58:02 -04001735 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
1736 {
1737 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1738 GL_SIGNED_NORMALIZED};
1739
1740 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
1741 drawBufferIdx++)
1742 {
1743 if (!ValidateWebGLFramebufferAttachmentClearType(
1744 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
1745 {
1746 return false;
1747 }
1748 }
1749 }
1750
Jamie Madillc29968b2016-01-20 11:17:23 -05001751 return true;
1752}
1753
1754bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1755{
1756 if (!context->getExtensions().drawBuffers)
1757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001759 return false;
1760 }
1761
1762 return ValidateDrawBuffersBase(context, n, bufs);
1763}
1764
Jamie Madill73a84962016-02-12 09:27:23 -05001765bool ValidateTexImage2D(Context *context,
1766 GLenum target,
1767 GLint level,
1768 GLint internalformat,
1769 GLsizei width,
1770 GLsizei height,
1771 GLint border,
1772 GLenum format,
1773 GLenum type,
1774 const GLvoid *pixels)
1775{
Martin Radev1be913c2016-07-11 17:59:16 +03001776 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001777 {
1778 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001779 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001780 }
1781
Martin Radev1be913c2016-07-11 17:59:16 +03001782 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001783 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001784 0, 0, width, height, 1, border, format, type, -1,
1785 pixels);
1786}
1787
1788bool ValidateTexImage2DRobust(Context *context,
1789 GLenum target,
1790 GLint level,
1791 GLint internalformat,
1792 GLsizei width,
1793 GLsizei height,
1794 GLint border,
1795 GLenum format,
1796 GLenum type,
1797 GLsizei bufSize,
1798 const GLvoid *pixels)
1799{
1800 if (!ValidateRobustEntryPoint(context, bufSize))
1801 {
1802 return false;
1803 }
1804
1805 if (context->getClientMajorVersion() < 3)
1806 {
1807 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1808 0, 0, width, height, border, format, type, bufSize,
1809 pixels);
1810 }
1811
1812 ASSERT(context->getClientMajorVersion() >= 3);
1813 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1814 0, 0, width, height, 1, border, format, type, bufSize,
1815 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001816}
1817
1818bool ValidateTexSubImage2D(Context *context,
1819 GLenum target,
1820 GLint level,
1821 GLint xoffset,
1822 GLint yoffset,
1823 GLsizei width,
1824 GLsizei height,
1825 GLenum format,
1826 GLenum type,
1827 const GLvoid *pixels)
1828{
1829
Martin Radev1be913c2016-07-11 17:59:16 +03001830 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001831 {
1832 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001833 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001834 }
1835
Martin Radev1be913c2016-07-11 17:59:16 +03001836 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001837 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001838 yoffset, 0, width, height, 1, 0, format, type, -1,
1839 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001840}
1841
Geoff Langc52f6f12016-10-14 10:18:00 -04001842bool ValidateTexSubImage2DRobustANGLE(Context *context,
1843 GLenum target,
1844 GLint level,
1845 GLint xoffset,
1846 GLint yoffset,
1847 GLsizei width,
1848 GLsizei height,
1849 GLenum format,
1850 GLenum type,
1851 GLsizei bufSize,
1852 const GLvoid *pixels)
1853{
1854 if (!ValidateRobustEntryPoint(context, bufSize))
1855 {
1856 return false;
1857 }
1858
1859 if (context->getClientMajorVersion() < 3)
1860 {
1861 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1862 yoffset, width, height, 0, format, type, bufSize,
1863 pixels);
1864 }
1865
1866 ASSERT(context->getClientMajorVersion() >= 3);
1867 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1868 yoffset, 0, width, height, 1, 0, format, type, bufSize,
1869 pixels);
1870}
1871
Jamie Madill73a84962016-02-12 09:27:23 -05001872bool ValidateCompressedTexImage2D(Context *context,
1873 GLenum target,
1874 GLint level,
1875 GLenum internalformat,
1876 GLsizei width,
1877 GLsizei height,
1878 GLint border,
1879 GLsizei imageSize,
1880 const GLvoid *data)
1881{
Martin Radev1be913c2016-07-11 17:59:16 +03001882 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001883 {
1884 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001885 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001886 {
1887 return false;
1888 }
1889 }
1890 else
1891 {
Martin Radev1be913c2016-07-11 17:59:16 +03001892 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001893 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001894 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001895 data))
1896 {
1897 return false;
1898 }
1899 }
1900
Geoff Langca271392017-04-05 12:30:00 -04001901 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001902 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001903 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001904 if (blockSizeOrErr.isError())
1905 {
1906 context->handleError(blockSizeOrErr.getError());
1907 return false;
1908 }
1909
1910 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001913 return false;
1914 }
1915
1916 return true;
1917}
1918
Corentin Wallezb2931602017-04-11 15:58:57 -04001919bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
1920 GLenum target,
1921 GLint level,
1922 GLenum internalformat,
1923 GLsizei width,
1924 GLsizei height,
1925 GLint border,
1926 GLsizei imageSize,
1927 GLsizei dataSize,
1928 const GLvoid *data)
1929{
1930 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1931 {
1932 return false;
1933 }
1934
1935 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
1936 border, imageSize, data);
1937}
1938bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
1939 GLenum target,
1940 GLint level,
1941 GLint xoffset,
1942 GLint yoffset,
1943 GLsizei width,
1944 GLsizei height,
1945 GLenum format,
1946 GLsizei imageSize,
1947 GLsizei dataSize,
1948 const GLvoid *data)
1949{
1950 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1951 {
1952 return false;
1953 }
1954
1955 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
1956 format, imageSize, data);
1957}
1958
Jamie Madill73a84962016-02-12 09:27:23 -05001959bool ValidateCompressedTexSubImage2D(Context *context,
1960 GLenum target,
1961 GLint level,
1962 GLint xoffset,
1963 GLint yoffset,
1964 GLsizei width,
1965 GLsizei height,
1966 GLenum format,
1967 GLsizei imageSize,
1968 const GLvoid *data)
1969{
Martin Radev1be913c2016-07-11 17:59:16 +03001970 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001971 {
1972 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001973 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05001974 {
1975 return false;
1976 }
1977 }
1978 else
1979 {
Martin Radev1be913c2016-07-11 17:59:16 +03001980 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001981 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04001982 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05001983 data))
1984 {
1985 return false;
1986 }
1987 }
1988
Geoff Langca271392017-04-05 12:30:00 -04001989 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04001990 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001991 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001992 if (blockSizeOrErr.isError())
1993 {
1994 context->handleError(blockSizeOrErr.getError());
1995 return false;
1996 }
1997
1998 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002001 return false;
2002 }
2003
2004 return true;
2005}
2006
Olli Etuaho4f667482016-03-30 15:56:35 +03002007bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2008{
Geoff Lang496c02d2016-10-20 11:38:11 -07002009 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002010}
2011
2012bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2013{
2014 if (!context->getExtensions().mapBuffer)
2015 {
Jamie Madill437fa652016-05-03 15:13:24 -04002016 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002017 return false;
2018 }
2019
2020 if (!ValidBufferTarget(context, target))
2021 {
Jamie Madill437fa652016-05-03 15:13:24 -04002022 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002023 return false;
2024 }
2025
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002026 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002027
2028 if (buffer == nullptr)
2029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002031 return false;
2032 }
2033
2034 if (access != GL_WRITE_ONLY_OES)
2035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002037 return false;
2038 }
2039
2040 if (buffer->isMapped())
2041 {
Jamie Madill437fa652016-05-03 15:13:24 -04002042 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002043 return false;
2044 }
2045
2046 return true;
2047}
2048
2049bool ValidateUnmapBufferOES(Context *context, GLenum target)
2050{
2051 if (!context->getExtensions().mapBuffer)
2052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002054 return false;
2055 }
2056
2057 return ValidateUnmapBufferBase(context, target);
2058}
2059
2060bool ValidateMapBufferRangeEXT(Context *context,
2061 GLenum target,
2062 GLintptr offset,
2063 GLsizeiptr length,
2064 GLbitfield access)
2065{
2066 if (!context->getExtensions().mapBufferRange)
2067 {
Jamie Madill437fa652016-05-03 15:13:24 -04002068 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002069 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2070 return false;
2071 }
2072
2073 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2074}
2075
2076bool ValidateFlushMappedBufferRangeEXT(Context *context,
2077 GLenum target,
2078 GLintptr offset,
2079 GLsizeiptr length)
2080{
2081 if (!context->getExtensions().mapBufferRange)
2082 {
Jamie Madill437fa652016-05-03 15:13:24 -04002083 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002084 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2085 return false;
2086 }
2087
2088 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2089}
2090
Ian Ewell54f87462016-03-10 13:47:21 -05002091bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2092{
2093 Texture *textureObject = context->getTexture(texture);
2094 if (textureObject && textureObject->getTarget() != target && texture != 0)
2095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002097 return false;
2098 }
2099
Geoff Langf41a7152016-09-19 15:11:17 -04002100 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2101 !context->isTextureGenerated(texture))
2102 {
2103 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2104 return false;
2105 }
2106
Ian Ewell54f87462016-03-10 13:47:21 -05002107 switch (target)
2108 {
2109 case GL_TEXTURE_2D:
2110 case GL_TEXTURE_CUBE_MAP:
2111 break;
2112
2113 case GL_TEXTURE_3D:
2114 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002115 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002116 {
Jamie Madill437fa652016-05-03 15:13:24 -04002117 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002118 return false;
2119 }
2120 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002121
2122 case GL_TEXTURE_2D_MULTISAMPLE:
2123 if (context->getClientVersion() < Version(3, 1))
2124 {
2125 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2126 return false;
2127 }
Geoff Lang3b573612016-10-31 14:08:10 -04002128 break;
2129
Ian Ewell54f87462016-03-10 13:47:21 -05002130 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002131 if (!context->getExtensions().eglImageExternal &&
2132 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002135 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2136 return false;
2137 }
2138 break;
2139 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002140 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002141 return false;
2142 }
2143
2144 return true;
2145}
2146
Geoff Langd8605522016-04-13 10:19:12 -04002147bool ValidateBindUniformLocationCHROMIUM(Context *context,
2148 GLuint program,
2149 GLint location,
2150 const GLchar *name)
2151{
2152 if (!context->getExtensions().bindUniformLocation)
2153 {
Jamie Madill437fa652016-05-03 15:13:24 -04002154 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002155 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2156 return false;
2157 }
2158
2159 Program *programObject = GetValidProgram(context, program);
2160 if (!programObject)
2161 {
2162 return false;
2163 }
2164
2165 if (location < 0)
2166 {
Jamie Madill437fa652016-05-03 15:13:24 -04002167 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002168 return false;
2169 }
2170
2171 const Caps &caps = context->getCaps();
2172 if (static_cast<size_t>(location) >=
2173 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002176 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2177 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2178 return false;
2179 }
2180
2181 if (strncmp(name, "gl_", 3) == 0)
2182 {
Jamie Madill437fa652016-05-03 15:13:24 -04002183 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002184 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2185 return false;
2186 }
2187
2188 return true;
2189}
2190
Jamie Madille2e406c2016-06-02 13:04:10 -04002191bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002192{
2193 if (!context->getExtensions().framebufferMixedSamples)
2194 {
2195 context->handleError(
2196 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2197 return false;
2198 }
2199 switch (components)
2200 {
2201 case GL_RGB:
2202 case GL_RGBA:
2203 case GL_ALPHA:
2204 case GL_NONE:
2205 break;
2206 default:
2207 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002208 Error(GL_INVALID_ENUM,
2209 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002210 return false;
2211 }
2212
2213 return true;
2214}
2215
Sami Väisänene45e53b2016-05-25 10:36:04 +03002216// CHROMIUM_path_rendering
2217
2218bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2219{
2220 if (!context->getExtensions().pathRendering)
2221 {
2222 context->handleError(
2223 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2224 return false;
2225 }
2226 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2227 {
2228 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2229 return false;
2230 }
2231 if (matrix == nullptr)
2232 {
2233 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2234 return false;
2235 }
2236 return true;
2237}
2238
2239bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2240{
2241 if (!context->getExtensions().pathRendering)
2242 {
2243 context->handleError(
2244 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2245 return false;
2246 }
2247 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2248 {
2249 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2250 return false;
2251 }
2252 return true;
2253}
2254
2255bool ValidateGenPaths(Context *context, GLsizei range)
2256{
2257 if (!context->getExtensions().pathRendering)
2258 {
2259 context->handleError(
2260 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2261 return false;
2262 }
2263
2264 // range = 0 is undefined in NV_path_rendering.
2265 // we add stricter semantic check here and require a non zero positive range.
2266 if (range <= 0)
2267 {
2268 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2269 return false;
2270 }
2271
2272 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2273 {
2274 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2275 return false;
2276 }
2277
2278 return true;
2279}
2280
2281bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2282{
2283 if (!context->getExtensions().pathRendering)
2284 {
2285 context->handleError(
2286 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2287 return false;
2288 }
2289
2290 // range = 0 is undefined in NV_path_rendering.
2291 // we add stricter semantic check here and require a non zero positive range.
2292 if (range <= 0)
2293 {
2294 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2295 return false;
2296 }
2297
2298 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2299 checkedRange += range;
2300
2301 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2302 {
2303 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2304 return false;
2305 }
2306 return true;
2307}
2308
2309bool ValidatePathCommands(Context *context,
2310 GLuint path,
2311 GLsizei numCommands,
2312 const GLubyte *commands,
2313 GLsizei numCoords,
2314 GLenum coordType,
2315 const void *coords)
2316{
2317 if (!context->getExtensions().pathRendering)
2318 {
2319 context->handleError(
2320 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2321 return false;
2322 }
2323 if (!context->hasPath(path))
2324 {
2325 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2326 return false;
2327 }
2328
2329 if (numCommands < 0)
2330 {
2331 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2332 return false;
2333 }
2334 else if (numCommands > 0)
2335 {
2336 if (!commands)
2337 {
2338 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2339 return false;
2340 }
2341 }
2342
2343 if (numCoords < 0)
2344 {
2345 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2346 return false;
2347 }
2348 else if (numCoords > 0)
2349 {
2350 if (!coords)
2351 {
2352 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2353 return false;
2354 }
2355 }
2356
2357 std::uint32_t coordTypeSize = 0;
2358 switch (coordType)
2359 {
2360 case GL_BYTE:
2361 coordTypeSize = sizeof(GLbyte);
2362 break;
2363
2364 case GL_UNSIGNED_BYTE:
2365 coordTypeSize = sizeof(GLubyte);
2366 break;
2367
2368 case GL_SHORT:
2369 coordTypeSize = sizeof(GLshort);
2370 break;
2371
2372 case GL_UNSIGNED_SHORT:
2373 coordTypeSize = sizeof(GLushort);
2374 break;
2375
2376 case GL_FLOAT:
2377 coordTypeSize = sizeof(GLfloat);
2378 break;
2379
2380 default:
2381 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2382 return false;
2383 }
2384
2385 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2386 checkedSize += (coordTypeSize * numCoords);
2387 if (!checkedSize.IsValid())
2388 {
2389 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2390 return false;
2391 }
2392
2393 // early return skips command data validation when it doesn't exist.
2394 if (!commands)
2395 return true;
2396
2397 GLsizei expectedNumCoords = 0;
2398 for (GLsizei i = 0; i < numCommands; ++i)
2399 {
2400 switch (commands[i])
2401 {
2402 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2403 break;
2404 case GL_MOVE_TO_CHROMIUM:
2405 case GL_LINE_TO_CHROMIUM:
2406 expectedNumCoords += 2;
2407 break;
2408 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2409 expectedNumCoords += 4;
2410 break;
2411 case GL_CUBIC_CURVE_TO_CHROMIUM:
2412 expectedNumCoords += 6;
2413 break;
2414 case GL_CONIC_CURVE_TO_CHROMIUM:
2415 expectedNumCoords += 5;
2416 break;
2417 default:
2418 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2419 return false;
2420 }
2421 }
2422 if (expectedNumCoords != numCoords)
2423 {
2424 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2425 return false;
2426 }
2427
2428 return true;
2429}
2430
2431bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2432{
2433 if (!context->getExtensions().pathRendering)
2434 {
2435 context->handleError(
2436 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2437 return false;
2438 }
2439 if (!context->hasPath(path))
2440 {
2441 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2442 return false;
2443 }
2444
2445 switch (pname)
2446 {
2447 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2448 if (value < 0.0f)
2449 {
2450 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2451 return false;
2452 }
2453 break;
2454 case GL_PATH_END_CAPS_CHROMIUM:
2455 switch (static_cast<GLenum>(value))
2456 {
2457 case GL_FLAT_CHROMIUM:
2458 case GL_SQUARE_CHROMIUM:
2459 case GL_ROUND_CHROMIUM:
2460 break;
2461 default:
2462 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2463 return false;
2464 }
2465 break;
2466 case GL_PATH_JOIN_STYLE_CHROMIUM:
2467 switch (static_cast<GLenum>(value))
2468 {
2469 case GL_MITER_REVERT_CHROMIUM:
2470 case GL_BEVEL_CHROMIUM:
2471 case GL_ROUND_CHROMIUM:
2472 break;
2473 default:
2474 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2475 return false;
2476 }
2477 case GL_PATH_MITER_LIMIT_CHROMIUM:
2478 if (value < 0.0f)
2479 {
2480 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2481 return false;
2482 }
2483 break;
2484
2485 case GL_PATH_STROKE_BOUND_CHROMIUM:
2486 // no errors, only clamping.
2487 break;
2488
2489 default:
2490 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2491 return false;
2492 }
2493 return true;
2494}
2495
2496bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2497{
2498 if (!context->getExtensions().pathRendering)
2499 {
2500 context->handleError(
2501 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2502 return false;
2503 }
2504
2505 if (!context->hasPath(path))
2506 {
2507 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2508 return false;
2509 }
2510 if (!value)
2511 {
2512 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2513 return false;
2514 }
2515
2516 switch (pname)
2517 {
2518 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2519 case GL_PATH_END_CAPS_CHROMIUM:
2520 case GL_PATH_JOIN_STYLE_CHROMIUM:
2521 case GL_PATH_MITER_LIMIT_CHROMIUM:
2522 case GL_PATH_STROKE_BOUND_CHROMIUM:
2523 break;
2524
2525 default:
2526 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2527 return false;
2528 }
2529
2530 return true;
2531}
2532
2533bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2534{
2535 if (!context->getExtensions().pathRendering)
2536 {
2537 context->handleError(
2538 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2539 return false;
2540 }
2541
2542 switch (func)
2543 {
2544 case GL_NEVER:
2545 case GL_ALWAYS:
2546 case GL_LESS:
2547 case GL_LEQUAL:
2548 case GL_EQUAL:
2549 case GL_GEQUAL:
2550 case GL_GREATER:
2551 case GL_NOTEQUAL:
2552 break;
2553 default:
2554 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2555 return false;
2556 }
2557
2558 return true;
2559}
2560
2561// Note that the spec specifies that for the path drawing commands
2562// if the path object is not an existing path object the command
2563// does nothing and no error is generated.
2564// However if the path object exists but has not been specified any
2565// commands then an error is generated.
2566
2567bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2568{
2569 if (!context->getExtensions().pathRendering)
2570 {
2571 context->handleError(
2572 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2573 return false;
2574 }
2575 if (context->hasPath(path) && !context->hasPathData(path))
2576 {
2577 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2578 return false;
2579 }
2580
2581 switch (fillMode)
2582 {
2583 case GL_COUNT_UP_CHROMIUM:
2584 case GL_COUNT_DOWN_CHROMIUM:
2585 break;
2586 default:
2587 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2588 return false;
2589 }
2590
2591 if (!isPow2(mask + 1))
2592 {
2593 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2594 return false;
2595 }
2596
2597 return true;
2598}
2599
2600bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2601{
2602 if (!context->getExtensions().pathRendering)
2603 {
2604 context->handleError(
2605 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2606 return false;
2607 }
2608 if (context->hasPath(path) && !context->hasPathData(path))
2609 {
2610 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2611 return false;
2612 }
2613
2614 return true;
2615}
2616
2617bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2618{
2619 if (!context->getExtensions().pathRendering)
2620 {
2621 context->handleError(
2622 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2623 return false;
2624 }
2625 if (context->hasPath(path) && !context->hasPathData(path))
2626 {
2627 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2628 return false;
2629 }
2630
2631 switch (coverMode)
2632 {
2633 case GL_CONVEX_HULL_CHROMIUM:
2634 case GL_BOUNDING_BOX_CHROMIUM:
2635 break;
2636 default:
2637 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2638 return false;
2639 }
2640 return true;
2641}
2642
2643bool ValidateStencilThenCoverFillPath(Context *context,
2644 GLuint path,
2645 GLenum fillMode,
2646 GLuint mask,
2647 GLenum coverMode)
2648{
2649 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2650 ValidateCoverPath(context, path, coverMode);
2651}
2652
2653bool ValidateStencilThenCoverStrokePath(Context *context,
2654 GLuint path,
2655 GLint reference,
2656 GLuint mask,
2657 GLenum coverMode)
2658{
2659 return ValidateStencilStrokePath(context, path, reference, mask) &&
2660 ValidateCoverPath(context, path, coverMode);
2661}
2662
2663bool ValidateIsPath(Context *context)
2664{
2665 if (!context->getExtensions().pathRendering)
2666 {
2667 context->handleError(
2668 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2669 return false;
2670 }
2671 return true;
2672}
2673
Sami Väisänend59ca052016-06-21 16:10:00 +03002674bool ValidateCoverFillPathInstanced(Context *context,
2675 GLsizei numPaths,
2676 GLenum pathNameType,
2677 const void *paths,
2678 GLuint pathBase,
2679 GLenum coverMode,
2680 GLenum transformType,
2681 const GLfloat *transformValues)
2682{
2683 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2684 transformType, transformValues))
2685 return false;
2686
2687 switch (coverMode)
2688 {
2689 case GL_CONVEX_HULL_CHROMIUM:
2690 case GL_BOUNDING_BOX_CHROMIUM:
2691 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2692 break;
2693 default:
2694 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2695 return false;
2696 }
2697
2698 return true;
2699}
2700
2701bool ValidateCoverStrokePathInstanced(Context *context,
2702 GLsizei numPaths,
2703 GLenum pathNameType,
2704 const void *paths,
2705 GLuint pathBase,
2706 GLenum coverMode,
2707 GLenum transformType,
2708 const GLfloat *transformValues)
2709{
2710 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2711 transformType, transformValues))
2712 return false;
2713
2714 switch (coverMode)
2715 {
2716 case GL_CONVEX_HULL_CHROMIUM:
2717 case GL_BOUNDING_BOX_CHROMIUM:
2718 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2719 break;
2720 default:
2721 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2722 return false;
2723 }
2724
2725 return true;
2726}
2727
2728bool ValidateStencilFillPathInstanced(Context *context,
2729 GLsizei numPaths,
2730 GLenum pathNameType,
2731 const void *paths,
2732 GLuint pathBase,
2733 GLenum fillMode,
2734 GLuint mask,
2735 GLenum transformType,
2736 const GLfloat *transformValues)
2737{
2738
2739 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2740 transformType, transformValues))
2741 return false;
2742
2743 switch (fillMode)
2744 {
2745 case GL_COUNT_UP_CHROMIUM:
2746 case GL_COUNT_DOWN_CHROMIUM:
2747 break;
2748 default:
2749 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2750 return false;
2751 }
2752 if (!isPow2(mask + 1))
2753 {
2754 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2755 return false;
2756 }
2757 return true;
2758}
2759
2760bool ValidateStencilStrokePathInstanced(Context *context,
2761 GLsizei numPaths,
2762 GLenum pathNameType,
2763 const void *paths,
2764 GLuint pathBase,
2765 GLint reference,
2766 GLuint mask,
2767 GLenum transformType,
2768 const GLfloat *transformValues)
2769{
2770 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2771 transformType, transformValues))
2772 return false;
2773
2774 // no more validation here.
2775
2776 return true;
2777}
2778
2779bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2780 GLsizei numPaths,
2781 GLenum pathNameType,
2782 const void *paths,
2783 GLuint pathBase,
2784 GLenum fillMode,
2785 GLuint mask,
2786 GLenum coverMode,
2787 GLenum transformType,
2788 const GLfloat *transformValues)
2789{
2790 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2791 transformType, transformValues))
2792 return false;
2793
2794 switch (coverMode)
2795 {
2796 case GL_CONVEX_HULL_CHROMIUM:
2797 case GL_BOUNDING_BOX_CHROMIUM:
2798 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2799 break;
2800 default:
2801 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2802 return false;
2803 }
2804
2805 switch (fillMode)
2806 {
2807 case GL_COUNT_UP_CHROMIUM:
2808 case GL_COUNT_DOWN_CHROMIUM:
2809 break;
2810 default:
2811 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2812 return false;
2813 }
2814 if (!isPow2(mask + 1))
2815 {
2816 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2817 return false;
2818 }
2819
2820 return true;
2821}
2822
2823bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2824 GLsizei numPaths,
2825 GLenum pathNameType,
2826 const void *paths,
2827 GLuint pathBase,
2828 GLint reference,
2829 GLuint mask,
2830 GLenum coverMode,
2831 GLenum transformType,
2832 const GLfloat *transformValues)
2833{
2834 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2835 transformType, transformValues))
2836 return false;
2837
2838 switch (coverMode)
2839 {
2840 case GL_CONVEX_HULL_CHROMIUM:
2841 case GL_BOUNDING_BOX_CHROMIUM:
2842 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2843 break;
2844 default:
2845 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2846 return false;
2847 }
2848
2849 return true;
2850}
2851
Sami Väisänen46eaa942016-06-29 10:26:37 +03002852bool ValidateBindFragmentInputLocation(Context *context,
2853 GLuint program,
2854 GLint location,
2855 const GLchar *name)
2856{
2857 if (!context->getExtensions().pathRendering)
2858 {
2859 context->handleError(
2860 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2861 return false;
2862 }
2863
2864 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2865 if (location >= MaxLocation)
2866 {
2867 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2868 return false;
2869 }
2870
2871 const auto *programObject = context->getProgram(program);
2872 if (!programObject)
2873 {
2874 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2875 return false;
2876 }
2877
2878 if (!name)
2879 {
2880 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2881 return false;
2882 }
2883
2884 if (angle::BeginsWith(name, "gl_"))
2885 {
2886 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2887 return false;
2888 }
2889
2890 return true;
2891}
2892
2893bool ValidateProgramPathFragmentInputGen(Context *context,
2894 GLuint program,
2895 GLint location,
2896 GLenum genMode,
2897 GLint components,
2898 const GLfloat *coeffs)
2899{
2900 if (!context->getExtensions().pathRendering)
2901 {
2902 context->handleError(
2903 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2904 return false;
2905 }
2906
2907 const auto *programObject = context->getProgram(program);
2908 if (!programObject || programObject->isFlaggedForDeletion())
2909 {
2910 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2911 return false;
2912 }
2913
2914 if (!programObject->isLinked())
2915 {
2916 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2917 return false;
2918 }
2919
2920 switch (genMode)
2921 {
2922 case GL_NONE:
2923 if (components != 0)
2924 {
2925 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2926 return false;
2927 }
2928 break;
2929
2930 case GL_OBJECT_LINEAR_CHROMIUM:
2931 case GL_EYE_LINEAR_CHROMIUM:
2932 case GL_CONSTANT_CHROMIUM:
2933 if (components < 1 || components > 4)
2934 {
2935 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2936 return false;
2937 }
2938 if (!coeffs)
2939 {
2940 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2941 return false;
2942 }
2943 break;
2944
2945 default:
2946 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2947 return false;
2948 }
2949
2950 // If the location is -1 then the command is silently ignored
2951 // and no further validation is needed.
2952 if (location == -1)
2953 return true;
2954
2955 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2956
2957 if (!binding.valid)
2958 {
2959 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
2960 return false;
2961 }
2962
2963 if (binding.type != GL_NONE)
2964 {
2965 GLint expectedComponents = 0;
2966 switch (binding.type)
2967 {
2968 case GL_FLOAT:
2969 expectedComponents = 1;
2970 break;
2971 case GL_FLOAT_VEC2:
2972 expectedComponents = 2;
2973 break;
2974 case GL_FLOAT_VEC3:
2975 expectedComponents = 3;
2976 break;
2977 case GL_FLOAT_VEC4:
2978 expectedComponents = 4;
2979 break;
2980 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08002981 context->handleError(
2982 Error(GL_INVALID_OPERATION,
2983 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03002984 return false;
2985 }
2986 if (expectedComponents != components && genMode != GL_NONE)
2987 {
2988 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
2989 return false;
2990 }
2991 }
2992 return true;
2993}
2994
Geoff Lang97073d12016-04-20 10:42:34 -07002995bool ValidateCopyTextureCHROMIUM(Context *context,
2996 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04002997 GLint sourceLevel,
2998 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07002999 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003000 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003001 GLint internalFormat,
3002 GLenum destType,
3003 GLboolean unpackFlipY,
3004 GLboolean unpackPremultiplyAlpha,
3005 GLboolean unpackUnmultiplyAlpha)
3006{
3007 if (!context->getExtensions().copyTexture)
3008 {
3009 context->handleError(
3010 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3011 return false;
3012 }
3013
3014 const gl::Texture *source = context->getTexture(sourceId);
3015 if (source == nullptr)
3016 {
3017 context->handleError(
3018 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3019 return false;
3020 }
3021
3022 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3023 {
3024 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3025 return false;
3026 }
3027
3028 GLenum sourceTarget = source->getTarget();
3029 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3030 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3031 {
3032 context->handleError(
3033 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3034 return false;
3035 }
3036
Geoff Langca271392017-04-05 12:30:00 -04003037 const gl::InternalFormat &sourceFormat = *source->getFormat(sourceTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003038 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3039 {
3040 context->handleError(
3041 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3042 return false;
3043 }
3044
3045 const gl::Texture *dest = context->getTexture(destId);
3046 if (dest == nullptr)
3047 {
3048 context->handleError(
3049 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3050 return false;
3051 }
3052
3053 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3054 {
3055 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3056 return false;
3057 }
3058
3059 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3060 {
3061 context->handleError(
3062 Error(GL_INVALID_OPERATION,
3063 "Destination internal format and type combination is not valid."));
3064 return false;
3065 }
3066
3067 if (dest->getImmutableFormat())
3068 {
3069 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3070 return false;
3071 }
3072
3073 return true;
3074}
3075
3076bool ValidateCopySubTextureCHROMIUM(Context *context,
3077 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003078 GLint sourceLevel,
3079 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003080 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003081 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003082 GLint xoffset,
3083 GLint yoffset,
3084 GLint x,
3085 GLint y,
3086 GLsizei width,
3087 GLsizei height,
3088 GLboolean unpackFlipY,
3089 GLboolean unpackPremultiplyAlpha,
3090 GLboolean unpackUnmultiplyAlpha)
3091{
3092 if (!context->getExtensions().copyTexture)
3093 {
3094 context->handleError(
3095 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3096 return false;
3097 }
3098
3099 const gl::Texture *source = context->getTexture(sourceId);
3100 if (source == nullptr)
3101 {
3102 context->handleError(
3103 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3104 return false;
3105 }
3106
3107 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3108 {
3109 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3110 return false;
3111 }
3112
3113 GLenum sourceTarget = source->getTarget();
3114 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3115 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3116 {
3117 context->handleError(
3118 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3119 return false;
3120 }
3121
3122 if (x < 0 || y < 0)
3123 {
3124 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3125 return false;
3126 }
3127
3128 if (width < 0 || height < 0)
3129 {
3130 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3131 return false;
3132 }
3133
3134 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3135 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3136 {
3137 context->handleError(
3138 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3139 return false;
3140 }
3141
3142 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
Geoff Langca271392017-04-05 12:30:00 -04003143 if (!IsValidCopyTextureFormat(context, sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003144 {
3145 context->handleError(
3146 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3147 return false;
3148 }
3149
3150 const gl::Texture *dest = context->getTexture(destId);
3151 if (dest == nullptr)
3152 {
3153 context->handleError(
3154 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3155 return false;
3156 }
3157
3158 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3159 {
3160 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3161 return false;
3162 }
3163
Geoff Lang97073d12016-04-20 10:42:34 -07003164 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3165 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3166 {
3167 context->handleError(
3168 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3169 return false;
3170 }
3171
Geoff Langca271392017-04-05 12:30:00 -04003172 const gl::InternalFormat &destFormat = *dest->getFormat(destTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003173 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3174 {
3175 context->handleError(
3176 Error(GL_INVALID_OPERATION,
3177 "Destination internal format and type combination is not valid."));
3178 return false;
3179 }
3180
3181 if (xoffset < 0 || yoffset < 0)
3182 {
3183 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3184 return false;
3185 }
3186
3187 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3188 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3189 {
3190 context->handleError(
3191 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3192 return false;
3193 }
3194
3195 return true;
3196}
3197
Geoff Lang47110bf2016-04-20 11:13:22 -07003198bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3199{
3200 if (!context->getExtensions().copyCompressedTexture)
3201 {
3202 context->handleError(Error(GL_INVALID_OPERATION,
3203 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3204 return false;
3205 }
3206
3207 const gl::Texture *source = context->getTexture(sourceId);
3208 if (source == nullptr)
3209 {
3210 context->handleError(
3211 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3212 return false;
3213 }
3214
3215 if (source->getTarget() != GL_TEXTURE_2D)
3216 {
3217 context->handleError(
3218 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3219 return false;
3220 }
3221
3222 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3223 {
3224 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3225 return false;
3226 }
3227
3228 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3229 if (!sourceFormat.info->compressed)
3230 {
3231 context->handleError(
3232 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3233 return false;
3234 }
3235
3236 const gl::Texture *dest = context->getTexture(destId);
3237 if (dest == nullptr)
3238 {
3239 context->handleError(
3240 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3241 return false;
3242 }
3243
3244 if (dest->getTarget() != GL_TEXTURE_2D)
3245 {
3246 context->handleError(
3247 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3248 return false;
3249 }
3250
3251 if (dest->getImmutableFormat())
3252 {
3253 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3254 return false;
3255 }
3256
3257 return true;
3258}
3259
Martin Radev4c4c8e72016-08-04 12:25:34 +03003260bool ValidateCreateShader(Context *context, GLenum type)
3261{
3262 switch (type)
3263 {
3264 case GL_VERTEX_SHADER:
3265 case GL_FRAGMENT_SHADER:
3266 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003267
Martin Radev4c4c8e72016-08-04 12:25:34 +03003268 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003269 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003270 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003271 context->handleError(
3272 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3273 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003274 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003275 break;
3276
Martin Radev4c4c8e72016-08-04 12:25:34 +03003277 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003278 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003279 return false;
3280 }
Jamie Madill29639852016-09-02 15:00:09 -04003281
3282 return true;
3283}
3284
3285bool ValidateBufferData(ValidationContext *context,
3286 GLenum target,
3287 GLsizeiptr size,
3288 const GLvoid *data,
3289 GLenum usage)
3290{
3291 if (size < 0)
3292 {
3293 context->handleError(Error(GL_INVALID_VALUE));
3294 return false;
3295 }
3296
3297 switch (usage)
3298 {
3299 case GL_STREAM_DRAW:
3300 case GL_STATIC_DRAW:
3301 case GL_DYNAMIC_DRAW:
3302 break;
3303
3304 case GL_STREAM_READ:
3305 case GL_STREAM_COPY:
3306 case GL_STATIC_READ:
3307 case GL_STATIC_COPY:
3308 case GL_DYNAMIC_READ:
3309 case GL_DYNAMIC_COPY:
3310 if (context->getClientMajorVersion() < 3)
3311 {
3312 context->handleError(Error(GL_INVALID_ENUM));
3313 return false;
3314 }
3315 break;
3316
3317 default:
3318 context->handleError(Error(GL_INVALID_ENUM));
3319 return false;
3320 }
3321
3322 if (!ValidBufferTarget(context, target))
3323 {
3324 context->handleError(Error(GL_INVALID_ENUM));
3325 return false;
3326 }
3327
3328 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3329
3330 if (!buffer)
3331 {
3332 context->handleError(Error(GL_INVALID_OPERATION));
3333 return false;
3334 }
3335
3336 return true;
3337}
3338
3339bool ValidateBufferSubData(ValidationContext *context,
3340 GLenum target,
3341 GLintptr offset,
3342 GLsizeiptr size,
3343 const GLvoid *data)
3344{
3345 if (size < 0 || offset < 0)
3346 {
3347 context->handleError(Error(GL_INVALID_VALUE));
3348 return false;
3349 }
3350
3351 if (!ValidBufferTarget(context, target))
3352 {
3353 context->handleError(Error(GL_INVALID_ENUM));
3354 return false;
3355 }
3356
3357 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3358
3359 if (!buffer)
3360 {
3361 context->handleError(Error(GL_INVALID_OPERATION));
3362 return false;
3363 }
3364
3365 if (buffer->isMapped())
3366 {
3367 context->handleError(Error(GL_INVALID_OPERATION));
3368 return false;
3369 }
3370
3371 // Check for possible overflow of size + offset
3372 angle::CheckedNumeric<size_t> checkedSize(size);
3373 checkedSize += offset;
3374 if (!checkedSize.IsValid())
3375 {
3376 context->handleError(Error(GL_OUT_OF_MEMORY));
3377 return false;
3378 }
3379
3380 if (size + offset > buffer->getSize())
3381 {
3382 context->handleError(Error(GL_INVALID_VALUE));
3383 return false;
3384 }
3385
Martin Radev4c4c8e72016-08-04 12:25:34 +03003386 return true;
3387}
3388
Geoff Langc339c4e2016-11-29 10:37:36 -05003389bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003390{
Geoff Langc339c4e2016-11-29 10:37:36 -05003391 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003392 {
3393 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003394 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003395 return false;
3396 }
3397
3398 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3399 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003400 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003401 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003402 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003403 return false;
3404 }
3405
3406 return true;
3407}
3408
Jamie Madillef300b12016-10-07 15:12:09 -04003409bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3410{
3411 if (texture < GL_TEXTURE0 ||
3412 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3413 {
3414 context->handleError(Error(GL_INVALID_ENUM));
3415 return false;
3416 }
3417
3418 return true;
3419}
3420
3421bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3422{
3423 Program *programObject = GetValidProgram(context, program);
3424 if (!programObject)
3425 {
3426 return false;
3427 }
3428
3429 Shader *shaderObject = GetValidShader(context, shader);
3430 if (!shaderObject)
3431 {
3432 return false;
3433 }
3434
3435 switch (shaderObject->getType())
3436 {
3437 case GL_VERTEX_SHADER:
3438 {
3439 if (programObject->getAttachedVertexShader())
3440 {
3441 context->handleError(Error(GL_INVALID_OPERATION));
3442 return false;
3443 }
3444 break;
3445 }
3446 case GL_FRAGMENT_SHADER:
3447 {
3448 if (programObject->getAttachedFragmentShader())
3449 {
3450 context->handleError(Error(GL_INVALID_OPERATION));
3451 return false;
3452 }
3453 break;
3454 }
3455 case GL_COMPUTE_SHADER:
3456 {
3457 if (programObject->getAttachedComputeShader())
3458 {
3459 context->handleError(Error(GL_INVALID_OPERATION));
3460 return false;
3461 }
3462 break;
3463 }
3464 default:
3465 UNREACHABLE();
3466 break;
3467 }
3468
3469 return true;
3470}
3471
Jamie Madill01a80ee2016-11-07 12:06:18 -05003472bool ValidateBindAttribLocation(ValidationContext *context,
3473 GLuint program,
3474 GLuint index,
3475 const GLchar *name)
3476{
3477 if (index >= MAX_VERTEX_ATTRIBS)
3478 {
3479 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3480 return false;
3481 }
3482
3483 if (strncmp(name, "gl_", 3) == 0)
3484 {
3485 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3486 return false;
3487 }
3488
3489 return GetValidProgram(context, program) != nullptr;
3490}
3491
3492bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3493{
3494 if (!ValidBufferTarget(context, target))
3495 {
3496 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3497 return false;
3498 }
3499
3500 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3501 !context->isBufferGenerated(buffer))
3502 {
3503 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3504 return false;
3505 }
3506
3507 return true;
3508}
3509
3510bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3511{
3512 if (!ValidFramebufferTarget(target))
3513 {
3514 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3515 return false;
3516 }
3517
3518 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3519 !context->isFramebufferGenerated(framebuffer))
3520 {
3521 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3522 return false;
3523 }
3524
3525 return true;
3526}
3527
3528bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3529{
3530 if (target != GL_RENDERBUFFER)
3531 {
3532 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3533 return false;
3534 }
3535
3536 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3537 !context->isRenderbufferGenerated(renderbuffer))
3538 {
3539 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3540 return false;
3541 }
3542
3543 return true;
3544}
3545
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003546static bool ValidBlendEquationMode(GLenum mode)
3547{
3548 switch (mode)
3549 {
3550 case GL_FUNC_ADD:
3551 case GL_FUNC_SUBTRACT:
3552 case GL_FUNC_REVERSE_SUBTRACT:
3553 case GL_MIN:
3554 case GL_MAX:
3555 return true;
3556
3557 default:
3558 return false;
3559 }
3560}
3561
Jamie Madillc1d770e2017-04-13 17:31:24 -04003562bool ValidateBlendColor(ValidationContext *context,
3563 GLclampf red,
3564 GLclampf green,
3565 GLclampf blue,
3566 GLclampf alpha)
3567{
3568 return true;
3569}
3570
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003571bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3572{
3573 if (!ValidBlendEquationMode(mode))
3574 {
3575 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3576 return false;
3577 }
3578
3579 return true;
3580}
3581
3582bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3583{
3584 if (!ValidBlendEquationMode(modeRGB))
3585 {
3586 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3587 return false;
3588 }
3589
3590 if (!ValidBlendEquationMode(modeAlpha))
3591 {
3592 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3593 return false;
3594 }
3595
3596 return true;
3597}
3598
3599bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3600{
3601 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3602}
3603
3604static bool ValidSrcBlendFunc(GLenum srcBlend)
3605{
3606 switch (srcBlend)
3607 {
3608 case GL_ZERO:
3609 case GL_ONE:
3610 case GL_SRC_COLOR:
3611 case GL_ONE_MINUS_SRC_COLOR:
3612 case GL_DST_COLOR:
3613 case GL_ONE_MINUS_DST_COLOR:
3614 case GL_SRC_ALPHA:
3615 case GL_ONE_MINUS_SRC_ALPHA:
3616 case GL_DST_ALPHA:
3617 case GL_ONE_MINUS_DST_ALPHA:
3618 case GL_CONSTANT_COLOR:
3619 case GL_ONE_MINUS_CONSTANT_COLOR:
3620 case GL_CONSTANT_ALPHA:
3621 case GL_ONE_MINUS_CONSTANT_ALPHA:
3622 case GL_SRC_ALPHA_SATURATE:
3623 return true;
3624
3625 default:
3626 return false;
3627 }
3628}
3629
3630static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3631{
3632 switch (dstBlend)
3633 {
3634 case GL_ZERO:
3635 case GL_ONE:
3636 case GL_SRC_COLOR:
3637 case GL_ONE_MINUS_SRC_COLOR:
3638 case GL_DST_COLOR:
3639 case GL_ONE_MINUS_DST_COLOR:
3640 case GL_SRC_ALPHA:
3641 case GL_ONE_MINUS_SRC_ALPHA:
3642 case GL_DST_ALPHA:
3643 case GL_ONE_MINUS_DST_ALPHA:
3644 case GL_CONSTANT_COLOR:
3645 case GL_ONE_MINUS_CONSTANT_COLOR:
3646 case GL_CONSTANT_ALPHA:
3647 case GL_ONE_MINUS_CONSTANT_ALPHA:
3648 return true;
3649
3650 case GL_SRC_ALPHA_SATURATE:
3651 return (contextMajorVersion >= 3);
3652
3653 default:
3654 return false;
3655 }
3656}
3657
3658bool ValidateBlendFuncSeparate(ValidationContext *context,
3659 GLenum srcRGB,
3660 GLenum dstRGB,
3661 GLenum srcAlpha,
3662 GLenum dstAlpha)
3663{
3664 if (!ValidSrcBlendFunc(srcRGB))
3665 {
3666 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3667 return false;
3668 }
3669
3670 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3671 {
3672 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3673 return false;
3674 }
3675
3676 if (!ValidSrcBlendFunc(srcAlpha))
3677 {
3678 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3679 return false;
3680 }
3681
3682 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3683 {
3684 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3685 return false;
3686 }
3687
Frank Henigman146e8a12017-03-02 23:22:37 -05003688 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3689 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003690 {
3691 bool constantColorUsed =
3692 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3693 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3694
3695 bool constantAlphaUsed =
3696 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3697 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3698
3699 if (constantColorUsed && constantAlphaUsed)
3700 {
Frank Henigman146e8a12017-03-02 23:22:37 -05003701 const char *msg;
3702 if (context->getExtensions().webglCompatibility)
3703 {
3704 msg =
3705 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3706 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
3707 }
3708 else
3709 {
3710 msg =
3711 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3712 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3713 "implementation.";
3714 ERR() << msg;
3715 }
3716 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003717 return false;
3718 }
3719 }
3720
3721 return true;
3722}
3723
Geoff Langc339c4e2016-11-29 10:37:36 -05003724bool ValidateGetString(Context *context, GLenum name)
3725{
3726 switch (name)
3727 {
3728 case GL_VENDOR:
3729 case GL_RENDERER:
3730 case GL_VERSION:
3731 case GL_SHADING_LANGUAGE_VERSION:
3732 case GL_EXTENSIONS:
3733 break;
3734
3735 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3736 if (!context->getExtensions().requestExtension)
3737 {
3738 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3739 return false;
3740 }
3741 break;
3742
3743 default:
3744 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
3745 return false;
3746 }
3747
3748 return true;
3749}
3750
Geoff Lang47c48082016-12-07 15:38:13 -05003751bool ValidateLineWidth(ValidationContext *context, GLfloat width)
3752{
3753 if (width <= 0.0f || isNaN(width))
3754 {
3755 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
3756 return false;
3757 }
3758
3759 return true;
3760}
3761
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003762bool ValidateVertexAttribPointer(ValidationContext *context,
3763 GLuint index,
3764 GLint size,
3765 GLenum type,
3766 GLboolean normalized,
3767 GLsizei stride,
3768 const GLvoid *ptr)
3769{
Shao80957d92017-02-20 21:25:59 +08003770 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003771 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003772 return false;
3773 }
3774
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003775 if (stride < 0)
3776 {
Shao80957d92017-02-20 21:25:59 +08003777 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003778 return false;
3779 }
3780
Shao80957d92017-02-20 21:25:59 +08003781 const Caps &caps = context->getCaps();
3782 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003783 {
Shao80957d92017-02-20 21:25:59 +08003784 if (stride > caps.maxVertexAttribStride)
3785 {
3786 context->handleError(
3787 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
3788 return false;
3789 }
3790
3791 if (index >= caps.maxVertexAttribBindings)
3792 {
3793 context->handleError(
3794 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
3795 return false;
3796 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003797 }
3798
3799 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3800 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3801 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3802 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05003803 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
3804 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08003805 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003806 {
3807 context->handleError(
3808 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08003809 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003810 return false;
3811 }
3812
3813 if (context->getExtensions().webglCompatibility)
3814 {
3815 // WebGL 1.0 [Section 6.14] Fixed point support
3816 // The WebGL API does not support the GL_FIXED data type.
3817 if (type == GL_FIXED)
3818 {
3819 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
3820 return false;
3821 }
3822
Geoff Lang2d62ab72017-03-23 16:54:40 -04003823 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003824 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05003825 return false;
3826 }
3827 }
3828
3829 return true;
3830}
3831
Frank Henigman6137ddc2017-02-10 18:55:07 -05003832bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar)
3833{
3834 if (context->getExtensions().webglCompatibility && zNear > zFar)
3835 {
3836 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
3837 return false;
3838 }
3839
3840 return true;
3841}
3842
Jamie Madille8fb6402017-02-14 17:56:40 -05003843bool ValidateRenderbufferStorage(ValidationContext *context,
3844 GLenum target,
3845 GLenum internalformat,
3846 GLsizei width,
3847 GLsizei height)
3848{
3849 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
3850 height);
3851}
3852
3853bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
3854 GLenum target,
3855 GLsizei samples,
3856 GLenum internalformat,
3857 GLsizei width,
3858 GLsizei height)
3859{
3860 if (!context->getExtensions().framebufferMultisample)
3861 {
3862 context->handleError(
3863 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
3864 return false;
3865 }
3866
3867 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
3868 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
3869 // generated.
3870 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
3871 {
3872 context->handleError(Error(GL_INVALID_VALUE));
3873 return false;
3874 }
3875
3876 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
3877 // the specified storage. This is different than ES 3.0 in which a sample number higher
3878 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
3879 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
3880 if (context->getClientMajorVersion() >= 3)
3881 {
3882 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3883 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3884 {
3885 context->handleError(Error(GL_OUT_OF_MEMORY));
3886 return false;
3887 }
3888 }
3889
3890 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
3891 width, height);
3892}
3893
Jamie Madillc1d770e2017-04-13 17:31:24 -04003894bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
3895{
3896 if (!ValidFramebufferTarget(target))
3897 {
3898 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3899 return false;
3900 }
3901
3902 return true;
3903}
3904
3905bool ValidateClearColor(ValidationContext *context,
3906 GLclampf red,
3907 GLclampf green,
3908 GLclampf blue,
3909 GLclampf alpha)
3910{
3911 return true;
3912}
3913
3914bool ValidateClearDepthf(ValidationContext *context, GLclampf depth)
3915{
3916 return true;
3917}
3918
3919bool ValidateClearStencil(ValidationContext *context, GLint s)
3920{
3921 return true;
3922}
3923
3924bool ValidateColorMask(ValidationContext *context,
3925 GLboolean red,
3926 GLboolean green,
3927 GLboolean blue,
3928 GLboolean alpha)
3929{
3930 return true;
3931}
3932
3933bool ValidateCompileShader(ValidationContext *context, GLuint shader)
3934{
3935 return true;
3936}
3937
3938bool ValidateCreateProgram(ValidationContext *context)
3939{
3940 return true;
3941}
3942
3943bool ValidateCullFace(ValidationContext *context, GLenum mode)
3944{
3945 switch (mode)
3946 {
3947 case GL_FRONT:
3948 case GL_BACK:
3949 case GL_FRONT_AND_BACK:
3950 break;
3951
3952 default:
3953 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
3954 return false;
3955 }
3956
3957 return true;
3958}
3959
3960bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
3961{
3962 if (program == 0)
3963 {
3964 return false;
3965 }
3966
3967 if (!context->getProgram(program))
3968 {
3969 if (context->getShader(program))
3970 {
3971 context->handleError(
3972 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
3973 return false;
3974 }
3975 else
3976 {
3977 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
3978 return false;
3979 }
3980 }
3981
3982 return true;
3983}
3984
3985bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
3986{
3987 if (shader == 0)
3988 {
3989 return false;
3990 }
3991
3992 if (!context->getShader(shader))
3993 {
3994 if (context->getProgram(shader))
3995 {
3996 context->handleError(
3997 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
3998 return false;
3999 }
4000 else
4001 {
4002 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4003 return false;
4004 }
4005 }
4006
4007 return true;
4008}
4009
4010bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4011{
4012 switch (func)
4013 {
4014 case GL_NEVER:
4015 case GL_ALWAYS:
4016 case GL_LESS:
4017 case GL_LEQUAL:
4018 case GL_EQUAL:
4019 case GL_GREATER:
4020 case GL_GEQUAL:
4021 case GL_NOTEQUAL:
4022 break;
4023
4024 default:
4025 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4026 return false;
4027 }
4028
4029 return true;
4030}
4031
4032bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4033{
4034 return true;
4035}
4036
4037bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4038{
4039 Program *programObject = GetValidProgram(context, program);
4040 if (!programObject)
4041 {
4042 return false;
4043 }
4044
4045 Shader *shaderObject = GetValidShader(context, shader);
4046 if (!shaderObject)
4047 {
4048 return false;
4049 }
4050
4051 const Shader *attachedShader = nullptr;
4052
4053 switch (shaderObject->getType())
4054 {
4055 case GL_VERTEX_SHADER:
4056 {
4057 attachedShader = programObject->getAttachedVertexShader();
4058 break;
4059 }
4060 case GL_FRAGMENT_SHADER:
4061 {
4062 attachedShader = programObject->getAttachedFragmentShader();
4063 break;
4064 }
4065 case GL_COMPUTE_SHADER:
4066 {
4067 attachedShader = programObject->getAttachedComputeShader();
4068 break;
4069 }
4070 default:
4071 UNREACHABLE();
4072 return false;
4073 }
4074
4075 if (attachedShader != shaderObject)
4076 {
4077 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4078 return false;
4079 }
4080
4081 return true;
4082}
4083
4084bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4085{
4086 if (index >= MAX_VERTEX_ATTRIBS)
4087 {
4088 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4089 return false;
4090 }
4091
4092 return true;
4093}
4094
4095bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4096{
4097 if (index >= MAX_VERTEX_ATTRIBS)
4098 {
4099 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4100 return false;
4101 }
4102
4103 return true;
4104}
4105
4106bool ValidateFinish(ValidationContext *context)
4107{
4108 return true;
4109}
4110
4111bool ValidateFlush(ValidationContext *context)
4112{
4113 return true;
4114}
4115
4116bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4117{
4118 switch (mode)
4119 {
4120 case GL_CW:
4121 case GL_CCW:
4122 break;
4123 default:
4124 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4125 return false;
4126 }
4127
4128 return true;
4129}
4130
4131bool ValidateGetActiveAttrib(ValidationContext *context,
4132 GLuint program,
4133 GLuint index,
4134 GLsizei bufsize,
4135 GLsizei *length,
4136 GLint *size,
4137 GLenum *type,
4138 GLchar *name)
4139{
4140 if (bufsize < 0)
4141 {
4142 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4143 return false;
4144 }
4145
4146 Program *programObject = GetValidProgram(context, program);
4147
4148 if (!programObject)
4149 {
4150 return false;
4151 }
4152
4153 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4154 {
4155 context->handleError(
4156 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4157 return false;
4158 }
4159
4160 return true;
4161}
4162
4163bool ValidateGetActiveUniform(ValidationContext *context,
4164 GLuint program,
4165 GLuint index,
4166 GLsizei bufsize,
4167 GLsizei *length,
4168 GLint *size,
4169 GLenum *type,
4170 GLchar *name)
4171{
4172 if (bufsize < 0)
4173 {
4174 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4175 return false;
4176 }
4177
4178 Program *programObject = GetValidProgram(context, program);
4179
4180 if (!programObject)
4181 {
4182 return false;
4183 }
4184
4185 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4186 {
4187 context->handleError(
4188 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4189 return false;
4190 }
4191
4192 return true;
4193}
4194
4195bool ValidateGetAttachedShaders(ValidationContext *context,
4196 GLuint program,
4197 GLsizei maxcount,
4198 GLsizei *count,
4199 GLuint *shaders)
4200{
4201 if (maxcount < 0)
4202 {
4203 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4204 return false;
4205 }
4206
4207 Program *programObject = GetValidProgram(context, program);
4208
4209 if (!programObject)
4210 {
4211 return false;
4212 }
4213
4214 return true;
4215}
4216
4217bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4218{
4219 Program *programObject = GetValidProgram(context, program);
4220
4221 if (!programObject)
4222 {
4223 return false;
4224 }
4225
4226 if (!programObject->isLinked())
4227 {
4228 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4229 return false;
4230 }
4231
4232 return true;
4233}
4234
4235bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4236{
4237 GLenum nativeType;
4238 unsigned int numParams = 0;
4239 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4240}
4241
4242bool ValidateGetError(ValidationContext *context)
4243{
4244 return true;
4245}
4246
4247bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4248{
4249 GLenum nativeType;
4250 unsigned int numParams = 0;
4251 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4252}
4253
4254bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4255{
4256 GLenum nativeType;
4257 unsigned int numParams = 0;
4258 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4259}
4260
4261bool ValidateGetProgramInfoLog(ValidationContext *context,
4262 GLuint program,
4263 GLsizei bufsize,
4264 GLsizei *length,
4265 GLchar *infolog)
4266{
4267 if (bufsize < 0)
4268 {
4269 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4270 return false;
4271 }
4272
4273 Program *programObject = GetValidProgram(context, program);
4274 if (!programObject)
4275 {
4276 return false;
4277 }
4278
4279 return true;
4280}
4281
4282bool ValidateGetShaderInfoLog(ValidationContext *context,
4283 GLuint shader,
4284 GLsizei bufsize,
4285 GLsizei *length,
4286 GLchar *infolog)
4287{
4288 if (bufsize < 0)
4289 {
4290 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4291 return false;
4292 }
4293
4294 Shader *shaderObject = GetValidShader(context, shader);
4295 if (!shaderObject)
4296 {
4297 return false;
4298 }
4299
4300 return true;
4301}
4302
4303bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4304 GLenum shadertype,
4305 GLenum precisiontype,
4306 GLint *range,
4307 GLint *precision)
4308{
4309 switch (shadertype)
4310 {
4311 case GL_VERTEX_SHADER:
4312 case GL_FRAGMENT_SHADER:
4313 break;
4314 case GL_COMPUTE_SHADER:
4315 context->handleError(
4316 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4317 return false;
4318 default:
4319 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4320 return false;
4321 }
4322
4323 switch (precisiontype)
4324 {
4325 case GL_LOW_FLOAT:
4326 case GL_MEDIUM_FLOAT:
4327 case GL_HIGH_FLOAT:
4328 case GL_LOW_INT:
4329 case GL_MEDIUM_INT:
4330 case GL_HIGH_INT:
4331 break;
4332
4333 default:
4334 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4335 return false;
4336 }
4337
4338 return true;
4339}
4340
4341bool ValidateGetShaderSource(ValidationContext *context,
4342 GLuint shader,
4343 GLsizei bufsize,
4344 GLsizei *length,
4345 GLchar *source)
4346{
4347 if (bufsize < 0)
4348 {
4349 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4350 return false;
4351 }
4352
4353 Shader *shaderObject = GetValidShader(context, shader);
4354 if (!shaderObject)
4355 {
4356 return false;
4357 }
4358
4359 return true;
4360}
4361
4362bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4363{
4364 if (strstr(name, "gl_") == name)
4365 {
4366 return false;
4367 }
4368
4369 Program *programObject = GetValidProgram(context, program);
4370
4371 if (!programObject)
4372 {
4373 return false;
4374 }
4375
4376 if (!programObject->isLinked())
4377 {
4378 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4379 return false;
4380 }
4381
4382 return true;
4383}
4384
4385bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4386{
4387 switch (mode)
4388 {
4389 case GL_FASTEST:
4390 case GL_NICEST:
4391 case GL_DONT_CARE:
4392 break;
4393
4394 default:
4395 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4396 return false;
4397 }
4398
4399 switch (target)
4400 {
4401 case GL_GENERATE_MIPMAP_HINT:
4402 break;
4403
4404 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4405 if (!context->getExtensions().standardDerivatives)
4406 {
4407 context->handleError(
4408 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4409 return false;
4410 }
4411 break;
4412
4413 default:
4414 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4415 return false;
4416 }
4417
4418 return true;
4419}
4420
4421bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4422{
4423 return true;
4424}
4425
4426bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4427{
4428 return true;
4429}
4430
4431bool ValidateIsProgram(ValidationContext *context, GLuint program)
4432{
4433 return true;
4434}
4435
4436bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4437{
4438 return true;
4439}
4440
4441bool ValidateIsShader(ValidationContext *context, GLuint shader)
4442{
4443 return true;
4444}
4445
4446bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4447{
4448 return true;
4449}
4450
4451bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4452{
4453 if (context->getClientMajorVersion() < 3)
4454 {
4455 switch (pname)
4456 {
4457 case GL_UNPACK_IMAGE_HEIGHT:
4458 case GL_UNPACK_SKIP_IMAGES:
4459 context->handleError(Error(GL_INVALID_ENUM));
4460 return false;
4461
4462 case GL_UNPACK_ROW_LENGTH:
4463 case GL_UNPACK_SKIP_ROWS:
4464 case GL_UNPACK_SKIP_PIXELS:
4465 if (!context->getExtensions().unpackSubimage)
4466 {
4467 context->handleError(Error(GL_INVALID_ENUM));
4468 return false;
4469 }
4470 break;
4471
4472 case GL_PACK_ROW_LENGTH:
4473 case GL_PACK_SKIP_ROWS:
4474 case GL_PACK_SKIP_PIXELS:
4475 if (!context->getExtensions().packSubimage)
4476 {
4477 context->handleError(Error(GL_INVALID_ENUM));
4478 return false;
4479 }
4480 break;
4481 }
4482 }
4483
4484 if (param < 0)
4485 {
4486 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4487 return false;
4488 }
4489
4490 switch (pname)
4491 {
4492 case GL_UNPACK_ALIGNMENT:
4493 if (param != 1 && param != 2 && param != 4 && param != 8)
4494 {
4495 context->handleError(Error(GL_INVALID_VALUE));
4496 return false;
4497 }
4498 break;
4499
4500 case GL_PACK_ALIGNMENT:
4501 if (param != 1 && param != 2 && param != 4 && param != 8)
4502 {
4503 context->handleError(Error(GL_INVALID_VALUE));
4504 return false;
4505 }
4506 break;
4507
4508 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4509 case GL_UNPACK_ROW_LENGTH:
4510 case GL_UNPACK_IMAGE_HEIGHT:
4511 case GL_UNPACK_SKIP_IMAGES:
4512 case GL_UNPACK_SKIP_ROWS:
4513 case GL_UNPACK_SKIP_PIXELS:
4514 case GL_PACK_ROW_LENGTH:
4515 case GL_PACK_SKIP_ROWS:
4516 case GL_PACK_SKIP_PIXELS:
4517 break;
4518
4519 default:
4520 context->handleError(Error(GL_INVALID_ENUM));
4521 return false;
4522 }
4523
4524 return true;
4525}
4526
4527bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4528{
4529 return true;
4530}
4531
4532bool ValidateReleaseShaderCompiler(ValidationContext *context)
4533{
4534 return true;
4535}
4536
4537bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert)
4538{
4539 return true;
4540}
4541
4542bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4543{
4544 if (width < 0 || height < 0)
4545 {
4546 context->handleError(
4547 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4548 return false;
4549 }
4550
4551 return true;
4552}
4553
4554bool ValidateShaderBinary(ValidationContext *context,
4555 GLsizei n,
4556 const GLuint *shaders,
4557 GLenum binaryformat,
4558 const GLvoid *binary,
4559 GLsizei length)
4560{
4561 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4562 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4563 shaderBinaryFormats.end())
4564 {
4565 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4566 return false;
4567 }
4568
4569 return true;
4570}
4571
4572bool ValidateShaderSource(ValidationContext *context,
4573 GLuint shader,
4574 GLsizei count,
4575 const GLchar *const *string,
4576 const GLint *length)
4577{
4578 if (count < 0)
4579 {
4580 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4581 return false;
4582 }
4583
4584 Shader *shaderObject = GetValidShader(context, shader);
4585 if (!shaderObject)
4586 {
4587 return false;
4588 }
4589
4590 return true;
4591}
4592
4593bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4594{
4595 if (!IsValidStencilFunc(func))
4596 {
4597 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4598 return false;
4599 }
4600
4601 return true;
4602}
4603
4604bool ValidateStencilFuncSeparate(ValidationContext *context,
4605 GLenum face,
4606 GLenum func,
4607 GLint ref,
4608 GLuint mask)
4609{
4610 if (!IsValidStencilFace(face))
4611 {
4612 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4613 return false;
4614 }
4615
4616 if (!IsValidStencilFunc(func))
4617 {
4618 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4619 return false;
4620 }
4621
4622 return true;
4623}
4624
4625bool ValidateStencilMask(ValidationContext *context, GLuint mask)
4626{
4627 return true;
4628}
4629
4630bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
4631{
4632 if (!IsValidStencilFace(face))
4633 {
4634 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4635 return false;
4636 }
4637
4638 return true;
4639}
4640
4641bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
4642{
4643 if (!IsValidStencilOp(fail))
4644 {
4645 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
4646 return false;
4647 }
4648
4649 if (!IsValidStencilOp(zfail))
4650 {
4651 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
4652 return false;
4653 }
4654
4655 if (!IsValidStencilOp(zpass))
4656 {
4657 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
4658 return false;
4659 }
4660
4661 return true;
4662}
4663
4664bool ValidateStencilOpSeparate(ValidationContext *context,
4665 GLenum face,
4666 GLenum fail,
4667 GLenum zfail,
4668 GLenum zpass)
4669{
4670 if (!IsValidStencilFace(face))
4671 {
4672 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4673 return false;
4674 }
4675
4676 return ValidateStencilOp(context, fail, zfail, zpass);
4677}
4678
4679bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
4680{
4681 return ValidateUniform(context, GL_FLOAT, location, 1);
4682}
4683
4684bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4685{
4686 return ValidateUniform(context, GL_FLOAT, location, count);
4687}
4688
4689bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
4690{
4691 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
4692}
4693
4694bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4695{
4696 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
4697}
4698
4699bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
4700{
4701 return ValidateUniform(context, GL_INT_VEC2, location, 1);
4702}
4703
4704bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4705{
4706 return ValidateUniform(context, GL_INT_VEC2, location, count);
4707}
4708
4709bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
4710{
4711 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
4712}
4713
4714bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4715{
4716 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
4717}
4718
4719bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
4720{
4721 return ValidateUniform(context, GL_INT_VEC3, location, 1);
4722}
4723
4724bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4725{
4726 return ValidateUniform(context, GL_INT_VEC3, location, count);
4727}
4728
4729bool ValidateUniform4f(ValidationContext *context,
4730 GLint location,
4731 GLfloat x,
4732 GLfloat y,
4733 GLfloat z,
4734 GLfloat w)
4735{
4736 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
4737}
4738
4739bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
4740{
4741 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
4742}
4743
4744bool ValidateUniform4i(ValidationContext *context,
4745 GLint location,
4746 GLint x,
4747 GLint y,
4748 GLint z,
4749 GLint w)
4750{
4751 return ValidateUniform(context, GL_INT_VEC4, location, 1);
4752}
4753
4754bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
4755{
4756 return ValidateUniform(context, GL_INT_VEC4, location, count);
4757}
4758
4759bool ValidateUniformMatrix2fv(ValidationContext *context,
4760 GLint location,
4761 GLsizei count,
4762 GLboolean transpose,
4763 const GLfloat *value)
4764{
4765 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
4766}
4767
4768bool ValidateUniformMatrix3fv(ValidationContext *context,
4769 GLint location,
4770 GLsizei count,
4771 GLboolean transpose,
4772 const GLfloat *value)
4773{
4774 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
4775}
4776
4777bool ValidateUniformMatrix4fv(ValidationContext *context,
4778 GLint location,
4779 GLsizei count,
4780 GLboolean transpose,
4781 const GLfloat *value)
4782{
4783 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
4784}
4785
4786bool ValidateValidateProgram(ValidationContext *context, GLuint program)
4787{
4788 Program *programObject = GetValidProgram(context, program);
4789
4790 if (!programObject)
4791 {
4792 return false;
4793 }
4794
4795 return true;
4796}
4797
4798bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
4799{
4800 if (index >= MAX_VERTEX_ATTRIBS)
4801 {
4802 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
4803 return false;
4804 }
4805
4806 return true;
4807}
4808
4809bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
4810{
4811 return ValidateVertexAttribIndex(context, index);
4812}
4813
4814bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
4815{
4816 return ValidateVertexAttribIndex(context, index);
4817}
4818
4819bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
4820{
4821 return ValidateVertexAttribIndex(context, index);
4822}
4823
4824bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
4825{
4826 return ValidateVertexAttribIndex(context, index);
4827}
4828
4829bool ValidateVertexAttrib3f(ValidationContext *context,
4830 GLuint index,
4831 GLfloat x,
4832 GLfloat y,
4833 GLfloat z)
4834{
4835 return ValidateVertexAttribIndex(context, index);
4836}
4837
4838bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
4839{
4840 return ValidateVertexAttribIndex(context, index);
4841}
4842
4843bool ValidateVertexAttrib4f(ValidationContext *context,
4844 GLuint index,
4845 GLfloat x,
4846 GLfloat y,
4847 GLfloat z,
4848 GLfloat w)
4849{
4850 return ValidateVertexAttribIndex(context, index);
4851}
4852
4853bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
4854{
4855 return ValidateVertexAttribIndex(context, index);
4856}
4857
4858bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4859{
4860 if (width < 0 || height < 0)
4861 {
4862 context->handleError(
4863 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
4864 return false;
4865 }
4866
4867 return true;
4868}
4869
4870bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
4871{
4872 return ValidateDrawArraysCommon(context, mode, first, count, 1);
4873}
4874
Jamie Madillc29968b2016-01-20 11:17:23 -05004875} // namespace gl