blob: 94679b8c3d498715493865719554dcae83720d0a [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;
Geoff Lang3b573612016-10-31 14:08:10 -04002291
2292 case GL_TEXTURE_2D_MULTISAMPLE:
2293 if (context->getClientVersion() < Version(3, 1))
2294 {
2295 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2296 return false;
2297 }
2298 UNIMPLEMENTED();
2299 break;
2300
Ian Ewell54f87462016-03-10 13:47:21 -05002301 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002302 if (!context->getExtensions().eglImageExternal &&
2303 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002304 {
Jamie Madill437fa652016-05-03 15:13:24 -04002305 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002306 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2307 return false;
2308 }
2309 break;
2310 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002311 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002312 return false;
2313 }
2314
2315 return true;
2316}
2317
Geoff Langd8605522016-04-13 10:19:12 -04002318bool ValidateBindUniformLocationCHROMIUM(Context *context,
2319 GLuint program,
2320 GLint location,
2321 const GLchar *name)
2322{
2323 if (!context->getExtensions().bindUniformLocation)
2324 {
Jamie Madill437fa652016-05-03 15:13:24 -04002325 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002326 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2327 return false;
2328 }
2329
2330 Program *programObject = GetValidProgram(context, program);
2331 if (!programObject)
2332 {
2333 return false;
2334 }
2335
2336 if (location < 0)
2337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002339 return false;
2340 }
2341
2342 const Caps &caps = context->getCaps();
2343 if (static_cast<size_t>(location) >=
2344 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2345 {
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002347 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2348 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2349 return false;
2350 }
2351
2352 if (strncmp(name, "gl_", 3) == 0)
2353 {
Jamie Madill437fa652016-05-03 15:13:24 -04002354 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002355 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2356 return false;
2357 }
2358
2359 return true;
2360}
2361
Jamie Madille2e406c2016-06-02 13:04:10 -04002362bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002363{
2364 if (!context->getExtensions().framebufferMixedSamples)
2365 {
2366 context->handleError(
2367 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2368 return false;
2369 }
2370 switch (components)
2371 {
2372 case GL_RGB:
2373 case GL_RGBA:
2374 case GL_ALPHA:
2375 case GL_NONE:
2376 break;
2377 default:
2378 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002379 Error(GL_INVALID_ENUM,
2380 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002381 return false;
2382 }
2383
2384 return true;
2385}
2386
Sami Väisänene45e53b2016-05-25 10:36:04 +03002387// CHROMIUM_path_rendering
2388
2389bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2390{
2391 if (!context->getExtensions().pathRendering)
2392 {
2393 context->handleError(
2394 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2395 return false;
2396 }
2397 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2398 {
2399 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2400 return false;
2401 }
2402 if (matrix == nullptr)
2403 {
2404 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2405 return false;
2406 }
2407 return true;
2408}
2409
2410bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2411{
2412 if (!context->getExtensions().pathRendering)
2413 {
2414 context->handleError(
2415 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2416 return false;
2417 }
2418 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2419 {
2420 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2421 return false;
2422 }
2423 return true;
2424}
2425
2426bool ValidateGenPaths(Context *context, GLsizei range)
2427{
2428 if (!context->getExtensions().pathRendering)
2429 {
2430 context->handleError(
2431 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2432 return false;
2433 }
2434
2435 // range = 0 is undefined in NV_path_rendering.
2436 // we add stricter semantic check here and require a non zero positive range.
2437 if (range <= 0)
2438 {
2439 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2440 return false;
2441 }
2442
2443 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2444 {
2445 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2446 return false;
2447 }
2448
2449 return true;
2450}
2451
2452bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2453{
2454 if (!context->getExtensions().pathRendering)
2455 {
2456 context->handleError(
2457 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2458 return false;
2459 }
2460
2461 // range = 0 is undefined in NV_path_rendering.
2462 // we add stricter semantic check here and require a non zero positive range.
2463 if (range <= 0)
2464 {
2465 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2466 return false;
2467 }
2468
2469 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2470 checkedRange += range;
2471
2472 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2473 {
2474 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2475 return false;
2476 }
2477 return true;
2478}
2479
2480bool ValidatePathCommands(Context *context,
2481 GLuint path,
2482 GLsizei numCommands,
2483 const GLubyte *commands,
2484 GLsizei numCoords,
2485 GLenum coordType,
2486 const void *coords)
2487{
2488 if (!context->getExtensions().pathRendering)
2489 {
2490 context->handleError(
2491 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2492 return false;
2493 }
2494 if (!context->hasPath(path))
2495 {
2496 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2497 return false;
2498 }
2499
2500 if (numCommands < 0)
2501 {
2502 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2503 return false;
2504 }
2505 else if (numCommands > 0)
2506 {
2507 if (!commands)
2508 {
2509 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2510 return false;
2511 }
2512 }
2513
2514 if (numCoords < 0)
2515 {
2516 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2517 return false;
2518 }
2519 else if (numCoords > 0)
2520 {
2521 if (!coords)
2522 {
2523 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2524 return false;
2525 }
2526 }
2527
2528 std::uint32_t coordTypeSize = 0;
2529 switch (coordType)
2530 {
2531 case GL_BYTE:
2532 coordTypeSize = sizeof(GLbyte);
2533 break;
2534
2535 case GL_UNSIGNED_BYTE:
2536 coordTypeSize = sizeof(GLubyte);
2537 break;
2538
2539 case GL_SHORT:
2540 coordTypeSize = sizeof(GLshort);
2541 break;
2542
2543 case GL_UNSIGNED_SHORT:
2544 coordTypeSize = sizeof(GLushort);
2545 break;
2546
2547 case GL_FLOAT:
2548 coordTypeSize = sizeof(GLfloat);
2549 break;
2550
2551 default:
2552 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2553 return false;
2554 }
2555
2556 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2557 checkedSize += (coordTypeSize * numCoords);
2558 if (!checkedSize.IsValid())
2559 {
2560 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2561 return false;
2562 }
2563
2564 // early return skips command data validation when it doesn't exist.
2565 if (!commands)
2566 return true;
2567
2568 GLsizei expectedNumCoords = 0;
2569 for (GLsizei i = 0; i < numCommands; ++i)
2570 {
2571 switch (commands[i])
2572 {
2573 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2574 break;
2575 case GL_MOVE_TO_CHROMIUM:
2576 case GL_LINE_TO_CHROMIUM:
2577 expectedNumCoords += 2;
2578 break;
2579 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2580 expectedNumCoords += 4;
2581 break;
2582 case GL_CUBIC_CURVE_TO_CHROMIUM:
2583 expectedNumCoords += 6;
2584 break;
2585 case GL_CONIC_CURVE_TO_CHROMIUM:
2586 expectedNumCoords += 5;
2587 break;
2588 default:
2589 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2590 return false;
2591 }
2592 }
2593 if (expectedNumCoords != numCoords)
2594 {
2595 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2596 return false;
2597 }
2598
2599 return true;
2600}
2601
2602bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2603{
2604 if (!context->getExtensions().pathRendering)
2605 {
2606 context->handleError(
2607 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2608 return false;
2609 }
2610 if (!context->hasPath(path))
2611 {
2612 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2613 return false;
2614 }
2615
2616 switch (pname)
2617 {
2618 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2619 if (value < 0.0f)
2620 {
2621 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2622 return false;
2623 }
2624 break;
2625 case GL_PATH_END_CAPS_CHROMIUM:
2626 switch (static_cast<GLenum>(value))
2627 {
2628 case GL_FLAT_CHROMIUM:
2629 case GL_SQUARE_CHROMIUM:
2630 case GL_ROUND_CHROMIUM:
2631 break;
2632 default:
2633 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2634 return false;
2635 }
2636 break;
2637 case GL_PATH_JOIN_STYLE_CHROMIUM:
2638 switch (static_cast<GLenum>(value))
2639 {
2640 case GL_MITER_REVERT_CHROMIUM:
2641 case GL_BEVEL_CHROMIUM:
2642 case GL_ROUND_CHROMIUM:
2643 break;
2644 default:
2645 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2646 return false;
2647 }
2648 case GL_PATH_MITER_LIMIT_CHROMIUM:
2649 if (value < 0.0f)
2650 {
2651 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2652 return false;
2653 }
2654 break;
2655
2656 case GL_PATH_STROKE_BOUND_CHROMIUM:
2657 // no errors, only clamping.
2658 break;
2659
2660 default:
2661 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2662 return false;
2663 }
2664 return true;
2665}
2666
2667bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2668{
2669 if (!context->getExtensions().pathRendering)
2670 {
2671 context->handleError(
2672 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2673 return false;
2674 }
2675
2676 if (!context->hasPath(path))
2677 {
2678 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2679 return false;
2680 }
2681 if (!value)
2682 {
2683 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2684 return false;
2685 }
2686
2687 switch (pname)
2688 {
2689 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2690 case GL_PATH_END_CAPS_CHROMIUM:
2691 case GL_PATH_JOIN_STYLE_CHROMIUM:
2692 case GL_PATH_MITER_LIMIT_CHROMIUM:
2693 case GL_PATH_STROKE_BOUND_CHROMIUM:
2694 break;
2695
2696 default:
2697 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2698 return false;
2699 }
2700
2701 return true;
2702}
2703
2704bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2705{
2706 if (!context->getExtensions().pathRendering)
2707 {
2708 context->handleError(
2709 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2710 return false;
2711 }
2712
2713 switch (func)
2714 {
2715 case GL_NEVER:
2716 case GL_ALWAYS:
2717 case GL_LESS:
2718 case GL_LEQUAL:
2719 case GL_EQUAL:
2720 case GL_GEQUAL:
2721 case GL_GREATER:
2722 case GL_NOTEQUAL:
2723 break;
2724 default:
2725 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2726 return false;
2727 }
2728
2729 return true;
2730}
2731
2732// Note that the spec specifies that for the path drawing commands
2733// if the path object is not an existing path object the command
2734// does nothing and no error is generated.
2735// However if the path object exists but has not been specified any
2736// commands then an error is generated.
2737
2738bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2739{
2740 if (!context->getExtensions().pathRendering)
2741 {
2742 context->handleError(
2743 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2744 return false;
2745 }
2746 if (context->hasPath(path) && !context->hasPathData(path))
2747 {
2748 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2749 return false;
2750 }
2751
2752 switch (fillMode)
2753 {
2754 case GL_COUNT_UP_CHROMIUM:
2755 case GL_COUNT_DOWN_CHROMIUM:
2756 break;
2757 default:
2758 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2759 return false;
2760 }
2761
2762 if (!isPow2(mask + 1))
2763 {
2764 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2765 return false;
2766 }
2767
2768 return true;
2769}
2770
2771bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2772{
2773 if (!context->getExtensions().pathRendering)
2774 {
2775 context->handleError(
2776 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2777 return false;
2778 }
2779 if (context->hasPath(path) && !context->hasPathData(path))
2780 {
2781 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2782 return false;
2783 }
2784
2785 return true;
2786}
2787
2788bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2789{
2790 if (!context->getExtensions().pathRendering)
2791 {
2792 context->handleError(
2793 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2794 return false;
2795 }
2796 if (context->hasPath(path) && !context->hasPathData(path))
2797 {
2798 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2799 return false;
2800 }
2801
2802 switch (coverMode)
2803 {
2804 case GL_CONVEX_HULL_CHROMIUM:
2805 case GL_BOUNDING_BOX_CHROMIUM:
2806 break;
2807 default:
2808 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2809 return false;
2810 }
2811 return true;
2812}
2813
2814bool ValidateStencilThenCoverFillPath(Context *context,
2815 GLuint path,
2816 GLenum fillMode,
2817 GLuint mask,
2818 GLenum coverMode)
2819{
2820 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2821 ValidateCoverPath(context, path, coverMode);
2822}
2823
2824bool ValidateStencilThenCoverStrokePath(Context *context,
2825 GLuint path,
2826 GLint reference,
2827 GLuint mask,
2828 GLenum coverMode)
2829{
2830 return ValidateStencilStrokePath(context, path, reference, mask) &&
2831 ValidateCoverPath(context, path, coverMode);
2832}
2833
2834bool ValidateIsPath(Context *context)
2835{
2836 if (!context->getExtensions().pathRendering)
2837 {
2838 context->handleError(
2839 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2840 return false;
2841 }
2842 return true;
2843}
2844
Sami Väisänend59ca052016-06-21 16:10:00 +03002845bool ValidateCoverFillPathInstanced(Context *context,
2846 GLsizei numPaths,
2847 GLenum pathNameType,
2848 const void *paths,
2849 GLuint pathBase,
2850 GLenum coverMode,
2851 GLenum transformType,
2852 const GLfloat *transformValues)
2853{
2854 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2855 transformType, transformValues))
2856 return false;
2857
2858 switch (coverMode)
2859 {
2860 case GL_CONVEX_HULL_CHROMIUM:
2861 case GL_BOUNDING_BOX_CHROMIUM:
2862 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2863 break;
2864 default:
2865 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2866 return false;
2867 }
2868
2869 return true;
2870}
2871
2872bool ValidateCoverStrokePathInstanced(Context *context,
2873 GLsizei numPaths,
2874 GLenum pathNameType,
2875 const void *paths,
2876 GLuint pathBase,
2877 GLenum coverMode,
2878 GLenum transformType,
2879 const GLfloat *transformValues)
2880{
2881 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2882 transformType, transformValues))
2883 return false;
2884
2885 switch (coverMode)
2886 {
2887 case GL_CONVEX_HULL_CHROMIUM:
2888 case GL_BOUNDING_BOX_CHROMIUM:
2889 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2890 break;
2891 default:
2892 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2893 return false;
2894 }
2895
2896 return true;
2897}
2898
2899bool ValidateStencilFillPathInstanced(Context *context,
2900 GLsizei numPaths,
2901 GLenum pathNameType,
2902 const void *paths,
2903 GLuint pathBase,
2904 GLenum fillMode,
2905 GLuint mask,
2906 GLenum transformType,
2907 const GLfloat *transformValues)
2908{
2909
2910 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2911 transformType, transformValues))
2912 return false;
2913
2914 switch (fillMode)
2915 {
2916 case GL_COUNT_UP_CHROMIUM:
2917 case GL_COUNT_DOWN_CHROMIUM:
2918 break;
2919 default:
2920 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2921 return false;
2922 }
2923 if (!isPow2(mask + 1))
2924 {
2925 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2926 return false;
2927 }
2928 return true;
2929}
2930
2931bool ValidateStencilStrokePathInstanced(Context *context,
2932 GLsizei numPaths,
2933 GLenum pathNameType,
2934 const void *paths,
2935 GLuint pathBase,
2936 GLint reference,
2937 GLuint mask,
2938 GLenum transformType,
2939 const GLfloat *transformValues)
2940{
2941 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2942 transformType, transformValues))
2943 return false;
2944
2945 // no more validation here.
2946
2947 return true;
2948}
2949
2950bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2951 GLsizei numPaths,
2952 GLenum pathNameType,
2953 const void *paths,
2954 GLuint pathBase,
2955 GLenum fillMode,
2956 GLuint mask,
2957 GLenum coverMode,
2958 GLenum transformType,
2959 const GLfloat *transformValues)
2960{
2961 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2962 transformType, transformValues))
2963 return false;
2964
2965 switch (coverMode)
2966 {
2967 case GL_CONVEX_HULL_CHROMIUM:
2968 case GL_BOUNDING_BOX_CHROMIUM:
2969 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2970 break;
2971 default:
2972 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2973 return false;
2974 }
2975
2976 switch (fillMode)
2977 {
2978 case GL_COUNT_UP_CHROMIUM:
2979 case GL_COUNT_DOWN_CHROMIUM:
2980 break;
2981 default:
2982 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2983 return false;
2984 }
2985 if (!isPow2(mask + 1))
2986 {
2987 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2988 return false;
2989 }
2990
2991 return true;
2992}
2993
2994bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2995 GLsizei numPaths,
2996 GLenum pathNameType,
2997 const void *paths,
2998 GLuint pathBase,
2999 GLint reference,
3000 GLuint mask,
3001 GLenum coverMode,
3002 GLenum transformType,
3003 const GLfloat *transformValues)
3004{
3005 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3006 transformType, transformValues))
3007 return false;
3008
3009 switch (coverMode)
3010 {
3011 case GL_CONVEX_HULL_CHROMIUM:
3012 case GL_BOUNDING_BOX_CHROMIUM:
3013 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3014 break;
3015 default:
3016 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3017 return false;
3018 }
3019
3020 return true;
3021}
3022
Sami Väisänen46eaa942016-06-29 10:26:37 +03003023bool ValidateBindFragmentInputLocation(Context *context,
3024 GLuint program,
3025 GLint location,
3026 const GLchar *name)
3027{
3028 if (!context->getExtensions().pathRendering)
3029 {
3030 context->handleError(
3031 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3032 return false;
3033 }
3034
3035 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3036 if (location >= MaxLocation)
3037 {
3038 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3039 return false;
3040 }
3041
3042 const auto *programObject = context->getProgram(program);
3043 if (!programObject)
3044 {
3045 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3046 return false;
3047 }
3048
3049 if (!name)
3050 {
3051 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3052 return false;
3053 }
3054
3055 if (angle::BeginsWith(name, "gl_"))
3056 {
3057 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3058 return false;
3059 }
3060
3061 return true;
3062}
3063
3064bool ValidateProgramPathFragmentInputGen(Context *context,
3065 GLuint program,
3066 GLint location,
3067 GLenum genMode,
3068 GLint components,
3069 const GLfloat *coeffs)
3070{
3071 if (!context->getExtensions().pathRendering)
3072 {
3073 context->handleError(
3074 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3075 return false;
3076 }
3077
3078 const auto *programObject = context->getProgram(program);
3079 if (!programObject || programObject->isFlaggedForDeletion())
3080 {
3081 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3082 return false;
3083 }
3084
3085 if (!programObject->isLinked())
3086 {
3087 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3088 return false;
3089 }
3090
3091 switch (genMode)
3092 {
3093 case GL_NONE:
3094 if (components != 0)
3095 {
3096 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3097 return false;
3098 }
3099 break;
3100
3101 case GL_OBJECT_LINEAR_CHROMIUM:
3102 case GL_EYE_LINEAR_CHROMIUM:
3103 case GL_CONSTANT_CHROMIUM:
3104 if (components < 1 || components > 4)
3105 {
3106 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3107 return false;
3108 }
3109 if (!coeffs)
3110 {
3111 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3112 return false;
3113 }
3114 break;
3115
3116 default:
3117 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3118 return false;
3119 }
3120
3121 // If the location is -1 then the command is silently ignored
3122 // and no further validation is needed.
3123 if (location == -1)
3124 return true;
3125
3126 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3127
3128 if (!binding.valid)
3129 {
3130 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3131 return false;
3132 }
3133
3134 if (binding.type != GL_NONE)
3135 {
3136 GLint expectedComponents = 0;
3137 switch (binding.type)
3138 {
3139 case GL_FLOAT:
3140 expectedComponents = 1;
3141 break;
3142 case GL_FLOAT_VEC2:
3143 expectedComponents = 2;
3144 break;
3145 case GL_FLOAT_VEC3:
3146 expectedComponents = 3;
3147 break;
3148 case GL_FLOAT_VEC4:
3149 expectedComponents = 4;
3150 break;
3151 default:
3152 context->handleError(Error(GL_INVALID_OPERATION,
3153 "Fragment input type is not a floating point scalar or vector."));
3154 return false;
3155 }
3156 if (expectedComponents != components && genMode != GL_NONE)
3157 {
3158 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3159 return false;
3160 }
3161 }
3162 return true;
3163}
3164
Geoff Lang97073d12016-04-20 10:42:34 -07003165bool ValidateCopyTextureCHROMIUM(Context *context,
3166 GLuint sourceId,
3167 GLuint destId,
3168 GLint internalFormat,
3169 GLenum destType,
3170 GLboolean unpackFlipY,
3171 GLboolean unpackPremultiplyAlpha,
3172 GLboolean unpackUnmultiplyAlpha)
3173{
3174 if (!context->getExtensions().copyTexture)
3175 {
3176 context->handleError(
3177 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3178 return false;
3179 }
3180
3181 const gl::Texture *source = context->getTexture(sourceId);
3182 if (source == nullptr)
3183 {
3184 context->handleError(
3185 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3186 return false;
3187 }
3188
3189 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3190 {
3191 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3192 return false;
3193 }
3194
3195 GLenum sourceTarget = source->getTarget();
3196 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3197 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3198 {
3199 context->handleError(
3200 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3201 return false;
3202 }
3203
3204 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3205 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3206 {
3207 context->handleError(
3208 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3209 return false;
3210 }
3211
3212 const gl::Texture *dest = context->getTexture(destId);
3213 if (dest == nullptr)
3214 {
3215 context->handleError(
3216 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3217 return false;
3218 }
3219
3220 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3221 {
3222 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3223 return false;
3224 }
3225
3226 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3227 {
3228 context->handleError(
3229 Error(GL_INVALID_OPERATION,
3230 "Destination internal format and type combination is not valid."));
3231 return false;
3232 }
3233
3234 if (dest->getImmutableFormat())
3235 {
3236 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3237 return false;
3238 }
3239
3240 return true;
3241}
3242
3243bool ValidateCopySubTextureCHROMIUM(Context *context,
3244 GLuint sourceId,
3245 GLuint destId,
3246 GLint xoffset,
3247 GLint yoffset,
3248 GLint x,
3249 GLint y,
3250 GLsizei width,
3251 GLsizei height,
3252 GLboolean unpackFlipY,
3253 GLboolean unpackPremultiplyAlpha,
3254 GLboolean unpackUnmultiplyAlpha)
3255{
3256 if (!context->getExtensions().copyTexture)
3257 {
3258 context->handleError(
3259 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3260 return false;
3261 }
3262
3263 const gl::Texture *source = context->getTexture(sourceId);
3264 if (source == nullptr)
3265 {
3266 context->handleError(
3267 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3268 return false;
3269 }
3270
3271 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3272 {
3273 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3274 return false;
3275 }
3276
3277 GLenum sourceTarget = source->getTarget();
3278 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3279 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3280 {
3281 context->handleError(
3282 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3283 return false;
3284 }
3285
3286 if (x < 0 || y < 0)
3287 {
3288 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3289 return false;
3290 }
3291
3292 if (width < 0 || height < 0)
3293 {
3294 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3295 return false;
3296 }
3297
3298 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3299 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3300 {
3301 context->handleError(
3302 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3303 return false;
3304 }
3305
3306 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3307 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3308 {
3309 context->handleError(
3310 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3311 return false;
3312 }
3313
3314 const gl::Texture *dest = context->getTexture(destId);
3315 if (dest == nullptr)
3316 {
3317 context->handleError(
3318 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3319 return false;
3320 }
3321
3322 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3323 {
3324 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3325 return false;
3326 }
3327
3328 GLenum destTarget = dest->getTarget();
3329 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3330 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3331 {
3332 context->handleError(
3333 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3334 return false;
3335 }
3336
3337 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3338 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3339 {
3340 context->handleError(
3341 Error(GL_INVALID_OPERATION,
3342 "Destination internal format and type combination is not valid."));
3343 return false;
3344 }
3345
3346 if (xoffset < 0 || yoffset < 0)
3347 {
3348 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3349 return false;
3350 }
3351
3352 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3353 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3354 {
3355 context->handleError(
3356 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3357 return false;
3358 }
3359
3360 return true;
3361}
3362
Geoff Lang47110bf2016-04-20 11:13:22 -07003363bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3364{
3365 if (!context->getExtensions().copyCompressedTexture)
3366 {
3367 context->handleError(Error(GL_INVALID_OPERATION,
3368 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3369 return false;
3370 }
3371
3372 const gl::Texture *source = context->getTexture(sourceId);
3373 if (source == nullptr)
3374 {
3375 context->handleError(
3376 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3377 return false;
3378 }
3379
3380 if (source->getTarget() != GL_TEXTURE_2D)
3381 {
3382 context->handleError(
3383 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3384 return false;
3385 }
3386
3387 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3388 {
3389 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3390 return false;
3391 }
3392
3393 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3394 if (!sourceFormat.info->compressed)
3395 {
3396 context->handleError(
3397 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3398 return false;
3399 }
3400
3401 const gl::Texture *dest = context->getTexture(destId);
3402 if (dest == nullptr)
3403 {
3404 context->handleError(
3405 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3406 return false;
3407 }
3408
3409 if (dest->getTarget() != GL_TEXTURE_2D)
3410 {
3411 context->handleError(
3412 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3413 return false;
3414 }
3415
3416 if (dest->getImmutableFormat())
3417 {
3418 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3419 return false;
3420 }
3421
3422 return true;
3423}
3424
Martin Radev4c4c8e72016-08-04 12:25:34 +03003425bool ValidateCreateShader(Context *context, GLenum type)
3426{
3427 switch (type)
3428 {
3429 case GL_VERTEX_SHADER:
3430 case GL_FRAGMENT_SHADER:
3431 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003432
Martin Radev4c4c8e72016-08-04 12:25:34 +03003433 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003434 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003435 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003436 context->handleError(
3437 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3438 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003439 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003440 break;
3441
Martin Radev4c4c8e72016-08-04 12:25:34 +03003442 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003443 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003444 return false;
3445 }
Jamie Madill29639852016-09-02 15:00:09 -04003446
3447 return true;
3448}
3449
3450bool ValidateBufferData(ValidationContext *context,
3451 GLenum target,
3452 GLsizeiptr size,
3453 const GLvoid *data,
3454 GLenum usage)
3455{
3456 if (size < 0)
3457 {
3458 context->handleError(Error(GL_INVALID_VALUE));
3459 return false;
3460 }
3461
3462 switch (usage)
3463 {
3464 case GL_STREAM_DRAW:
3465 case GL_STATIC_DRAW:
3466 case GL_DYNAMIC_DRAW:
3467 break;
3468
3469 case GL_STREAM_READ:
3470 case GL_STREAM_COPY:
3471 case GL_STATIC_READ:
3472 case GL_STATIC_COPY:
3473 case GL_DYNAMIC_READ:
3474 case GL_DYNAMIC_COPY:
3475 if (context->getClientMajorVersion() < 3)
3476 {
3477 context->handleError(Error(GL_INVALID_ENUM));
3478 return false;
3479 }
3480 break;
3481
3482 default:
3483 context->handleError(Error(GL_INVALID_ENUM));
3484 return false;
3485 }
3486
3487 if (!ValidBufferTarget(context, target))
3488 {
3489 context->handleError(Error(GL_INVALID_ENUM));
3490 return false;
3491 }
3492
3493 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3494
3495 if (!buffer)
3496 {
3497 context->handleError(Error(GL_INVALID_OPERATION));
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
3504bool ValidateBufferSubData(ValidationContext *context,
3505 GLenum target,
3506 GLintptr offset,
3507 GLsizeiptr size,
3508 const GLvoid *data)
3509{
3510 if (size < 0 || offset < 0)
3511 {
3512 context->handleError(Error(GL_INVALID_VALUE));
3513 return false;
3514 }
3515
3516 if (!ValidBufferTarget(context, target))
3517 {
3518 context->handleError(Error(GL_INVALID_ENUM));
3519 return false;
3520 }
3521
3522 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3523
3524 if (!buffer)
3525 {
3526 context->handleError(Error(GL_INVALID_OPERATION));
3527 return false;
3528 }
3529
3530 if (buffer->isMapped())
3531 {
3532 context->handleError(Error(GL_INVALID_OPERATION));
3533 return false;
3534 }
3535
3536 // Check for possible overflow of size + offset
3537 angle::CheckedNumeric<size_t> checkedSize(size);
3538 checkedSize += offset;
3539 if (!checkedSize.IsValid())
3540 {
3541 context->handleError(Error(GL_OUT_OF_MEMORY));
3542 return false;
3543 }
3544
3545 if (size + offset > buffer->getSize())
3546 {
3547 context->handleError(Error(GL_INVALID_VALUE));
3548 return false;
3549 }
3550
Martin Radev4c4c8e72016-08-04 12:25:34 +03003551 return true;
3552}
3553
Geoff Langc287ea62016-09-16 14:46:51 -04003554bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3555{
3556 if (!context->getExtensions().webglCompatibility)
3557 {
3558 context->handleError(
3559 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3560 return false;
3561 }
3562
3563 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3564 auto extension = extensionInfos.find(name);
3565 if (extension == extensionInfos.end() || !extension->second.Enableable)
3566 {
3567 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3568 return false;
3569 }
3570
3571 return true;
3572}
3573
Jamie Madillef300b12016-10-07 15:12:09 -04003574bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3575{
3576 if (texture < GL_TEXTURE0 ||
3577 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3578 {
3579 context->handleError(Error(GL_INVALID_ENUM));
3580 return false;
3581 }
3582
3583 return true;
3584}
3585
3586bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3587{
3588 Program *programObject = GetValidProgram(context, program);
3589 if (!programObject)
3590 {
3591 return false;
3592 }
3593
3594 Shader *shaderObject = GetValidShader(context, shader);
3595 if (!shaderObject)
3596 {
3597 return false;
3598 }
3599
3600 switch (shaderObject->getType())
3601 {
3602 case GL_VERTEX_SHADER:
3603 {
3604 if (programObject->getAttachedVertexShader())
3605 {
3606 context->handleError(Error(GL_INVALID_OPERATION));
3607 return false;
3608 }
3609 break;
3610 }
3611 case GL_FRAGMENT_SHADER:
3612 {
3613 if (programObject->getAttachedFragmentShader())
3614 {
3615 context->handleError(Error(GL_INVALID_OPERATION));
3616 return false;
3617 }
3618 break;
3619 }
3620 case GL_COMPUTE_SHADER:
3621 {
3622 if (programObject->getAttachedComputeShader())
3623 {
3624 context->handleError(Error(GL_INVALID_OPERATION));
3625 return false;
3626 }
3627 break;
3628 }
3629 default:
3630 UNREACHABLE();
3631 break;
3632 }
3633
3634 return true;
3635}
3636
Jamie Madill01a80ee2016-11-07 12:06:18 -05003637bool ValidateBindAttribLocation(ValidationContext *context,
3638 GLuint program,
3639 GLuint index,
3640 const GLchar *name)
3641{
3642 if (index >= MAX_VERTEX_ATTRIBS)
3643 {
3644 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3645 return false;
3646 }
3647
3648 if (strncmp(name, "gl_", 3) == 0)
3649 {
3650 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3651 return false;
3652 }
3653
3654 return GetValidProgram(context, program) != nullptr;
3655}
3656
3657bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3658{
3659 if (!ValidBufferTarget(context, target))
3660 {
3661 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3662 return false;
3663 }
3664
3665 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3666 !context->isBufferGenerated(buffer))
3667 {
3668 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3669 return false;
3670 }
3671
3672 return true;
3673}
3674
3675bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3676{
3677 if (!ValidFramebufferTarget(target))
3678 {
3679 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3680 return false;
3681 }
3682
3683 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3684 !context->isFramebufferGenerated(framebuffer))
3685 {
3686 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3687 return false;
3688 }
3689
3690 return true;
3691}
3692
3693bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3694{
3695 if (target != GL_RENDERBUFFER)
3696 {
3697 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3698 return false;
3699 }
3700
3701 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3702 !context->isRenderbufferGenerated(renderbuffer))
3703 {
3704 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3705 return false;
3706 }
3707
3708 return true;
3709}
3710
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003711static bool ValidBlendEquationMode(GLenum mode)
3712{
3713 switch (mode)
3714 {
3715 case GL_FUNC_ADD:
3716 case GL_FUNC_SUBTRACT:
3717 case GL_FUNC_REVERSE_SUBTRACT:
3718 case GL_MIN:
3719 case GL_MAX:
3720 return true;
3721
3722 default:
3723 return false;
3724 }
3725}
3726
3727bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3728{
3729 if (!ValidBlendEquationMode(mode))
3730 {
3731 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3732 return false;
3733 }
3734
3735 return true;
3736}
3737
3738bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3739{
3740 if (!ValidBlendEquationMode(modeRGB))
3741 {
3742 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3743 return false;
3744 }
3745
3746 if (!ValidBlendEquationMode(modeAlpha))
3747 {
3748 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3749 return false;
3750 }
3751
3752 return true;
3753}
3754
3755bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3756{
3757 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3758}
3759
3760static bool ValidSrcBlendFunc(GLenum srcBlend)
3761{
3762 switch (srcBlend)
3763 {
3764 case GL_ZERO:
3765 case GL_ONE:
3766 case GL_SRC_COLOR:
3767 case GL_ONE_MINUS_SRC_COLOR:
3768 case GL_DST_COLOR:
3769 case GL_ONE_MINUS_DST_COLOR:
3770 case GL_SRC_ALPHA:
3771 case GL_ONE_MINUS_SRC_ALPHA:
3772 case GL_DST_ALPHA:
3773 case GL_ONE_MINUS_DST_ALPHA:
3774 case GL_CONSTANT_COLOR:
3775 case GL_ONE_MINUS_CONSTANT_COLOR:
3776 case GL_CONSTANT_ALPHA:
3777 case GL_ONE_MINUS_CONSTANT_ALPHA:
3778 case GL_SRC_ALPHA_SATURATE:
3779 return true;
3780
3781 default:
3782 return false;
3783 }
3784}
3785
3786static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3787{
3788 switch (dstBlend)
3789 {
3790 case GL_ZERO:
3791 case GL_ONE:
3792 case GL_SRC_COLOR:
3793 case GL_ONE_MINUS_SRC_COLOR:
3794 case GL_DST_COLOR:
3795 case GL_ONE_MINUS_DST_COLOR:
3796 case GL_SRC_ALPHA:
3797 case GL_ONE_MINUS_SRC_ALPHA:
3798 case GL_DST_ALPHA:
3799 case GL_ONE_MINUS_DST_ALPHA:
3800 case GL_CONSTANT_COLOR:
3801 case GL_ONE_MINUS_CONSTANT_COLOR:
3802 case GL_CONSTANT_ALPHA:
3803 case GL_ONE_MINUS_CONSTANT_ALPHA:
3804 return true;
3805
3806 case GL_SRC_ALPHA_SATURATE:
3807 return (contextMajorVersion >= 3);
3808
3809 default:
3810 return false;
3811 }
3812}
3813
3814bool ValidateBlendFuncSeparate(ValidationContext *context,
3815 GLenum srcRGB,
3816 GLenum dstRGB,
3817 GLenum srcAlpha,
3818 GLenum dstAlpha)
3819{
3820 if (!ValidSrcBlendFunc(srcRGB))
3821 {
3822 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3823 return false;
3824 }
3825
3826 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
3827 {
3828 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3829 return false;
3830 }
3831
3832 if (!ValidSrcBlendFunc(srcAlpha))
3833 {
3834 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3835 return false;
3836 }
3837
3838 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
3839 {
3840 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
3841 return false;
3842 }
3843
3844 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
3845 {
3846 bool constantColorUsed =
3847 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3848 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3849
3850 bool constantAlphaUsed =
3851 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3852 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3853
3854 if (constantColorUsed && constantAlphaUsed)
3855 {
3856 ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3857 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
3858 "implementation.");
3859 context->handleError(Error(GL_INVALID_OPERATION,
3860 "Simultaneous use of "
3861 "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
3862 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
3863 "supported by this implementation."));
3864 return false;
3865 }
3866 }
3867
3868 return true;
3869}
3870
Jamie Madillc29968b2016-01-20 11:17:23 -05003871} // namespace gl