blob: 1d7b894e1c2ed6ded40d962d79659cbf6c3ab1b2 [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"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27namespace gl
28{
29
Jamie Madillc29968b2016-01-20 11:17:23 -050030namespace
31{
32
33bool IsPartialBlit(gl::Context *context,
34 const FramebufferAttachment *readBuffer,
35 const FramebufferAttachment *writeBuffer,
36 GLint srcX0,
37 GLint srcY0,
38 GLint srcX1,
39 GLint srcY1,
40 GLint dstX0,
41 GLint dstY0,
42 GLint dstX1,
43 GLint dstY1)
44{
45 const Extents &writeSize = writeBuffer->getSize();
46 const Extents &readSize = readBuffer->getSize();
47
48 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
49 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
50 {
51 return true;
52 }
53
Jamie Madilldfde6ab2016-06-09 07:07:18 -070054 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050055 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070056 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050057 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
58 scissor.height < writeSize.height;
59 }
60
61 return false;
62}
63
Sami Väisänend59ca052016-06-21 16:10:00 +030064template <typename T>
65bool ValidatePathInstances(gl::Context *context,
66 GLsizei numPaths,
67 const void *paths,
68 GLuint pathBase)
69{
70 const auto *array = static_cast<const T *>(paths);
71
72 for (GLsizei i = 0; i < numPaths; ++i)
73 {
74 const GLuint pathName = array[i] + pathBase;
75 if (context->hasPath(pathName) && !context->hasPathData(pathName))
76 {
77 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
78 return false;
79 }
80 }
81 return true;
82}
83
84bool ValidateInstancedPathParameters(gl::Context *context,
85 GLsizei numPaths,
86 GLenum pathNameType,
87 const void *paths,
88 GLuint pathBase,
89 GLenum transformType,
90 const GLfloat *transformValues)
91{
92 if (!context->getExtensions().pathRendering)
93 {
94 context->handleError(
95 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
96 return false;
97 }
98
99 if (paths == nullptr)
100 {
101 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
102 return false;
103 }
104
105 if (numPaths < 0)
106 {
107 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
108 return false;
109 }
110
111 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
112 {
113 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
114 return false;
115 }
116
117 std::uint32_t pathNameTypeSize = 0;
118 std::uint32_t componentCount = 0;
119
120 switch (pathNameType)
121 {
122 case GL_UNSIGNED_BYTE:
123 pathNameTypeSize = sizeof(GLubyte);
124 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
125 return false;
126 break;
127
128 case GL_BYTE:
129 pathNameTypeSize = sizeof(GLbyte);
130 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
131 return false;
132 break;
133
134 case GL_UNSIGNED_SHORT:
135 pathNameTypeSize = sizeof(GLushort);
136 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
137 return false;
138 break;
139
140 case GL_SHORT:
141 pathNameTypeSize = sizeof(GLshort);
142 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
143 return false;
144 break;
145
146 case GL_UNSIGNED_INT:
147 pathNameTypeSize = sizeof(GLuint);
148 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
149 return false;
150 break;
151
152 case GL_INT:
153 pathNameTypeSize = sizeof(GLint);
154 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
155 return false;
156 break;
157
158 default:
159 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
160 return false;
161 }
162
163 switch (transformType)
164 {
165 case GL_NONE:
166 componentCount = 0;
167 break;
168 case GL_TRANSLATE_X_CHROMIUM:
169 case GL_TRANSLATE_Y_CHROMIUM:
170 componentCount = 1;
171 break;
172 case GL_TRANSLATE_2D_CHROMIUM:
173 componentCount = 2;
174 break;
175 case GL_TRANSLATE_3D_CHROMIUM:
176 componentCount = 3;
177 break;
178 case GL_AFFINE_2D_CHROMIUM:
179 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
180 componentCount = 6;
181 break;
182 case GL_AFFINE_3D_CHROMIUM:
183 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
184 componentCount = 12;
185 break;
186 default:
187 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
188 return false;
189 }
190 if (componentCount != 0 && transformValues == nullptr)
191 {
192 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
193 return false;
194 }
195
196 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
197 checkedSize += (numPaths * pathNameTypeSize);
198 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
199 if (!checkedSize.IsValid())
200 {
201 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
202 return false;
203 }
204
205 return true;
206}
207
Geoff Lang97073d12016-04-20 10:42:34 -0700208bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
209{
210 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
211 switch (internalFormatInfo.format)
212 {
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 Madillc29968b2016-01-20 11:17:23 -0500286} // anonymous namespace
287
Geoff Langff5b2d52016-09-07 11:32:23 -0400288bool ValidateES2TexImageParameters(Context *context,
289 GLenum target,
290 GLint level,
291 GLenum internalformat,
292 bool isCompressed,
293 bool isSubImage,
294 GLint xoffset,
295 GLint yoffset,
296 GLsizei width,
297 GLsizei height,
298 GLint border,
299 GLenum format,
300 GLenum type,
301 GLsizei imageSize,
302 const GLvoid *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400303{
Jamie Madill6f38f822014-06-06 17:12:20 -0400304 if (!ValidTexture2DDestinationTarget(context, target))
305 {
Jamie Madill437fa652016-05-03 15:13:24 -0400306 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400307 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400308 }
309
Austin Kinross08528e12015-10-07 16:24:40 -0700310 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400311 {
Jamie Madill437fa652016-05-03 15:13:24 -0400312 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400313 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400314 }
315
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400316 if (level < 0 || xoffset < 0 ||
317 std::numeric_limits<GLsizei>::max() - xoffset < width ||
318 std::numeric_limits<GLsizei>::max() - yoffset < height)
319 {
Jamie Madill437fa652016-05-03 15:13:24 -0400320 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
Geoff Lang005df412013-10-16 14:12:50 -0400324 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Jamie Madill437fa652016-05-03 15:13:24 -0400326 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 }
329
Geoff Langaae65a42014-05-26 12:43:44 -0400330 const gl::Caps &caps = context->getCaps();
331
Geoff Langa9be0dc2014-12-17 12:34:40 -0500332 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500334 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
335 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 {
Jamie Madill437fa652016-05-03 15:13:24 -0400337 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500340 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500341 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500342 {
343 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 {
Jamie Madill437fa652016-05-03 15:13:24 -0400345 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400348
Geoff Langa9be0dc2014-12-17 12:34:40 -0500349 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
350 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
351 {
Jamie Madill437fa652016-05-03 15:13:24 -0400352 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500353 return false;
354 }
355 }
356 else
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;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400360 }
361
Geoff Lang691e58c2014-12-19 17:03:25 -0500362 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400363 if (!texture)
364 {
Jamie Madill437fa652016-05-03 15:13:24 -0400365 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
368
Geoff Langa9be0dc2014-12-17 12:34:40 -0500369 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400370 {
Geoff Langc51642b2016-11-14 16:18:26 -0500371 GLenum textureFormat = texture->getFormat(target, level).asSized();
372 if (textureFormat == GL_NONE)
373 {
374 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
375 return false;
376 }
377
Geoff Langa9be0dc2014-12-17 12:34:40 -0500378 if (format != GL_NONE)
379 {
Geoff Langc51642b2016-11-14 16:18:26 -0500380 if (gl::GetSizedInternalFormat(format, type) != textureFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500381 {
Jamie Madill437fa652016-05-03 15:13:24 -0400382 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500383 return false;
384 }
385 }
386
387 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
388 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
389 {
Jamie Madill437fa652016-05-03 15:13:24 -0400390 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500391 return false;
392 }
393 }
394 else
395 {
Geoff Lang69cce582015-09-17 13:20:36 -0400396 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500397 {
Jamie Madill437fa652016-05-03 15:13:24 -0400398 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500399 return false;
400 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400401 }
402
403 // Verify zero border
404 if (border != 0)
405 {
Jamie Madill437fa652016-05-03 15:13:24 -0400406 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 }
409
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400410 if (isCompressed)
411 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400412 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400413 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400414 switch (actualInternalFormat)
415 {
416 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
417 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400418 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400419 {
Jamie Madill437fa652016-05-03 15:13:24 -0400420 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 }
423 break;
424 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400425 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400426 {
Jamie Madill437fa652016-05-03 15:13:24 -0400427 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400429 }
430 break;
431 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400432 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400433 {
Jamie Madill437fa652016-05-03 15:13:24 -0400434 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400436 }
437 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400438 case GL_ETC1_RGB8_OES:
439 if (!context->getExtensions().compressedETC1RGB8Texture)
440 {
Jamie Madill437fa652016-05-03 15:13:24 -0400441 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400442 return false;
443 }
444 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800445 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
446 if (!context->getExtensions().lossyETCDecode)
447 {
Jamie Madill437fa652016-05-03 15:13:24 -0400448 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800449 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
450 return false;
451 }
452 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400453 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400454 context->handleError(Error(
tmartino0ccd5ae2015-10-01 14:33:14 -0400455 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
456 return false;
457 }
458 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
459 {
Jamie Madill437fa652016-05-03 15:13:24 -0400460 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400462 }
463 }
464 else
465 {
466 // validate <type> by itself (used as secondary key below)
467 switch (type)
468 {
469 case GL_UNSIGNED_BYTE:
470 case GL_UNSIGNED_SHORT_5_6_5:
471 case GL_UNSIGNED_SHORT_4_4_4_4:
472 case GL_UNSIGNED_SHORT_5_5_5_1:
473 case GL_UNSIGNED_SHORT:
474 case GL_UNSIGNED_INT:
475 case GL_UNSIGNED_INT_24_8_OES:
476 case GL_HALF_FLOAT_OES:
477 case GL_FLOAT:
478 break;
479 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400480 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400481 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400482 }
483
484 // validate <format> + <type> combinations
485 // - invalid <format> -> sets INVALID_ENUM
486 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
487 switch (format)
488 {
489 case GL_ALPHA:
490 case GL_LUMINANCE:
491 case GL_LUMINANCE_ALPHA:
492 switch (type)
493 {
494 case GL_UNSIGNED_BYTE:
495 case GL_FLOAT:
496 case GL_HALF_FLOAT_OES:
497 break;
Geoff Langb1196682014-07-23 13:47:29 -0400498 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400499 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400500 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400501 }
502 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400503 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400504 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400505 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400506 {
Jamie Madill437fa652016-05-03 15:13:24 -0400507 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400508 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400509 }
510 switch (type)
511 {
512 case GL_UNSIGNED_BYTE:
513 case GL_FLOAT:
514 case GL_HALF_FLOAT_OES:
515 break;
516 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400517 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400518 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400519 }
520 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400521 case GL_RGB:
522 switch (type)
523 {
524 case GL_UNSIGNED_BYTE:
525 case GL_UNSIGNED_SHORT_5_6_5:
526 case GL_FLOAT:
527 case GL_HALF_FLOAT_OES:
528 break;
529 default:
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 break;
534 case GL_RGBA:
535 switch (type)
536 {
537 case GL_UNSIGNED_BYTE:
538 case GL_UNSIGNED_SHORT_4_4_4_4:
539 case GL_UNSIGNED_SHORT_5_5_5_1:
540 case GL_FLOAT:
541 case GL_HALF_FLOAT_OES:
542 break;
543 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400544 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400545 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400546 }
547 break;
548 case GL_BGRA_EXT:
549 switch (type)
550 {
551 case GL_UNSIGNED_BYTE:
552 break;
553 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400554 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400555 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400556 }
557 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400558 case GL_SRGB_EXT:
559 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400560 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400561 {
Jamie Madill437fa652016-05-03 15:13:24 -0400562 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400563 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400564 }
565 switch (type)
566 {
567 case GL_UNSIGNED_BYTE:
568 break;
569 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400570 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400571 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400572 }
573 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400574 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
575 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
576 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
577 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
578 break;
579 case GL_DEPTH_COMPONENT:
580 switch (type)
581 {
582 case GL_UNSIGNED_SHORT:
583 case GL_UNSIGNED_INT:
584 break;
585 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400586 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400587 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400588 }
589 break;
590 case GL_DEPTH_STENCIL_OES:
591 switch (type)
592 {
593 case GL_UNSIGNED_INT_24_8_OES:
594 break;
595 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400596 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400597 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400598 }
599 break;
600 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400601 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400602 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400603 }
604
605 switch (format)
606 {
607 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
608 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400609 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400610 {
Jamie Madill437fa652016-05-03 15:13:24 -0400611 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400612 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400613 }
614 else
615 {
Jamie Madill437fa652016-05-03 15:13:24 -0400616 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400617 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400618 }
619 break;
620 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400621 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400622 {
Jamie Madill437fa652016-05-03 15:13:24 -0400623 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400624 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400625 }
626 else
627 {
Jamie Madill437fa652016-05-03 15:13:24 -0400628 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400629 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400630 }
631 break;
632 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400633 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400634 {
Jamie Madill437fa652016-05-03 15:13:24 -0400635 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400637 }
638 else
639 {
Jamie Madill437fa652016-05-03 15:13:24 -0400640 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400641 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400642 }
643 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400644 case GL_ETC1_RGB8_OES:
645 if (context->getExtensions().compressedETC1RGB8Texture)
646 {
Jamie Madill437fa652016-05-03 15:13:24 -0400647 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400648 return false;
649 }
650 else
651 {
Jamie Madill437fa652016-05-03 15:13:24 -0400652 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400653 return false;
654 }
655 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800656 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
657 if (context->getExtensions().lossyETCDecode)
658 {
Jamie Madill437fa652016-05-03 15:13:24 -0400659 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800660 Error(GL_INVALID_OPERATION,
661 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
662 return false;
663 }
664 else
665 {
Jamie Madill437fa652016-05-03 15:13:24 -0400666 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800667 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
668 return false;
669 }
670 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400671 case GL_DEPTH_COMPONENT:
672 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400673 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400674 {
Jamie Madill437fa652016-05-03 15:13:24 -0400675 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400676 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400677 }
678 if (target != GL_TEXTURE_2D)
679 {
Jamie Madill437fa652016-05-03 15:13:24 -0400680 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400681 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 }
683 // OES_depth_texture supports loading depth data and multiple levels,
684 // but ANGLE_depth_texture does not
685 if (pixels != NULL || level != 0)
686 {
Jamie Madill437fa652016-05-03 15:13:24 -0400687 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400688 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400689 }
690 break;
691 default:
692 break;
693 }
694
695 if (type == GL_FLOAT)
696 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400697 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400698 {
Jamie Madill437fa652016-05-03 15:13:24 -0400699 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400700 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701 }
702 }
703 else if (type == GL_HALF_FLOAT_OES)
704 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400705 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400706 {
Jamie Madill437fa652016-05-03 15:13:24 -0400707 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400708 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400709 }
710 }
711 }
712
Geoff Langff5b2d52016-09-07 11:32:23 -0400713 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
714 imageSize))
715 {
716 return false;
717 }
718
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 return true;
720}
721
Jamie Madillc29968b2016-01-20 11:17:23 -0500722bool ValidateES2CopyTexImageParameters(ValidationContext *context,
723 GLenum target,
724 GLint level,
725 GLenum internalformat,
726 bool isSubImage,
727 GLint xoffset,
728 GLint yoffset,
729 GLint x,
730 GLint y,
731 GLsizei width,
732 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 GLint border)
734{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500735 if (!ValidTexture2DDestinationTarget(context, target))
736 {
Jamie Madill437fa652016-05-03 15:13:24 -0400737 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500738 return false;
739 }
740
Jamie Madill0c8abca2016-07-22 20:21:26 -0400741 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400742 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400743 xoffset, yoffset, 0, x, y, width, height, border,
744 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400745 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 }
748
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700749 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400750 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400751 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752
753 // [OpenGL ES 2.0.24] table 3.9
754 if (isSubImage)
755 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400756 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400757 {
758 case GL_ALPHA:
759 if (colorbufferFormat != GL_ALPHA8_EXT &&
760 colorbufferFormat != GL_RGBA4 &&
761 colorbufferFormat != GL_RGB5_A1 &&
762 colorbufferFormat != GL_RGBA8_OES)
763 {
Jamie Madill437fa652016-05-03 15:13:24 -0400764 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400766 }
767 break;
768 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400769 if (colorbufferFormat != GL_R8_EXT &&
770 colorbufferFormat != GL_RG8_EXT &&
771 colorbufferFormat != GL_RGB565 &&
772 colorbufferFormat != GL_RGB8_OES &&
773 colorbufferFormat != GL_RGBA4 &&
774 colorbufferFormat != GL_RGB5_A1 &&
775 colorbufferFormat != GL_RGBA8_OES)
776 {
Jamie Madill437fa652016-05-03 15:13:24 -0400777 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400778 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400779 }
780 break;
781 case GL_RED_EXT:
782 if (colorbufferFormat != GL_R8_EXT &&
783 colorbufferFormat != GL_RG8_EXT &&
784 colorbufferFormat != GL_RGB565 &&
785 colorbufferFormat != GL_RGB8_OES &&
786 colorbufferFormat != GL_RGBA4 &&
787 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500788 colorbufferFormat != GL_RGBA8_OES &&
789 colorbufferFormat != GL_R32F &&
790 colorbufferFormat != GL_RG32F &&
791 colorbufferFormat != GL_RGB32F &&
792 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400793 {
Jamie Madill437fa652016-05-03 15:13:24 -0400794 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400795 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400796 }
797 break;
798 case GL_RG_EXT:
799 if (colorbufferFormat != GL_RG8_EXT &&
800 colorbufferFormat != GL_RGB565 &&
801 colorbufferFormat != GL_RGB8_OES &&
802 colorbufferFormat != GL_RGBA4 &&
803 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500804 colorbufferFormat != GL_RGBA8_OES &&
805 colorbufferFormat != GL_RG32F &&
806 colorbufferFormat != GL_RGB32F &&
807 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400808 {
Jamie Madill437fa652016-05-03 15:13:24 -0400809 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400810 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400811 }
812 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400813 case GL_RGB:
814 if (colorbufferFormat != GL_RGB565 &&
815 colorbufferFormat != GL_RGB8_OES &&
816 colorbufferFormat != GL_RGBA4 &&
817 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500818 colorbufferFormat != GL_RGBA8_OES &&
819 colorbufferFormat != GL_RGB32F &&
820 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 {
Jamie Madill437fa652016-05-03 15:13:24 -0400822 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400823 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 }
825 break;
826 case GL_LUMINANCE_ALPHA:
827 case GL_RGBA:
828 if (colorbufferFormat != GL_RGBA4 &&
829 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500830 colorbufferFormat != GL_RGBA8_OES &&
831 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 {
Jamie Madill437fa652016-05-03 15:13:24 -0400833 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400834 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 }
836 break;
837 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
838 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
839 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
840 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400841 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800842 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400843 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400844 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400845 case GL_DEPTH_COMPONENT:
846 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400848 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400849 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400850 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400851 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400852 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500853
Jamie Madill0c8abca2016-07-22 20:21:26 -0400854 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500855 {
Jamie Madill437fa652016-05-03 15:13:24 -0400856 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500857 return false;
858 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 }
860 else
861 {
862 switch (internalformat)
863 {
864 case GL_ALPHA:
865 if (colorbufferFormat != GL_ALPHA8_EXT &&
866 colorbufferFormat != GL_RGBA4 &&
867 colorbufferFormat != GL_RGB5_A1 &&
868 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500869 colorbufferFormat != GL_RGBA8_OES &&
870 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 {
Jamie Madill437fa652016-05-03 15:13:24 -0400872 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400873 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 }
875 break;
876 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400877 if (colorbufferFormat != GL_R8_EXT &&
878 colorbufferFormat != GL_RG8_EXT &&
879 colorbufferFormat != GL_RGB565 &&
880 colorbufferFormat != GL_RGB8_OES &&
881 colorbufferFormat != GL_RGBA4 &&
882 colorbufferFormat != GL_RGB5_A1 &&
883 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500884 colorbufferFormat != GL_RGBA8_OES &&
885 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400886 {
Jamie Madill437fa652016-05-03 15:13:24 -0400887 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400888 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400889 }
890 break;
891 case GL_RED_EXT:
892 if (colorbufferFormat != GL_R8_EXT &&
893 colorbufferFormat != GL_RG8_EXT &&
894 colorbufferFormat != GL_RGB565 &&
895 colorbufferFormat != GL_RGB8_OES &&
896 colorbufferFormat != GL_RGBA4 &&
897 colorbufferFormat != GL_RGB5_A1 &&
898 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500899 colorbufferFormat != GL_RGBA8_OES &&
900 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400901 {
Jamie Madill437fa652016-05-03 15:13:24 -0400902 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400903 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400904 }
905 break;
906 case GL_RG_EXT:
907 if (colorbufferFormat != GL_RG8_EXT &&
908 colorbufferFormat != GL_RGB565 &&
909 colorbufferFormat != GL_RGB8_OES &&
910 colorbufferFormat != GL_RGBA4 &&
911 colorbufferFormat != GL_RGB5_A1 &&
912 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500913 colorbufferFormat != GL_RGBA8_OES &&
914 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400915 {
Jamie Madill437fa652016-05-03 15:13:24 -0400916 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400917 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400918 }
919 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400920 case GL_RGB:
921 if (colorbufferFormat != GL_RGB565 &&
922 colorbufferFormat != GL_RGB8_OES &&
923 colorbufferFormat != GL_RGBA4 &&
924 colorbufferFormat != GL_RGB5_A1 &&
925 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500926 colorbufferFormat != GL_RGBA8_OES &&
927 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 {
Jamie Madill437fa652016-05-03 15:13:24 -0400929 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400930 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931 }
932 break;
933 case GL_LUMINANCE_ALPHA:
934 case GL_RGBA:
935 if (colorbufferFormat != GL_RGBA4 &&
936 colorbufferFormat != GL_RGB5_A1 &&
937 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500938 colorbufferFormat != GL_RGBA8_OES &&
939 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400940 {
Jamie Madill437fa652016-05-03 15:13:24 -0400941 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400943 }
944 break;
945 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
946 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400947 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 {
Jamie Madill437fa652016-05-03 15:13:24 -0400949 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952 else
953 {
Jamie Madill437fa652016-05-03 15:13:24 -0400954 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 }
957 break;
958 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400959 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 {
Jamie Madill437fa652016-05-03 15:13:24 -0400961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963 }
964 else
965 {
Jamie Madill437fa652016-05-03 15:13:24 -0400966 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400967 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 }
969 break;
970 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400971 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972 {
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 else
977 {
Jamie Madill437fa652016-05-03 15:13:24 -0400978 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400979 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 }
981 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400982 case GL_ETC1_RGB8_OES:
983 if (context->getExtensions().compressedETC1RGB8Texture)
984 {
Jamie Madill437fa652016-05-03 15:13:24 -0400985 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400986 return false;
987 }
988 else
989 {
Jamie Madill437fa652016-05-03 15:13:24 -0400990 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400991 return false;
992 }
993 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800994 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
995 if (context->getExtensions().lossyETCDecode)
996 {
Jamie Madill437fa652016-05-03 15:13:24 -0400997 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800998 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
999 return false;
1000 }
1001 else
1002 {
Jamie Madill437fa652016-05-03 15:13:24 -04001003 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001004 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1005 return false;
1006 }
1007 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 case GL_DEPTH_COMPONENT:
1009 case GL_DEPTH_COMPONENT16:
1010 case GL_DEPTH_COMPONENT32_OES:
1011 case GL_DEPTH_STENCIL_OES:
1012 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001013 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 {
Jamie Madill437fa652016-05-03 15:13:24 -04001015 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001016 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001017 }
1018 else
1019 {
Jamie Madill437fa652016-05-03 15:13:24 -04001020 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001021 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001022 }
1023 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001024 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 }
1027 }
1028
Geoff Lang784a8fd2013-09-24 12:33:16 -04001029 // If width or height is zero, it is a no-op. Return false without setting an error.
1030 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031}
1032
Geoff Langb1196682014-07-23 13:47:29 -04001033bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 GLsizei width, GLsizei height)
1035{
1036 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041
1042 if (width < 1 || height < 1 || levels < 1)
1043 {
Jamie Madill437fa652016-05-03 15:13:24 -04001044 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001045 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001046 }
1047
1048 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053
1054 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1055 {
Jamie Madill437fa652016-05-03 15:13:24 -04001056 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 }
1059
Geoff Lang5d601382014-07-22 15:14:06 -04001060 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1061 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 {
Jamie Madill437fa652016-05-03 15:13:24 -04001063 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066
Geoff Langaae65a42014-05-26 12:43:44 -04001067 const gl::Caps &caps = context->getCaps();
1068
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001069 switch (target)
1070 {
1071 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -04001072 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1073 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 {
Jamie Madill437fa652016-05-03 15:13:24 -04001075 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001076 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 }
1078 break;
1079 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -04001080 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1081 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 {
Jamie Madill437fa652016-05-03 15:13:24 -04001083 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 }
1086 break;
1087 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001088 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 }
1091
Geoff Langc0b9ef42014-07-02 10:02:37 -04001092 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 {
1094 if (!gl::isPow2(width) || !gl::isPow2(height))
1095 {
Jamie Madill437fa652016-05-03 15:13:24 -04001096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 }
1099 }
1100
1101 switch (internalformat)
1102 {
1103 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1104 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001105 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 {
Jamie Madill437fa652016-05-03 15:13:24 -04001107 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001108 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001109 }
1110 break;
1111 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001112 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 {
Jamie Madill437fa652016-05-03 15:13:24 -04001114 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001115 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 }
1117 break;
1118 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001119 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 {
Jamie Madill437fa652016-05-03 15:13:24 -04001121 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001122 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001123 }
1124 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001125 case GL_ETC1_RGB8_OES:
1126 if (!context->getExtensions().compressedETC1RGB8Texture)
1127 {
Jamie Madill437fa652016-05-03 15:13:24 -04001128 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001129 return false;
1130 }
1131 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001132 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1133 if (!context->getExtensions().lossyETCDecode)
1134 {
Jamie Madill437fa652016-05-03 15:13:24 -04001135 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001136 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1137 return false;
1138 }
1139 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001140 case GL_RGBA32F_EXT:
1141 case GL_RGB32F_EXT:
1142 case GL_ALPHA32F_EXT:
1143 case GL_LUMINANCE32F_EXT:
1144 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001145 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 {
Jamie Madill437fa652016-05-03 15:13:24 -04001147 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150 break;
1151 case GL_RGBA16F_EXT:
1152 case GL_RGB16F_EXT:
1153 case GL_ALPHA16F_EXT:
1154 case GL_LUMINANCE16F_EXT:
1155 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001156 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 {
Jamie Madill437fa652016-05-03 15:13:24 -04001158 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001159 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 }
1161 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001162 case GL_R8_EXT:
1163 case GL_RG8_EXT:
1164 case GL_R16F_EXT:
1165 case GL_RG16F_EXT:
1166 case GL_R32F_EXT:
1167 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001168 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001169 {
Jamie Madill437fa652016-05-03 15:13:24 -04001170 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001172 }
1173 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001174 case GL_DEPTH_COMPONENT16:
1175 case GL_DEPTH_COMPONENT32_OES:
1176 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001177 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 {
Jamie Madill437fa652016-05-03 15:13:24 -04001179 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 }
1182 if (target != GL_TEXTURE_2D)
1183 {
Jamie Madill437fa652016-05-03 15:13:24 -04001184 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001186 }
1187 // ANGLE_depth_texture only supports 1-level textures
1188 if (levels != 1)
1189 {
Jamie Madill437fa652016-05-03 15:13:24 -04001190 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001191 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001192 }
1193 break;
1194 default:
1195 break;
1196 }
1197
Geoff Lang691e58c2014-12-19 17:03:25 -05001198 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001199 if (!texture || texture->id() == 0)
1200 {
Jamie Madill437fa652016-05-03 15:13:24 -04001201 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 }
1204
Geoff Lang69cce582015-09-17 13:20:36 -04001205 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001206 {
Jamie Madill437fa652016-05-03 15:13:24 -04001207 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001208 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001209 }
1210
1211 return true;
1212}
1213
Austin Kinross08332632015-05-05 13:35:47 -07001214bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1215 const GLenum *attachments)
1216{
Jamie Madillc29968b2016-01-20 11:17:23 -05001217 if (!context->getExtensions().discardFramebuffer)
1218 {
Jamie Madill437fa652016-05-03 15:13:24 -04001219 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001220 return false;
1221 }
1222
Austin Kinross08332632015-05-05 13:35:47 -07001223 bool defaultFramebuffer = false;
1224
1225 switch (target)
1226 {
1227 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001228 defaultFramebuffer =
1229 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1230 break;
Austin Kinross08332632015-05-05 13:35:47 -07001231 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001232 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001233 return false;
1234 }
1235
1236 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1237}
1238
Austin Kinrossbc781f32015-10-26 09:27:38 -07001239bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1240{
1241 if (!context->getExtensions().vertexArrayObject)
1242 {
Jamie Madill437fa652016-05-03 15:13:24 -04001243 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001244 return false;
1245 }
1246
1247 return ValidateBindVertexArrayBase(context, array);
1248}
1249
1250bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1251{
1252 if (!context->getExtensions().vertexArrayObject)
1253 {
Jamie Madill437fa652016-05-03 15:13:24 -04001254 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001255 return false;
1256 }
1257
Olli Etuaho41997e72016-03-10 13:38:39 +02001258 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001259}
1260
1261bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1262{
1263 if (!context->getExtensions().vertexArrayObject)
1264 {
Jamie Madill437fa652016-05-03 15:13:24 -04001265 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001266 return false;
1267 }
1268
Olli Etuaho41997e72016-03-10 13:38:39 +02001269 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001270}
1271
1272bool ValidateIsVertexArrayOES(Context *context)
1273{
1274 if (!context->getExtensions().vertexArrayObject)
1275 {
Jamie Madill437fa652016-05-03 15:13:24 -04001276 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001277 return false;
1278 }
1279
1280 return true;
1281}
Geoff Langc5629752015-12-07 16:29:04 -05001282
1283bool ValidateProgramBinaryOES(Context *context,
1284 GLuint program,
1285 GLenum binaryFormat,
1286 const void *binary,
1287 GLint length)
1288{
1289 if (!context->getExtensions().getProgramBinary)
1290 {
Jamie Madill437fa652016-05-03 15:13:24 -04001291 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001292 return false;
1293 }
1294
1295 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1296}
1297
1298bool ValidateGetProgramBinaryOES(Context *context,
1299 GLuint program,
1300 GLsizei bufSize,
1301 GLsizei *length,
1302 GLenum *binaryFormat,
1303 void *binary)
1304{
1305 if (!context->getExtensions().getProgramBinary)
1306 {
Jamie Madill437fa652016-05-03 15:13:24 -04001307 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001308 return false;
1309 }
1310
1311 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1312}
Geoff Lange102fee2015-12-10 11:23:30 -05001313
Geoff Lang70d0f492015-12-10 17:45:46 -05001314static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1315{
1316 switch (source)
1317 {
1318 case GL_DEBUG_SOURCE_API:
1319 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1320 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1321 case GL_DEBUG_SOURCE_OTHER:
1322 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1323 return !mustBeThirdPartyOrApplication;
1324
1325 case GL_DEBUG_SOURCE_THIRD_PARTY:
1326 case GL_DEBUG_SOURCE_APPLICATION:
1327 return true;
1328
1329 default:
1330 return false;
1331 }
1332}
1333
1334static bool ValidDebugType(GLenum type)
1335{
1336 switch (type)
1337 {
1338 case GL_DEBUG_TYPE_ERROR:
1339 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1340 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1341 case GL_DEBUG_TYPE_PERFORMANCE:
1342 case GL_DEBUG_TYPE_PORTABILITY:
1343 case GL_DEBUG_TYPE_OTHER:
1344 case GL_DEBUG_TYPE_MARKER:
1345 case GL_DEBUG_TYPE_PUSH_GROUP:
1346 case GL_DEBUG_TYPE_POP_GROUP:
1347 return true;
1348
1349 default:
1350 return false;
1351 }
1352}
1353
1354static bool ValidDebugSeverity(GLenum severity)
1355{
1356 switch (severity)
1357 {
1358 case GL_DEBUG_SEVERITY_HIGH:
1359 case GL_DEBUG_SEVERITY_MEDIUM:
1360 case GL_DEBUG_SEVERITY_LOW:
1361 case GL_DEBUG_SEVERITY_NOTIFICATION:
1362 return true;
1363
1364 default:
1365 return false;
1366 }
1367}
1368
Geoff Lange102fee2015-12-10 11:23:30 -05001369bool ValidateDebugMessageControlKHR(Context *context,
1370 GLenum source,
1371 GLenum type,
1372 GLenum severity,
1373 GLsizei count,
1374 const GLuint *ids,
1375 GLboolean enabled)
1376{
1377 if (!context->getExtensions().debug)
1378 {
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001380 return false;
1381 }
1382
Geoff Lang70d0f492015-12-10 17:45:46 -05001383 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001386 return false;
1387 }
1388
1389 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1390 {
Jamie Madill437fa652016-05-03 15:13:24 -04001391 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001392 return false;
1393 }
1394
1395 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1396 {
Jamie Madill437fa652016-05-03 15:13:24 -04001397 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001398 return false;
1399 }
1400
1401 if (count > 0)
1402 {
1403 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1404 {
Jamie Madill437fa652016-05-03 15:13:24 -04001405 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001406 GL_INVALID_OPERATION,
1407 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1408 return false;
1409 }
1410
1411 if (severity != GL_DONT_CARE)
1412 {
Jamie Madill437fa652016-05-03 15:13:24 -04001413 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001414 Error(GL_INVALID_OPERATION,
1415 "If count is greater than zero, severity must be GL_DONT_CARE."));
1416 return false;
1417 }
1418 }
1419
Geoff Lange102fee2015-12-10 11:23:30 -05001420 return true;
1421}
1422
1423bool ValidateDebugMessageInsertKHR(Context *context,
1424 GLenum source,
1425 GLenum type,
1426 GLuint id,
1427 GLenum severity,
1428 GLsizei length,
1429 const GLchar *buf)
1430{
1431 if (!context->getExtensions().debug)
1432 {
Jamie Madill437fa652016-05-03 15:13:24 -04001433 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001434 return false;
1435 }
1436
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001437 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001438 {
1439 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1440 // not generate an error.
1441 return false;
1442 }
1443
1444 if (!ValidDebugSeverity(severity))
1445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001447 return false;
1448 }
1449
1450 if (!ValidDebugType(type))
1451 {
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001453 return false;
1454 }
1455
1456 if (!ValidDebugSource(source, true))
1457 {
Jamie Madill437fa652016-05-03 15:13:24 -04001458 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001459 return false;
1460 }
1461
1462 size_t messageLength = (length < 0) ? strlen(buf) : length;
1463 if (messageLength > context->getExtensions().maxDebugMessageLength)
1464 {
Jamie Madill437fa652016-05-03 15:13:24 -04001465 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001466 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1467 return false;
1468 }
1469
Geoff Lange102fee2015-12-10 11:23:30 -05001470 return true;
1471}
1472
1473bool ValidateDebugMessageCallbackKHR(Context *context,
1474 GLDEBUGPROCKHR callback,
1475 const void *userParam)
1476{
1477 if (!context->getExtensions().debug)
1478 {
Jamie Madill437fa652016-05-03 15:13:24 -04001479 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001480 return false;
1481 }
1482
Geoff Lange102fee2015-12-10 11:23:30 -05001483 return true;
1484}
1485
1486bool ValidateGetDebugMessageLogKHR(Context *context,
1487 GLuint count,
1488 GLsizei bufSize,
1489 GLenum *sources,
1490 GLenum *types,
1491 GLuint *ids,
1492 GLenum *severities,
1493 GLsizei *lengths,
1494 GLchar *messageLog)
1495{
1496 if (!context->getExtensions().debug)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001499 return false;
1500 }
1501
Geoff Lang70d0f492015-12-10 17:45:46 -05001502 if (bufSize < 0 && messageLog != nullptr)
1503 {
Jamie Madill437fa652016-05-03 15:13:24 -04001504 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001505 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1506 return false;
1507 }
1508
Geoff Lange102fee2015-12-10 11:23:30 -05001509 return true;
1510}
1511
1512bool ValidatePushDebugGroupKHR(Context *context,
1513 GLenum source,
1514 GLuint id,
1515 GLsizei length,
1516 const GLchar *message)
1517{
1518 if (!context->getExtensions().debug)
1519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001521 return false;
1522 }
1523
Geoff Lang70d0f492015-12-10 17:45:46 -05001524 if (!ValidDebugSource(source, true))
1525 {
Jamie Madill437fa652016-05-03 15:13:24 -04001526 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001527 return false;
1528 }
1529
1530 size_t messageLength = (length < 0) ? strlen(message) : length;
1531 if (messageLength > context->getExtensions().maxDebugMessageLength)
1532 {
Jamie Madill437fa652016-05-03 15:13:24 -04001533 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001534 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1535 return false;
1536 }
1537
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001538 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001539 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1540 {
Jamie Madill437fa652016-05-03 15:13:24 -04001541 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001542 Error(GL_STACK_OVERFLOW,
1543 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1544 return false;
1545 }
1546
Geoff Lange102fee2015-12-10 11:23:30 -05001547 return true;
1548}
1549
1550bool ValidatePopDebugGroupKHR(Context *context)
1551{
1552 if (!context->getExtensions().debug)
1553 {
Jamie Madill437fa652016-05-03 15:13:24 -04001554 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001555 return false;
1556 }
1557
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001558 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001559 if (currentStackSize <= 1)
1560 {
Jamie Madill437fa652016-05-03 15:13:24 -04001561 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001562 return false;
1563 }
1564
1565 return true;
1566}
1567
1568static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1569{
1570 switch (identifier)
1571 {
1572 case GL_BUFFER:
1573 if (context->getBuffer(name) == nullptr)
1574 {
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001576 return false;
1577 }
1578 return true;
1579
1580 case GL_SHADER:
1581 if (context->getShader(name) == nullptr)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001584 return false;
1585 }
1586 return true;
1587
1588 case GL_PROGRAM:
1589 if (context->getProgram(name) == nullptr)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001592 return false;
1593 }
1594 return true;
1595
1596 case GL_VERTEX_ARRAY:
1597 if (context->getVertexArray(name) == nullptr)
1598 {
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001600 return false;
1601 }
1602 return true;
1603
1604 case GL_QUERY:
1605 if (context->getQuery(name) == nullptr)
1606 {
Jamie Madill437fa652016-05-03 15:13:24 -04001607 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001608 return false;
1609 }
1610 return true;
1611
1612 case GL_TRANSFORM_FEEDBACK:
1613 if (context->getTransformFeedback(name) == nullptr)
1614 {
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001616 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1617 return false;
1618 }
1619 return true;
1620
1621 case GL_SAMPLER:
1622 if (context->getSampler(name) == nullptr)
1623 {
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001625 return false;
1626 }
1627 return true;
1628
1629 case GL_TEXTURE:
1630 if (context->getTexture(name) == nullptr)
1631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001633 return false;
1634 }
1635 return true;
1636
1637 case GL_RENDERBUFFER:
1638 if (context->getRenderbuffer(name) == nullptr)
1639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001641 return false;
1642 }
1643 return true;
1644
1645 case GL_FRAMEBUFFER:
1646 if (context->getFramebuffer(name) == nullptr)
1647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 return false;
1650 }
1651 return true;
1652
1653 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001655 return false;
1656 }
Geoff Lange102fee2015-12-10 11:23:30 -05001657}
1658
Martin Radev9d901792016-07-15 15:58:58 +03001659static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1660{
1661 size_t labelLength = 0;
1662
1663 if (length < 0)
1664 {
1665 if (label != nullptr)
1666 {
1667 labelLength = strlen(label);
1668 }
1669 }
1670 else
1671 {
1672 labelLength = static_cast<size_t>(length);
1673 }
1674
1675 if (labelLength > context->getExtensions().maxLabelLength)
1676 {
1677 context->handleError(
1678 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1679 return false;
1680 }
1681
1682 return true;
1683}
1684
Geoff Lange102fee2015-12-10 11:23:30 -05001685bool ValidateObjectLabelKHR(Context *context,
1686 GLenum identifier,
1687 GLuint name,
1688 GLsizei length,
1689 const GLchar *label)
1690{
1691 if (!context->getExtensions().debug)
1692 {
Jamie Madill437fa652016-05-03 15:13:24 -04001693 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001694 return false;
1695 }
1696
Geoff Lang70d0f492015-12-10 17:45:46 -05001697 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1698 {
1699 return false;
1700 }
1701
Martin Radev9d901792016-07-15 15:58:58 +03001702 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001703 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001704 return false;
1705 }
1706
Geoff Lange102fee2015-12-10 11:23:30 -05001707 return true;
1708}
1709
1710bool ValidateGetObjectLabelKHR(Context *context,
1711 GLenum identifier,
1712 GLuint name,
1713 GLsizei bufSize,
1714 GLsizei *length,
1715 GLchar *label)
1716{
1717 if (!context->getExtensions().debug)
1718 {
Jamie Madill437fa652016-05-03 15:13:24 -04001719 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001720 return false;
1721 }
1722
Geoff Lang70d0f492015-12-10 17:45:46 -05001723 if (bufSize < 0)
1724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001726 return false;
1727 }
1728
1729 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1730 {
1731 return false;
1732 }
1733
Martin Radev9d901792016-07-15 15:58:58 +03001734 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001735}
1736
1737static bool ValidateObjectPtrName(Context *context, const void *ptr)
1738{
1739 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 return false;
1743 }
1744
Geoff Lange102fee2015-12-10 11:23:30 -05001745 return true;
1746}
1747
1748bool ValidateObjectPtrLabelKHR(Context *context,
1749 const void *ptr,
1750 GLsizei length,
1751 const GLchar *label)
1752{
1753 if (!context->getExtensions().debug)
1754 {
Jamie Madill437fa652016-05-03 15:13:24 -04001755 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001756 return false;
1757 }
1758
Geoff Lang70d0f492015-12-10 17:45:46 -05001759 if (!ValidateObjectPtrName(context, ptr))
1760 {
1761 return false;
1762 }
1763
Martin Radev9d901792016-07-15 15:58:58 +03001764 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001765 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001766 return false;
1767 }
1768
Geoff Lange102fee2015-12-10 11:23:30 -05001769 return true;
1770}
1771
1772bool ValidateGetObjectPtrLabelKHR(Context *context,
1773 const void *ptr,
1774 GLsizei bufSize,
1775 GLsizei *length,
1776 GLchar *label)
1777{
1778 if (!context->getExtensions().debug)
1779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001781 return false;
1782 }
1783
Geoff Lang70d0f492015-12-10 17:45:46 -05001784 if (bufSize < 0)
1785 {
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001787 return false;
1788 }
1789
1790 if (!ValidateObjectPtrName(context, ptr))
1791 {
1792 return false;
1793 }
1794
Martin Radev9d901792016-07-15 15:58:58 +03001795 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001796}
1797
1798bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1799{
1800 if (!context->getExtensions().debug)
1801 {
Jamie Madill437fa652016-05-03 15:13:24 -04001802 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001803 return false;
1804 }
1805
Geoff Lang70d0f492015-12-10 17:45:46 -05001806 // TODO: represent this in Context::getQueryParameterInfo.
1807 switch (pname)
1808 {
1809 case GL_DEBUG_CALLBACK_FUNCTION:
1810 case GL_DEBUG_CALLBACK_USER_PARAM:
1811 break;
1812
1813 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001815 return false;
1816 }
1817
Geoff Lange102fee2015-12-10 11:23:30 -05001818 return true;
1819}
Jamie Madillc29968b2016-01-20 11:17:23 -05001820
1821bool ValidateBlitFramebufferANGLE(Context *context,
1822 GLint srcX0,
1823 GLint srcY0,
1824 GLint srcX1,
1825 GLint srcY1,
1826 GLint dstX0,
1827 GLint dstY0,
1828 GLint dstX1,
1829 GLint dstY1,
1830 GLbitfield mask,
1831 GLenum filter)
1832{
1833 if (!context->getExtensions().framebufferBlit)
1834 {
Jamie Madill437fa652016-05-03 15:13:24 -04001835 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001836 return false;
1837 }
1838
1839 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1840 {
1841 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001842 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001843 GL_INVALID_OPERATION,
1844 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1845 return false;
1846 }
1847
1848 if (filter == GL_LINEAR)
1849 {
Jamie Madill437fa652016-05-03 15:13:24 -04001850 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001851 return false;
1852 }
1853
Jamie Madill51f40ec2016-06-15 14:06:00 -04001854 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1855 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001856
1857 if (mask & GL_COLOR_BUFFER_BIT)
1858 {
1859 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1860 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1861
1862 if (readColorAttachment && drawColorAttachment)
1863 {
1864 if (!(readColorAttachment->type() == GL_TEXTURE &&
1865 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1866 readColorAttachment->type() != GL_RENDERBUFFER &&
1867 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 return false;
1871 }
1872
Geoff Langa15472a2015-08-11 11:48:03 -04001873 for (size_t drawbufferIdx = 0;
1874 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001875 {
Geoff Langa15472a2015-08-11 11:48:03 -04001876 const FramebufferAttachment *attachment =
1877 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1878 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001879 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 if (!(attachment->type() == GL_TEXTURE &&
1881 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1882 attachment->type() != GL_RENDERBUFFER &&
1883 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1884 {
Jamie Madill437fa652016-05-03 15:13:24 -04001885 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 return false;
1887 }
1888
1889 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001890 if (!Format::SameSized(attachment->getFormat(),
1891 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001892 {
Jamie Madill437fa652016-05-03 15:13:24 -04001893 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001894 return false;
1895 }
1896 }
1897 }
1898
Jamie Madill51f40ec2016-06-15 14:06:00 -04001899 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001900 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1901 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001904 return false;
1905 }
1906 }
1907 }
1908
1909 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1910 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1911 for (size_t i = 0; i < 2; i++)
1912 {
1913 if (mask & masks[i])
1914 {
1915 const FramebufferAttachment *readBuffer =
1916 readFramebuffer->getAttachment(attachments[i]);
1917 const FramebufferAttachment *drawBuffer =
1918 drawFramebuffer->getAttachment(attachments[i]);
1919
1920 if (readBuffer && drawBuffer)
1921 {
1922 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1923 dstX0, dstY0, dstX1, dstY1))
1924 {
1925 // only whole-buffer copies are permitted
1926 ERR(
1927 "Only whole-buffer depth and stencil blits are supported by this "
1928 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001929 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001930 return false;
1931 }
1932
1933 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001936 return false;
1937 }
1938 }
1939 }
1940 }
1941
1942 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1943 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001944}
Jamie Madillc29968b2016-01-20 11:17:23 -05001945
1946bool ValidateClear(ValidationContext *context, GLbitfield mask)
1947{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001948 auto fbo = context->getGLState().getDrawFramebuffer();
1949 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001950 {
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001952 return false;
1953 }
1954
1955 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1956 {
Jamie Madill437fa652016-05-03 15:13:24 -04001957 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001958 return false;
1959 }
1960
1961 return true;
1962}
1963
1964bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1965{
1966 if (!context->getExtensions().drawBuffers)
1967 {
Jamie Madill437fa652016-05-03 15:13:24 -04001968 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001969 return false;
1970 }
1971
1972 return ValidateDrawBuffersBase(context, n, bufs);
1973}
1974
Jamie Madill73a84962016-02-12 09:27:23 -05001975bool ValidateTexImage2D(Context *context,
1976 GLenum target,
1977 GLint level,
1978 GLint internalformat,
1979 GLsizei width,
1980 GLsizei height,
1981 GLint border,
1982 GLenum format,
1983 GLenum type,
1984 const GLvoid *pixels)
1985{
Martin Radev1be913c2016-07-11 17:59:16 +03001986 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001987 {
1988 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001989 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001990 }
1991
Martin Radev1be913c2016-07-11 17:59:16 +03001992 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001993 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001994 0, 0, width, height, 1, border, format, type, -1,
1995 pixels);
1996}
1997
1998bool ValidateTexImage2DRobust(Context *context,
1999 GLenum target,
2000 GLint level,
2001 GLint internalformat,
2002 GLsizei width,
2003 GLsizei height,
2004 GLint border,
2005 GLenum format,
2006 GLenum type,
2007 GLsizei bufSize,
2008 const GLvoid *pixels)
2009{
2010 if (!ValidateRobustEntryPoint(context, bufSize))
2011 {
2012 return false;
2013 }
2014
2015 if (context->getClientMajorVersion() < 3)
2016 {
2017 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2018 0, 0, width, height, border, format, type, bufSize,
2019 pixels);
2020 }
2021
2022 ASSERT(context->getClientMajorVersion() >= 3);
2023 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2024 0, 0, width, height, 1, border, format, type, bufSize,
2025 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002026}
2027
2028bool ValidateTexSubImage2D(Context *context,
2029 GLenum target,
2030 GLint level,
2031 GLint xoffset,
2032 GLint yoffset,
2033 GLsizei width,
2034 GLsizei height,
2035 GLenum format,
2036 GLenum type,
2037 const GLvoid *pixels)
2038{
2039
Martin Radev1be913c2016-07-11 17:59:16 +03002040 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002041 {
2042 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002043 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002044 }
2045
Martin Radev1be913c2016-07-11 17:59:16 +03002046 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002047 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002048 yoffset, 0, width, height, 1, 0, format, type, -1,
2049 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002050}
2051
Geoff Langc52f6f12016-10-14 10:18:00 -04002052bool ValidateTexSubImage2DRobustANGLE(Context *context,
2053 GLenum target,
2054 GLint level,
2055 GLint xoffset,
2056 GLint yoffset,
2057 GLsizei width,
2058 GLsizei height,
2059 GLenum format,
2060 GLenum type,
2061 GLsizei bufSize,
2062 const GLvoid *pixels)
2063{
2064 if (!ValidateRobustEntryPoint(context, bufSize))
2065 {
2066 return false;
2067 }
2068
2069 if (context->getClientMajorVersion() < 3)
2070 {
2071 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2072 yoffset, width, height, 0, format, type, bufSize,
2073 pixels);
2074 }
2075
2076 ASSERT(context->getClientMajorVersion() >= 3);
2077 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2078 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2079 pixels);
2080}
2081
Jamie Madill73a84962016-02-12 09:27:23 -05002082bool ValidateCompressedTexImage2D(Context *context,
2083 GLenum target,
2084 GLint level,
2085 GLenum internalformat,
2086 GLsizei width,
2087 GLsizei height,
2088 GLint border,
2089 GLsizei imageSize,
2090 const GLvoid *data)
2091{
Martin Radev1be913c2016-07-11 17:59:16 +03002092 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002093 {
2094 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002095 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002096 {
2097 return false;
2098 }
2099 }
2100 else
2101 {
Martin Radev1be913c2016-07-11 17:59:16 +03002102 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002103 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002104 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002105 data))
2106 {
2107 return false;
2108 }
2109 }
2110
2111 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002112 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002113 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002114 if (blockSizeOrErr.isError())
2115 {
2116 context->handleError(blockSizeOrErr.getError());
2117 return false;
2118 }
2119
2120 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002121 {
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002123 return false;
2124 }
2125
2126 return true;
2127}
2128
2129bool ValidateCompressedTexSubImage2D(Context *context,
2130 GLenum target,
2131 GLint level,
2132 GLint xoffset,
2133 GLint yoffset,
2134 GLsizei width,
2135 GLsizei height,
2136 GLenum format,
2137 GLsizei imageSize,
2138 const GLvoid *data)
2139{
Martin Radev1be913c2016-07-11 17:59:16 +03002140 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002141 {
2142 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002143 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002144 {
2145 return false;
2146 }
2147 }
2148 else
2149 {
Martin Radev1be913c2016-07-11 17:59:16 +03002150 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002151 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002152 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002153 data))
2154 {
2155 return false;
2156 }
2157 }
2158
2159 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002160 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002161 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002162 if (blockSizeOrErr.isError())
2163 {
2164 context->handleError(blockSizeOrErr.getError());
2165 return false;
2166 }
2167
2168 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002169 {
Jamie Madill437fa652016-05-03 15:13:24 -04002170 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002171 return false;
2172 }
2173
2174 return true;
2175}
2176
Olli Etuaho4f667482016-03-30 15:56:35 +03002177bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2178{
Geoff Lang496c02d2016-10-20 11:38:11 -07002179 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002180}
2181
2182bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2183{
2184 if (!context->getExtensions().mapBuffer)
2185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002187 return false;
2188 }
2189
2190 if (!ValidBufferTarget(context, target))
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002193 return false;
2194 }
2195
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002196 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002197
2198 if (buffer == nullptr)
2199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002201 return false;
2202 }
2203
2204 if (access != GL_WRITE_ONLY_OES)
2205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 return false;
2208 }
2209
2210 if (buffer->isMapped())
2211 {
Jamie Madill437fa652016-05-03 15:13:24 -04002212 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002213 return false;
2214 }
2215
2216 return true;
2217}
2218
2219bool ValidateUnmapBufferOES(Context *context, GLenum target)
2220{
2221 if (!context->getExtensions().mapBuffer)
2222 {
Jamie Madill437fa652016-05-03 15:13:24 -04002223 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002224 return false;
2225 }
2226
2227 return ValidateUnmapBufferBase(context, target);
2228}
2229
2230bool ValidateMapBufferRangeEXT(Context *context,
2231 GLenum target,
2232 GLintptr offset,
2233 GLsizeiptr length,
2234 GLbitfield access)
2235{
2236 if (!context->getExtensions().mapBufferRange)
2237 {
Jamie Madill437fa652016-05-03 15:13:24 -04002238 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002239 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2240 return false;
2241 }
2242
2243 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2244}
2245
2246bool ValidateFlushMappedBufferRangeEXT(Context *context,
2247 GLenum target,
2248 GLintptr offset,
2249 GLsizeiptr length)
2250{
2251 if (!context->getExtensions().mapBufferRange)
2252 {
Jamie Madill437fa652016-05-03 15:13:24 -04002253 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002254 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2255 return false;
2256 }
2257
2258 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2259}
2260
Ian Ewell54f87462016-03-10 13:47:21 -05002261bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2262{
2263 Texture *textureObject = context->getTexture(texture);
2264 if (textureObject && textureObject->getTarget() != target && texture != 0)
2265 {
Jamie Madill437fa652016-05-03 15:13:24 -04002266 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002267 return false;
2268 }
2269
Geoff Langf41a7152016-09-19 15:11:17 -04002270 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2271 !context->isTextureGenerated(texture))
2272 {
2273 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2274 return false;
2275 }
2276
Ian Ewell54f87462016-03-10 13:47:21 -05002277 switch (target)
2278 {
2279 case GL_TEXTURE_2D:
2280 case GL_TEXTURE_CUBE_MAP:
2281 break;
2282
2283 case GL_TEXTURE_3D:
2284 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002285 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002286 {
Jamie Madill437fa652016-05-03 15:13:24 -04002287 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002288 return false;
2289 }
2290 break;
2291 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002292 if (!context->getExtensions().eglImageExternal &&
2293 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002294 {
Jamie Madill437fa652016-05-03 15:13:24 -04002295 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002296 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2297 return false;
2298 }
2299 break;
2300 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002301 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002302 return false;
2303 }
2304
2305 return true;
2306}
2307
Geoff Langd8605522016-04-13 10:19:12 -04002308bool ValidateBindUniformLocationCHROMIUM(Context *context,
2309 GLuint program,
2310 GLint location,
2311 const GLchar *name)
2312{
2313 if (!context->getExtensions().bindUniformLocation)
2314 {
Jamie Madill437fa652016-05-03 15:13:24 -04002315 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002316 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2317 return false;
2318 }
2319
2320 Program *programObject = GetValidProgram(context, program);
2321 if (!programObject)
2322 {
2323 return false;
2324 }
2325
2326 if (location < 0)
2327 {
Jamie Madill437fa652016-05-03 15:13:24 -04002328 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002329 return false;
2330 }
2331
2332 const Caps &caps = context->getCaps();
2333 if (static_cast<size_t>(location) >=
2334 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2335 {
Jamie Madill437fa652016-05-03 15:13:24 -04002336 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002337 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2338 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2339 return false;
2340 }
2341
2342 if (strncmp(name, "gl_", 3) == 0)
2343 {
Jamie Madill437fa652016-05-03 15:13:24 -04002344 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002345 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2346 return false;
2347 }
2348
2349 return true;
2350}
2351
Jamie Madille2e406c2016-06-02 13:04:10 -04002352bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002353{
2354 if (!context->getExtensions().framebufferMixedSamples)
2355 {
2356 context->handleError(
2357 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2358 return false;
2359 }
2360 switch (components)
2361 {
2362 case GL_RGB:
2363 case GL_RGBA:
2364 case GL_ALPHA:
2365 case GL_NONE:
2366 break;
2367 default:
2368 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002369 Error(GL_INVALID_ENUM,
2370 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002371 return false;
2372 }
2373
2374 return true;
2375}
2376
Sami Väisänene45e53b2016-05-25 10:36:04 +03002377// CHROMIUM_path_rendering
2378
2379bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2380{
2381 if (!context->getExtensions().pathRendering)
2382 {
2383 context->handleError(
2384 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2385 return false;
2386 }
2387 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2388 {
2389 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2390 return false;
2391 }
2392 if (matrix == nullptr)
2393 {
2394 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2395 return false;
2396 }
2397 return true;
2398}
2399
2400bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2401{
2402 if (!context->getExtensions().pathRendering)
2403 {
2404 context->handleError(
2405 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2406 return false;
2407 }
2408 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2409 {
2410 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2411 return false;
2412 }
2413 return true;
2414}
2415
2416bool ValidateGenPaths(Context *context, GLsizei range)
2417{
2418 if (!context->getExtensions().pathRendering)
2419 {
2420 context->handleError(
2421 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2422 return false;
2423 }
2424
2425 // range = 0 is undefined in NV_path_rendering.
2426 // we add stricter semantic check here and require a non zero positive range.
2427 if (range <= 0)
2428 {
2429 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2430 return false;
2431 }
2432
2433 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2434 {
2435 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2436 return false;
2437 }
2438
2439 return true;
2440}
2441
2442bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2443{
2444 if (!context->getExtensions().pathRendering)
2445 {
2446 context->handleError(
2447 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2448 return false;
2449 }
2450
2451 // range = 0 is undefined in NV_path_rendering.
2452 // we add stricter semantic check here and require a non zero positive range.
2453 if (range <= 0)
2454 {
2455 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2456 return false;
2457 }
2458
2459 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2460 checkedRange += range;
2461
2462 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2463 {
2464 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2465 return false;
2466 }
2467 return true;
2468}
2469
2470bool ValidatePathCommands(Context *context,
2471 GLuint path,
2472 GLsizei numCommands,
2473 const GLubyte *commands,
2474 GLsizei numCoords,
2475 GLenum coordType,
2476 const void *coords)
2477{
2478 if (!context->getExtensions().pathRendering)
2479 {
2480 context->handleError(
2481 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2482 return false;
2483 }
2484 if (!context->hasPath(path))
2485 {
2486 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2487 return false;
2488 }
2489
2490 if (numCommands < 0)
2491 {
2492 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2493 return false;
2494 }
2495 else if (numCommands > 0)
2496 {
2497 if (!commands)
2498 {
2499 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2500 return false;
2501 }
2502 }
2503
2504 if (numCoords < 0)
2505 {
2506 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2507 return false;
2508 }
2509 else if (numCoords > 0)
2510 {
2511 if (!coords)
2512 {
2513 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2514 return false;
2515 }
2516 }
2517
2518 std::uint32_t coordTypeSize = 0;
2519 switch (coordType)
2520 {
2521 case GL_BYTE:
2522 coordTypeSize = sizeof(GLbyte);
2523 break;
2524
2525 case GL_UNSIGNED_BYTE:
2526 coordTypeSize = sizeof(GLubyte);
2527 break;
2528
2529 case GL_SHORT:
2530 coordTypeSize = sizeof(GLshort);
2531 break;
2532
2533 case GL_UNSIGNED_SHORT:
2534 coordTypeSize = sizeof(GLushort);
2535 break;
2536
2537 case GL_FLOAT:
2538 coordTypeSize = sizeof(GLfloat);
2539 break;
2540
2541 default:
2542 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2543 return false;
2544 }
2545
2546 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2547 checkedSize += (coordTypeSize * numCoords);
2548 if (!checkedSize.IsValid())
2549 {
2550 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2551 return false;
2552 }
2553
2554 // early return skips command data validation when it doesn't exist.
2555 if (!commands)
2556 return true;
2557
2558 GLsizei expectedNumCoords = 0;
2559 for (GLsizei i = 0; i < numCommands; ++i)
2560 {
2561 switch (commands[i])
2562 {
2563 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2564 break;
2565 case GL_MOVE_TO_CHROMIUM:
2566 case GL_LINE_TO_CHROMIUM:
2567 expectedNumCoords += 2;
2568 break;
2569 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2570 expectedNumCoords += 4;
2571 break;
2572 case GL_CUBIC_CURVE_TO_CHROMIUM:
2573 expectedNumCoords += 6;
2574 break;
2575 case GL_CONIC_CURVE_TO_CHROMIUM:
2576 expectedNumCoords += 5;
2577 break;
2578 default:
2579 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2580 return false;
2581 }
2582 }
2583 if (expectedNumCoords != numCoords)
2584 {
2585 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2586 return false;
2587 }
2588
2589 return true;
2590}
2591
2592bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2593{
2594 if (!context->getExtensions().pathRendering)
2595 {
2596 context->handleError(
2597 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2598 return false;
2599 }
2600 if (!context->hasPath(path))
2601 {
2602 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2603 return false;
2604 }
2605
2606 switch (pname)
2607 {
2608 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2609 if (value < 0.0f)
2610 {
2611 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2612 return false;
2613 }
2614 break;
2615 case GL_PATH_END_CAPS_CHROMIUM:
2616 switch (static_cast<GLenum>(value))
2617 {
2618 case GL_FLAT_CHROMIUM:
2619 case GL_SQUARE_CHROMIUM:
2620 case GL_ROUND_CHROMIUM:
2621 break;
2622 default:
2623 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2624 return false;
2625 }
2626 break;
2627 case GL_PATH_JOIN_STYLE_CHROMIUM:
2628 switch (static_cast<GLenum>(value))
2629 {
2630 case GL_MITER_REVERT_CHROMIUM:
2631 case GL_BEVEL_CHROMIUM:
2632 case GL_ROUND_CHROMIUM:
2633 break;
2634 default:
2635 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2636 return false;
2637 }
2638 case GL_PATH_MITER_LIMIT_CHROMIUM:
2639 if (value < 0.0f)
2640 {
2641 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2642 return false;
2643 }
2644 break;
2645
2646 case GL_PATH_STROKE_BOUND_CHROMIUM:
2647 // no errors, only clamping.
2648 break;
2649
2650 default:
2651 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2652 return false;
2653 }
2654 return true;
2655}
2656
2657bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2658{
2659 if (!context->getExtensions().pathRendering)
2660 {
2661 context->handleError(
2662 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2663 return false;
2664 }
2665
2666 if (!context->hasPath(path))
2667 {
2668 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2669 return false;
2670 }
2671 if (!value)
2672 {
2673 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2674 return false;
2675 }
2676
2677 switch (pname)
2678 {
2679 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2680 case GL_PATH_END_CAPS_CHROMIUM:
2681 case GL_PATH_JOIN_STYLE_CHROMIUM:
2682 case GL_PATH_MITER_LIMIT_CHROMIUM:
2683 case GL_PATH_STROKE_BOUND_CHROMIUM:
2684 break;
2685
2686 default:
2687 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2688 return false;
2689 }
2690
2691 return true;
2692}
2693
2694bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2695{
2696 if (!context->getExtensions().pathRendering)
2697 {
2698 context->handleError(
2699 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2700 return false;
2701 }
2702
2703 switch (func)
2704 {
2705 case GL_NEVER:
2706 case GL_ALWAYS:
2707 case GL_LESS:
2708 case GL_LEQUAL:
2709 case GL_EQUAL:
2710 case GL_GEQUAL:
2711 case GL_GREATER:
2712 case GL_NOTEQUAL:
2713 break;
2714 default:
2715 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2716 return false;
2717 }
2718
2719 return true;
2720}
2721
2722// Note that the spec specifies that for the path drawing commands
2723// if the path object is not an existing path object the command
2724// does nothing and no error is generated.
2725// However if the path object exists but has not been specified any
2726// commands then an error is generated.
2727
2728bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2729{
2730 if (!context->getExtensions().pathRendering)
2731 {
2732 context->handleError(
2733 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2734 return false;
2735 }
2736 if (context->hasPath(path) && !context->hasPathData(path))
2737 {
2738 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2739 return false;
2740 }
2741
2742 switch (fillMode)
2743 {
2744 case GL_COUNT_UP_CHROMIUM:
2745 case GL_COUNT_DOWN_CHROMIUM:
2746 break;
2747 default:
2748 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2749 return false;
2750 }
2751
2752 if (!isPow2(mask + 1))
2753 {
2754 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2755 return false;
2756 }
2757
2758 return true;
2759}
2760
2761bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2762{
2763 if (!context->getExtensions().pathRendering)
2764 {
2765 context->handleError(
2766 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2767 return false;
2768 }
2769 if (context->hasPath(path) && !context->hasPathData(path))
2770 {
2771 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2772 return false;
2773 }
2774
2775 return true;
2776}
2777
2778bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2779{
2780 if (!context->getExtensions().pathRendering)
2781 {
2782 context->handleError(
2783 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2784 return false;
2785 }
2786 if (context->hasPath(path) && !context->hasPathData(path))
2787 {
2788 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2789 return false;
2790 }
2791
2792 switch (coverMode)
2793 {
2794 case GL_CONVEX_HULL_CHROMIUM:
2795 case GL_BOUNDING_BOX_CHROMIUM:
2796 break;
2797 default:
2798 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2799 return false;
2800 }
2801 return true;
2802}
2803
2804bool ValidateStencilThenCoverFillPath(Context *context,
2805 GLuint path,
2806 GLenum fillMode,
2807 GLuint mask,
2808 GLenum coverMode)
2809{
2810 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2811 ValidateCoverPath(context, path, coverMode);
2812}
2813
2814bool ValidateStencilThenCoverStrokePath(Context *context,
2815 GLuint path,
2816 GLint reference,
2817 GLuint mask,
2818 GLenum coverMode)
2819{
2820 return ValidateStencilStrokePath(context, path, reference, mask) &&
2821 ValidateCoverPath(context, path, coverMode);
2822}
2823
2824bool ValidateIsPath(Context *context)
2825{
2826 if (!context->getExtensions().pathRendering)
2827 {
2828 context->handleError(
2829 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2830 return false;
2831 }
2832 return true;
2833}
2834
Sami Väisänend59ca052016-06-21 16:10:00 +03002835bool ValidateCoverFillPathInstanced(Context *context,
2836 GLsizei numPaths,
2837 GLenum pathNameType,
2838 const void *paths,
2839 GLuint pathBase,
2840 GLenum coverMode,
2841 GLenum transformType,
2842 const GLfloat *transformValues)
2843{
2844 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2845 transformType, transformValues))
2846 return false;
2847
2848 switch (coverMode)
2849 {
2850 case GL_CONVEX_HULL_CHROMIUM:
2851 case GL_BOUNDING_BOX_CHROMIUM:
2852 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2853 break;
2854 default:
2855 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2856 return false;
2857 }
2858
2859 return true;
2860}
2861
2862bool ValidateCoverStrokePathInstanced(Context *context,
2863 GLsizei numPaths,
2864 GLenum pathNameType,
2865 const void *paths,
2866 GLuint pathBase,
2867 GLenum coverMode,
2868 GLenum transformType,
2869 const GLfloat *transformValues)
2870{
2871 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2872 transformType, transformValues))
2873 return false;
2874
2875 switch (coverMode)
2876 {
2877 case GL_CONVEX_HULL_CHROMIUM:
2878 case GL_BOUNDING_BOX_CHROMIUM:
2879 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2880 break;
2881 default:
2882 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2883 return false;
2884 }
2885
2886 return true;
2887}
2888
2889bool ValidateStencilFillPathInstanced(Context *context,
2890 GLsizei numPaths,
2891 GLenum pathNameType,
2892 const void *paths,
2893 GLuint pathBase,
2894 GLenum fillMode,
2895 GLuint mask,
2896 GLenum transformType,
2897 const GLfloat *transformValues)
2898{
2899
2900 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2901 transformType, transformValues))
2902 return false;
2903
2904 switch (fillMode)
2905 {
2906 case GL_COUNT_UP_CHROMIUM:
2907 case GL_COUNT_DOWN_CHROMIUM:
2908 break;
2909 default:
2910 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2911 return false;
2912 }
2913 if (!isPow2(mask + 1))
2914 {
2915 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2916 return false;
2917 }
2918 return true;
2919}
2920
2921bool ValidateStencilStrokePathInstanced(Context *context,
2922 GLsizei numPaths,
2923 GLenum pathNameType,
2924 const void *paths,
2925 GLuint pathBase,
2926 GLint reference,
2927 GLuint mask,
2928 GLenum transformType,
2929 const GLfloat *transformValues)
2930{
2931 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2932 transformType, transformValues))
2933 return false;
2934
2935 // no more validation here.
2936
2937 return true;
2938}
2939
2940bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2941 GLsizei numPaths,
2942 GLenum pathNameType,
2943 const void *paths,
2944 GLuint pathBase,
2945 GLenum fillMode,
2946 GLuint mask,
2947 GLenum coverMode,
2948 GLenum transformType,
2949 const GLfloat *transformValues)
2950{
2951 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2952 transformType, transformValues))
2953 return false;
2954
2955 switch (coverMode)
2956 {
2957 case GL_CONVEX_HULL_CHROMIUM:
2958 case GL_BOUNDING_BOX_CHROMIUM:
2959 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2960 break;
2961 default:
2962 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2963 return false;
2964 }
2965
2966 switch (fillMode)
2967 {
2968 case GL_COUNT_UP_CHROMIUM:
2969 case GL_COUNT_DOWN_CHROMIUM:
2970 break;
2971 default:
2972 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2973 return false;
2974 }
2975 if (!isPow2(mask + 1))
2976 {
2977 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2978 return false;
2979 }
2980
2981 return true;
2982}
2983
2984bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2985 GLsizei numPaths,
2986 GLenum pathNameType,
2987 const void *paths,
2988 GLuint pathBase,
2989 GLint reference,
2990 GLuint mask,
2991 GLenum coverMode,
2992 GLenum transformType,
2993 const GLfloat *transformValues)
2994{
2995 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2996 transformType, transformValues))
2997 return false;
2998
2999 switch (coverMode)
3000 {
3001 case GL_CONVEX_HULL_CHROMIUM:
3002 case GL_BOUNDING_BOX_CHROMIUM:
3003 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3004 break;
3005 default:
3006 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3007 return false;
3008 }
3009
3010 return true;
3011}
3012
Sami Väisänen46eaa942016-06-29 10:26:37 +03003013bool ValidateBindFragmentInputLocation(Context *context,
3014 GLuint program,
3015 GLint location,
3016 const GLchar *name)
3017{
3018 if (!context->getExtensions().pathRendering)
3019 {
3020 context->handleError(
3021 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3022 return false;
3023 }
3024
3025 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3026 if (location >= MaxLocation)
3027 {
3028 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3029 return false;
3030 }
3031
3032 const auto *programObject = context->getProgram(program);
3033 if (!programObject)
3034 {
3035 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3036 return false;
3037 }
3038
3039 if (!name)
3040 {
3041 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3042 return false;
3043 }
3044
3045 if (angle::BeginsWith(name, "gl_"))
3046 {
3047 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3048 return false;
3049 }
3050
3051 return true;
3052}
3053
3054bool ValidateProgramPathFragmentInputGen(Context *context,
3055 GLuint program,
3056 GLint location,
3057 GLenum genMode,
3058 GLint components,
3059 const GLfloat *coeffs)
3060{
3061 if (!context->getExtensions().pathRendering)
3062 {
3063 context->handleError(
3064 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3065 return false;
3066 }
3067
3068 const auto *programObject = context->getProgram(program);
3069 if (!programObject || programObject->isFlaggedForDeletion())
3070 {
3071 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3072 return false;
3073 }
3074
3075 if (!programObject->isLinked())
3076 {
3077 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3078 return false;
3079 }
3080
3081 switch (genMode)
3082 {
3083 case GL_NONE:
3084 if (components != 0)
3085 {
3086 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3087 return false;
3088 }
3089 break;
3090
3091 case GL_OBJECT_LINEAR_CHROMIUM:
3092 case GL_EYE_LINEAR_CHROMIUM:
3093 case GL_CONSTANT_CHROMIUM:
3094 if (components < 1 || components > 4)
3095 {
3096 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3097 return false;
3098 }
3099 if (!coeffs)
3100 {
3101 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3102 return false;
3103 }
3104 break;
3105
3106 default:
3107 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3108 return false;
3109 }
3110
3111 // If the location is -1 then the command is silently ignored
3112 // and no further validation is needed.
3113 if (location == -1)
3114 return true;
3115
3116 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3117
3118 if (!binding.valid)
3119 {
3120 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3121 return false;
3122 }
3123
3124 if (binding.type != GL_NONE)
3125 {
3126 GLint expectedComponents = 0;
3127 switch (binding.type)
3128 {
3129 case GL_FLOAT:
3130 expectedComponents = 1;
3131 break;
3132 case GL_FLOAT_VEC2:
3133 expectedComponents = 2;
3134 break;
3135 case GL_FLOAT_VEC3:
3136 expectedComponents = 3;
3137 break;
3138 case GL_FLOAT_VEC4:
3139 expectedComponents = 4;
3140 break;
3141 default:
3142 context->handleError(Error(GL_INVALID_OPERATION,
3143 "Fragment input type is not a floating point scalar or vector."));
3144 return false;
3145 }
3146 if (expectedComponents != components && genMode != GL_NONE)
3147 {
3148 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3149 return false;
3150 }
3151 }
3152 return true;
3153}
3154
Geoff Lang97073d12016-04-20 10:42:34 -07003155bool ValidateCopyTextureCHROMIUM(Context *context,
3156 GLuint sourceId,
3157 GLuint destId,
3158 GLint internalFormat,
3159 GLenum destType,
3160 GLboolean unpackFlipY,
3161 GLboolean unpackPremultiplyAlpha,
3162 GLboolean unpackUnmultiplyAlpha)
3163{
3164 if (!context->getExtensions().copyTexture)
3165 {
3166 context->handleError(
3167 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3168 return false;
3169 }
3170
3171 const gl::Texture *source = context->getTexture(sourceId);
3172 if (source == nullptr)
3173 {
3174 context->handleError(
3175 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3176 return false;
3177 }
3178
3179 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3180 {
3181 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3182 return false;
3183 }
3184
3185 GLenum sourceTarget = source->getTarget();
3186 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3187 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3188 {
3189 context->handleError(
3190 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3191 return false;
3192 }
3193
3194 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3195 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3196 {
3197 context->handleError(
3198 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3199 return false;
3200 }
3201
3202 const gl::Texture *dest = context->getTexture(destId);
3203 if (dest == nullptr)
3204 {
3205 context->handleError(
3206 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3207 return false;
3208 }
3209
3210 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3211 {
3212 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3213 return false;
3214 }
3215
3216 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3217 {
3218 context->handleError(
3219 Error(GL_INVALID_OPERATION,
3220 "Destination internal format and type combination is not valid."));
3221 return false;
3222 }
3223
3224 if (dest->getImmutableFormat())
3225 {
3226 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3227 return false;
3228 }
3229
3230 return true;
3231}
3232
3233bool ValidateCopySubTextureCHROMIUM(Context *context,
3234 GLuint sourceId,
3235 GLuint destId,
3236 GLint xoffset,
3237 GLint yoffset,
3238 GLint x,
3239 GLint y,
3240 GLsizei width,
3241 GLsizei height,
3242 GLboolean unpackFlipY,
3243 GLboolean unpackPremultiplyAlpha,
3244 GLboolean unpackUnmultiplyAlpha)
3245{
3246 if (!context->getExtensions().copyTexture)
3247 {
3248 context->handleError(
3249 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3250 return false;
3251 }
3252
3253 const gl::Texture *source = context->getTexture(sourceId);
3254 if (source == nullptr)
3255 {
3256 context->handleError(
3257 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3258 return false;
3259 }
3260
3261 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3262 {
3263 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3264 return false;
3265 }
3266
3267 GLenum sourceTarget = source->getTarget();
3268 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3269 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3270 {
3271 context->handleError(
3272 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3273 return false;
3274 }
3275
3276 if (x < 0 || y < 0)
3277 {
3278 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3279 return false;
3280 }
3281
3282 if (width < 0 || height < 0)
3283 {
3284 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3285 return false;
3286 }
3287
3288 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3289 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3290 {
3291 context->handleError(
3292 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3293 return false;
3294 }
3295
3296 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3297 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3298 {
3299 context->handleError(
3300 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3301 return false;
3302 }
3303
3304 const gl::Texture *dest = context->getTexture(destId);
3305 if (dest == nullptr)
3306 {
3307 context->handleError(
3308 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3309 return false;
3310 }
3311
3312 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3313 {
3314 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3315 return false;
3316 }
3317
3318 GLenum destTarget = dest->getTarget();
3319 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3320 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3321 {
3322 context->handleError(
3323 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3324 return false;
3325 }
3326
3327 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3328 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3329 {
3330 context->handleError(
3331 Error(GL_INVALID_OPERATION,
3332 "Destination internal format and type combination is not valid."));
3333 return false;
3334 }
3335
3336 if (xoffset < 0 || yoffset < 0)
3337 {
3338 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3339 return false;
3340 }
3341
3342 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3343 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3344 {
3345 context->handleError(
3346 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3347 return false;
3348 }
3349
3350 return true;
3351}
3352
Geoff Lang47110bf2016-04-20 11:13:22 -07003353bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3354{
3355 if (!context->getExtensions().copyCompressedTexture)
3356 {
3357 context->handleError(Error(GL_INVALID_OPERATION,
3358 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3359 return false;
3360 }
3361
3362 const gl::Texture *source = context->getTexture(sourceId);
3363 if (source == nullptr)
3364 {
3365 context->handleError(
3366 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3367 return false;
3368 }
3369
3370 if (source->getTarget() != GL_TEXTURE_2D)
3371 {
3372 context->handleError(
3373 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3374 return false;
3375 }
3376
3377 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3378 {
3379 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3380 return false;
3381 }
3382
3383 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3384 if (!sourceFormat.info->compressed)
3385 {
3386 context->handleError(
3387 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3388 return false;
3389 }
3390
3391 const gl::Texture *dest = context->getTexture(destId);
3392 if (dest == nullptr)
3393 {
3394 context->handleError(
3395 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3396 return false;
3397 }
3398
3399 if (dest->getTarget() != GL_TEXTURE_2D)
3400 {
3401 context->handleError(
3402 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3403 return false;
3404 }
3405
3406 if (dest->getImmutableFormat())
3407 {
3408 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3409 return false;
3410 }
3411
3412 return true;
3413}
3414
Martin Radev4c4c8e72016-08-04 12:25:34 +03003415bool ValidateCreateShader(Context *context, GLenum type)
3416{
3417 switch (type)
3418 {
3419 case GL_VERTEX_SHADER:
3420 case GL_FRAGMENT_SHADER:
3421 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003422
Martin Radev4c4c8e72016-08-04 12:25:34 +03003423 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003424 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003425 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003426 context->handleError(
3427 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3428 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003429 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003430 break;
3431
Martin Radev4c4c8e72016-08-04 12:25:34 +03003432 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003433 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003434 return false;
3435 }
Jamie Madill29639852016-09-02 15:00:09 -04003436
3437 return true;
3438}
3439
3440bool ValidateBufferData(ValidationContext *context,
3441 GLenum target,
3442 GLsizeiptr size,
3443 const GLvoid *data,
3444 GLenum usage)
3445{
3446 if (size < 0)
3447 {
3448 context->handleError(Error(GL_INVALID_VALUE));
3449 return false;
3450 }
3451
3452 switch (usage)
3453 {
3454 case GL_STREAM_DRAW:
3455 case GL_STATIC_DRAW:
3456 case GL_DYNAMIC_DRAW:
3457 break;
3458
3459 case GL_STREAM_READ:
3460 case GL_STREAM_COPY:
3461 case GL_STATIC_READ:
3462 case GL_STATIC_COPY:
3463 case GL_DYNAMIC_READ:
3464 case GL_DYNAMIC_COPY:
3465 if (context->getClientMajorVersion() < 3)
3466 {
3467 context->handleError(Error(GL_INVALID_ENUM));
3468 return false;
3469 }
3470 break;
3471
3472 default:
3473 context->handleError(Error(GL_INVALID_ENUM));
3474 return false;
3475 }
3476
3477 if (!ValidBufferTarget(context, target))
3478 {
3479 context->handleError(Error(GL_INVALID_ENUM));
3480 return false;
3481 }
3482
3483 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3484
3485 if (!buffer)
3486 {
3487 context->handleError(Error(GL_INVALID_OPERATION));
3488 return false;
3489 }
3490
3491 return true;
3492}
3493
3494bool ValidateBufferSubData(ValidationContext *context,
3495 GLenum target,
3496 GLintptr offset,
3497 GLsizeiptr size,
3498 const GLvoid *data)
3499{
3500 if (size < 0 || offset < 0)
3501 {
3502 context->handleError(Error(GL_INVALID_VALUE));
3503 return false;
3504 }
3505
3506 if (!ValidBufferTarget(context, target))
3507 {
3508 context->handleError(Error(GL_INVALID_ENUM));
3509 return false;
3510 }
3511
3512 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3513
3514 if (!buffer)
3515 {
3516 context->handleError(Error(GL_INVALID_OPERATION));
3517 return false;
3518 }
3519
3520 if (buffer->isMapped())
3521 {
3522 context->handleError(Error(GL_INVALID_OPERATION));
3523 return false;
3524 }
3525
3526 // Check for possible overflow of size + offset
3527 angle::CheckedNumeric<size_t> checkedSize(size);
3528 checkedSize += offset;
3529 if (!checkedSize.IsValid())
3530 {
3531 context->handleError(Error(GL_OUT_OF_MEMORY));
3532 return false;
3533 }
3534
3535 if (size + offset > buffer->getSize())
3536 {
3537 context->handleError(Error(GL_INVALID_VALUE));
3538 return false;
3539 }
3540
Martin Radev4c4c8e72016-08-04 12:25:34 +03003541 return true;
3542}
3543
Geoff Langc287ea62016-09-16 14:46:51 -04003544bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3545{
3546 if (!context->getExtensions().webglCompatibility)
3547 {
3548 context->handleError(
3549 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3550 return false;
3551 }
3552
3553 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3554 auto extension = extensionInfos.find(name);
3555 if (extension == extensionInfos.end() || !extension->second.Enableable)
3556 {
3557 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3558 return false;
3559 }
3560
3561 return true;
3562}
3563
Jamie Madillef300b12016-10-07 15:12:09 -04003564bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3565{
3566 if (texture < GL_TEXTURE0 ||
3567 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3568 {
3569 context->handleError(Error(GL_INVALID_ENUM));
3570 return false;
3571 }
3572
3573 return true;
3574}
3575
3576bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3577{
3578 Program *programObject = GetValidProgram(context, program);
3579 if (!programObject)
3580 {
3581 return false;
3582 }
3583
3584 Shader *shaderObject = GetValidShader(context, shader);
3585 if (!shaderObject)
3586 {
3587 return false;
3588 }
3589
3590 switch (shaderObject->getType())
3591 {
3592 case GL_VERTEX_SHADER:
3593 {
3594 if (programObject->getAttachedVertexShader())
3595 {
3596 context->handleError(Error(GL_INVALID_OPERATION));
3597 return false;
3598 }
3599 break;
3600 }
3601 case GL_FRAGMENT_SHADER:
3602 {
3603 if (programObject->getAttachedFragmentShader())
3604 {
3605 context->handleError(Error(GL_INVALID_OPERATION));
3606 return false;
3607 }
3608 break;
3609 }
3610 case GL_COMPUTE_SHADER:
3611 {
3612 if (programObject->getAttachedComputeShader())
3613 {
3614 context->handleError(Error(GL_INVALID_OPERATION));
3615 return false;
3616 }
3617 break;
3618 }
3619 default:
3620 UNREACHABLE();
3621 break;
3622 }
3623
3624 return true;
3625}
3626
Jamie Madill01a80ee2016-11-07 12:06:18 -05003627bool ValidateBindAttribLocation(ValidationContext *context,
3628 GLuint program,
3629 GLuint index,
3630 const GLchar *name)
3631{
3632 if (index >= MAX_VERTEX_ATTRIBS)
3633 {
3634 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3635 return false;
3636 }
3637
3638 if (strncmp(name, "gl_", 3) == 0)
3639 {
3640 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3641 return false;
3642 }
3643
3644 return GetValidProgram(context, program) != nullptr;
3645}
3646
3647bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3648{
3649 if (!ValidBufferTarget(context, target))
3650 {
3651 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3652 return false;
3653 }
3654
3655 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3656 !context->isBufferGenerated(buffer))
3657 {
3658 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3659 return false;
3660 }
3661
3662 return true;
3663}
3664
3665bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3666{
3667 if (!ValidFramebufferTarget(target))
3668 {
3669 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3670 return false;
3671 }
3672
3673 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3674 !context->isFramebufferGenerated(framebuffer))
3675 {
3676 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3677 return false;
3678 }
3679
3680 return true;
3681}
3682
3683bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3684{
3685 if (target != GL_RENDERBUFFER)
3686 {
3687 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3688 return false;
3689 }
3690
3691 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3692 !context->isRenderbufferGenerated(renderbuffer))
3693 {
3694 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3695 return false;
3696 }
3697
3698 return true;
3699}
3700
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003701static bool ValidBlendEquationMode(GLenum mode)
3702{
3703 switch (mode)
3704 {
3705 case GL_FUNC_ADD:
3706 case GL_FUNC_SUBTRACT:
3707 case GL_FUNC_REVERSE_SUBTRACT:
3708 case GL_MIN:
3709 case GL_MAX:
3710 return true;
3711
3712 default:
3713 return false;
3714 }
3715}
3716
3717bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3718{
3719 if (!ValidBlendEquationMode(mode))
3720 {
3721 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3722 return false;
3723 }
3724
3725 return true;
3726}
3727
3728bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3729{
3730 if (!ValidBlendEquationMode(modeRGB))
3731 {
3732 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3733 return false;
3734 }
3735
3736 if (!ValidBlendEquationMode(modeAlpha))
3737 {
3738 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3739 return false;
3740 }
3741
3742 return true;
3743}
3744
3745bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3746{
3747 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3748}
3749
3750static bool ValidSrcBlendFunc(GLenum srcBlend)
3751{
3752 switch (srcBlend)
3753 {
3754 case GL_ZERO:
3755 case GL_ONE:
3756 case GL_SRC_COLOR:
3757 case GL_ONE_MINUS_SRC_COLOR:
3758 case GL_DST_COLOR:
3759 case GL_ONE_MINUS_DST_COLOR:
3760 case GL_SRC_ALPHA:
3761 case GL_ONE_MINUS_SRC_ALPHA:
3762 case GL_DST_ALPHA:
3763 case GL_ONE_MINUS_DST_ALPHA:
3764 case GL_CONSTANT_COLOR:
3765 case GL_ONE_MINUS_CONSTANT_COLOR:
3766 case GL_CONSTANT_ALPHA:
3767 case GL_ONE_MINUS_CONSTANT_ALPHA:
3768 case GL_SRC_ALPHA_SATURATE:
3769 return true;
3770
3771 default:
3772 return false;
3773 }
3774}
3775
3776static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3777{
3778 switch (dstBlend)
3779 {
3780 case GL_ZERO:
3781 case GL_ONE:
3782 case GL_SRC_COLOR:
3783 case GL_ONE_MINUS_SRC_COLOR:
3784 case GL_DST_COLOR:
3785 case GL_ONE_MINUS_DST_COLOR:
3786 case GL_SRC_ALPHA:
3787 case GL_ONE_MINUS_SRC_ALPHA:
3788 case GL_DST_ALPHA:
3789 case GL_ONE_MINUS_DST_ALPHA:
3790 case GL_CONSTANT_COLOR:
3791 case GL_ONE_MINUS_CONSTANT_COLOR:
3792 case GL_CONSTANT_ALPHA:
3793 case GL_ONE_MINUS_CONSTANT_ALPHA:
3794 return true;
3795
3796 case GL_SRC_ALPHA_SATURATE:
3797 return (contextMajorVersion >= 3);
3798
3799 default:
3800 return false;
3801 }
3802}
3803
3804bool ValidateBlendFuncSeparate(ValidationContext *context,
3805 GLenum srcRGB,
3806 GLenum dstRGB,
3807 GLenum srcAlpha,
3808 GLenum dstAlpha)
3809{
3810 if (!ValidSrcBlendFunc(srcRGB))
3811 {
3812 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3813 return false;
3814 }
3815
3816 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3817 {
3818 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3819 return false;
3820 }
3821
3822 if (!ValidSrcBlendFunc(srcAlpha))
3823 {
3824 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3825 return false;
3826 }
3827
3828 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3829 {
3830 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3831 return false;
3832 }
3833
3834 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3835 {
3836 bool constantColorUsed =
3837 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3838 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3839
3840 bool constantAlphaUsed =
3841 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3842 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3843
3844 if (constantColorUsed && constantAlphaUsed)
3845 {
3846 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3847 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3848 "implementation.");
3849 context->handleError(Error(GL_INVALID_OPERATION,
3850 "Simultaneous use of "
3851 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3852 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3853 "supported by this implementation."));
3854 return false;
3855 }
3856 }
3857
3858 return true;
3859}
3860
Jamie Madillc29968b2016-01-20 11:17:23 -05003861} // namespace gl