blob: 84768797853a3b9d95ec98afc983c7dbff0c0ae8 [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 Langa9be0dc2014-12-17 12:34:40 -0500371 if (format != GL_NONE)
372 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400373 if (gl::GetSizedInternalFormat(format, type) !=
374 texture->getFormat(target, level).asSized())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500375 {
Jamie Madill437fa652016-05-03 15:13:24 -0400376 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500377 return false;
378 }
379 }
380
381 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
382 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
383 {
Jamie Madill437fa652016-05-03 15:13:24 -0400384 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500385 return false;
386 }
387 }
388 else
389 {
Geoff Lang69cce582015-09-17 13:20:36 -0400390 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500391 {
Jamie Madill437fa652016-05-03 15:13:24 -0400392 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500393 return false;
394 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
396
397 // Verify zero border
398 if (border != 0)
399 {
Jamie Madill437fa652016-05-03 15:13:24 -0400400 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400401 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 }
403
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 if (isCompressed)
405 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400406 GLenum actualInternalFormat =
Jamie Madilla3944d42016-07-22 22:13:26 -0400407 isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400408 switch (actualInternalFormat)
409 {
410 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
411 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400412 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400413 {
Jamie Madill437fa652016-05-03 15:13:24 -0400414 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416 }
417 break;
418 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400419 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400420 {
Jamie Madill437fa652016-05-03 15:13:24 -0400421 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400422 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 }
424 break;
425 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400426 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427 {
Jamie Madill437fa652016-05-03 15:13:24 -0400428 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430 }
431 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400432 case GL_ETC1_RGB8_OES:
433 if (!context->getExtensions().compressedETC1RGB8Texture)
434 {
Jamie Madill437fa652016-05-03 15:13:24 -0400435 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400436 return false;
437 }
438 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800439 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
440 if (!context->getExtensions().lossyETCDecode)
441 {
Jamie Madill437fa652016-05-03 15:13:24 -0400442 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800443 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
444 return false;
445 }
446 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400447 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400448 context->handleError(Error(
tmartino0ccd5ae2015-10-01 14:33:14 -0400449 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
450 return false;
451 }
452 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
453 {
Jamie Madill437fa652016-05-03 15:13:24 -0400454 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400455 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400456 }
457 }
458 else
459 {
460 // validate <type> by itself (used as secondary key below)
461 switch (type)
462 {
463 case GL_UNSIGNED_BYTE:
464 case GL_UNSIGNED_SHORT_5_6_5:
465 case GL_UNSIGNED_SHORT_4_4_4_4:
466 case GL_UNSIGNED_SHORT_5_5_5_1:
467 case GL_UNSIGNED_SHORT:
468 case GL_UNSIGNED_INT:
469 case GL_UNSIGNED_INT_24_8_OES:
470 case GL_HALF_FLOAT_OES:
471 case GL_FLOAT:
472 break;
473 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400474 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400475 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 }
477
478 // validate <format> + <type> combinations
479 // - invalid <format> -> sets INVALID_ENUM
480 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
481 switch (format)
482 {
483 case GL_ALPHA:
484 case GL_LUMINANCE:
485 case GL_LUMINANCE_ALPHA:
486 switch (type)
487 {
488 case GL_UNSIGNED_BYTE:
489 case GL_FLOAT:
490 case GL_HALF_FLOAT_OES:
491 break;
Geoff Langb1196682014-07-23 13:47:29 -0400492 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400493 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400494 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400495 }
496 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400497 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400498 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400499 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400500 {
Jamie Madill437fa652016-05-03 15:13:24 -0400501 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400502 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400503 }
504 switch (type)
505 {
506 case GL_UNSIGNED_BYTE:
507 case GL_FLOAT:
508 case GL_HALF_FLOAT_OES:
509 break;
510 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400511 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400512 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400513 }
514 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400515 case GL_RGB:
516 switch (type)
517 {
518 case GL_UNSIGNED_BYTE:
519 case GL_UNSIGNED_SHORT_5_6_5:
520 case GL_FLOAT:
521 case GL_HALF_FLOAT_OES:
522 break;
523 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400524 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400525 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400526 }
527 break;
528 case GL_RGBA:
529 switch (type)
530 {
531 case GL_UNSIGNED_BYTE:
532 case GL_UNSIGNED_SHORT_4_4_4_4:
533 case GL_UNSIGNED_SHORT_5_5_5_1:
534 case GL_FLOAT:
535 case GL_HALF_FLOAT_OES:
536 break;
537 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400538 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400539 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400540 }
541 break;
542 case GL_BGRA_EXT:
543 switch (type)
544 {
545 case GL_UNSIGNED_BYTE:
546 break;
547 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400548 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400549 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400550 }
551 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400552 case GL_SRGB_EXT:
553 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400554 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400555 {
Jamie Madill437fa652016-05-03 15:13:24 -0400556 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400557 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400558 }
559 switch (type)
560 {
561 case GL_UNSIGNED_BYTE:
562 break;
563 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400564 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400565 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400566 }
567 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400568 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
569 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
570 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
571 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
572 break;
573 case GL_DEPTH_COMPONENT:
574 switch (type)
575 {
576 case GL_UNSIGNED_SHORT:
577 case GL_UNSIGNED_INT:
578 break;
579 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400580 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400581 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400582 }
583 break;
584 case GL_DEPTH_STENCIL_OES:
585 switch (type)
586 {
587 case GL_UNSIGNED_INT_24_8_OES:
588 break;
589 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400590 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400591 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400592 }
593 break;
594 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400595 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400596 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400597 }
598
599 switch (format)
600 {
601 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
602 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400603 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 {
Jamie Madill437fa652016-05-03 15:13:24 -0400605 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400606 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400607 }
608 else
609 {
Jamie Madill437fa652016-05-03 15:13:24 -0400610 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400612 }
613 break;
614 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400615 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 {
Jamie Madill437fa652016-05-03 15:13:24 -0400617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400618 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400619 }
620 else
621 {
Jamie Madill437fa652016-05-03 15:13:24 -0400622 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400623 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624 }
625 break;
626 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400627 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400628 {
Jamie Madill437fa652016-05-03 15:13:24 -0400629 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400630 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400631 }
632 else
633 {
Jamie Madill437fa652016-05-03 15:13:24 -0400634 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400635 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400636 }
637 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400638 case GL_ETC1_RGB8_OES:
639 if (context->getExtensions().compressedETC1RGB8Texture)
640 {
Jamie Madill437fa652016-05-03 15:13:24 -0400641 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400642 return false;
643 }
644 else
645 {
Jamie Madill437fa652016-05-03 15:13:24 -0400646 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400647 return false;
648 }
649 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800650 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
651 if (context->getExtensions().lossyETCDecode)
652 {
Jamie Madill437fa652016-05-03 15:13:24 -0400653 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800654 Error(GL_INVALID_OPERATION,
655 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
656 return false;
657 }
658 else
659 {
Jamie Madill437fa652016-05-03 15:13:24 -0400660 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800661 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
662 return false;
663 }
664 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400665 case GL_DEPTH_COMPONENT:
666 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400667 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400668 {
Jamie Madill437fa652016-05-03 15:13:24 -0400669 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400670 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400671 }
672 if (target != GL_TEXTURE_2D)
673 {
Jamie Madill437fa652016-05-03 15:13:24 -0400674 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400675 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400676 }
677 // OES_depth_texture supports loading depth data and multiple levels,
678 // but ANGLE_depth_texture does not
679 if (pixels != NULL || level != 0)
680 {
Jamie Madill437fa652016-05-03 15:13:24 -0400681 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400682 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400683 }
684 break;
685 default:
686 break;
687 }
688
689 if (type == GL_FLOAT)
690 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400691 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400692 {
Jamie Madill437fa652016-05-03 15:13:24 -0400693 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400694 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400695 }
696 }
697 else if (type == GL_HALF_FLOAT_OES)
698 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400699 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400700 {
Jamie Madill437fa652016-05-03 15:13:24 -0400701 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400702 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400703 }
704 }
705 }
706
Geoff Langff5b2d52016-09-07 11:32:23 -0400707 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
708 imageSize))
709 {
710 return false;
711 }
712
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400713 return true;
714}
715
Jamie Madillc29968b2016-01-20 11:17:23 -0500716bool ValidateES2CopyTexImageParameters(ValidationContext *context,
717 GLenum target,
718 GLint level,
719 GLenum internalformat,
720 bool isSubImage,
721 GLint xoffset,
722 GLint yoffset,
723 GLint x,
724 GLint y,
725 GLsizei width,
726 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400727 GLint border)
728{
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500729 if (!ValidTexture2DDestinationTarget(context, target))
730 {
Jamie Madill437fa652016-05-03 15:13:24 -0400731 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500732 return false;
733 }
734
Jamie Madill0c8abca2016-07-22 20:21:26 -0400735 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400736 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400737 xoffset, yoffset, 0, x, y, width, height, border,
738 &textureFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400740 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400741 }
742
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700743 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madilla3944d42016-07-22 22:13:26 -0400744 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
Jamie Madill0c8abca2016-07-22 20:21:26 -0400745 const auto &formatInfo = *textureFormat.info;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746
747 // [OpenGL ES 2.0.24] table 3.9
748 if (isSubImage)
749 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400750 switch (formatInfo.format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400751 {
752 case GL_ALPHA:
753 if (colorbufferFormat != GL_ALPHA8_EXT &&
754 colorbufferFormat != GL_RGBA4 &&
755 colorbufferFormat != GL_RGB5_A1 &&
756 colorbufferFormat != GL_RGBA8_OES)
757 {
Jamie Madill437fa652016-05-03 15:13:24 -0400758 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 }
761 break;
762 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400763 if (colorbufferFormat != GL_R8_EXT &&
764 colorbufferFormat != GL_RG8_EXT &&
765 colorbufferFormat != GL_RGB565 &&
766 colorbufferFormat != GL_RGB8_OES &&
767 colorbufferFormat != GL_RGBA4 &&
768 colorbufferFormat != GL_RGB5_A1 &&
769 colorbufferFormat != GL_RGBA8_OES)
770 {
Jamie Madill437fa652016-05-03 15:13:24 -0400771 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400772 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400773 }
774 break;
775 case GL_RED_EXT:
776 if (colorbufferFormat != GL_R8_EXT &&
777 colorbufferFormat != GL_RG8_EXT &&
778 colorbufferFormat != GL_RGB565 &&
779 colorbufferFormat != GL_RGB8_OES &&
780 colorbufferFormat != GL_RGBA4 &&
781 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500782 colorbufferFormat != GL_RGBA8_OES &&
783 colorbufferFormat != GL_R32F &&
784 colorbufferFormat != GL_RG32F &&
785 colorbufferFormat != GL_RGB32F &&
786 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400787 {
Jamie Madill437fa652016-05-03 15:13:24 -0400788 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400789 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400790 }
791 break;
792 case GL_RG_EXT:
793 if (colorbufferFormat != GL_RG8_EXT &&
794 colorbufferFormat != GL_RGB565 &&
795 colorbufferFormat != GL_RGB8_OES &&
796 colorbufferFormat != GL_RGBA4 &&
797 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500798 colorbufferFormat != GL_RGBA8_OES &&
799 colorbufferFormat != GL_RG32F &&
800 colorbufferFormat != GL_RGB32F &&
801 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400802 {
Jamie Madill437fa652016-05-03 15:13:24 -0400803 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400804 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400805 }
806 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400807 case GL_RGB:
808 if (colorbufferFormat != GL_RGB565 &&
809 colorbufferFormat != GL_RGB8_OES &&
810 colorbufferFormat != GL_RGBA4 &&
811 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500812 colorbufferFormat != GL_RGBA8_OES &&
813 colorbufferFormat != GL_RGB32F &&
814 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 {
Jamie Madill437fa652016-05-03 15:13:24 -0400816 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400817 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400818 }
819 break;
820 case GL_LUMINANCE_ALPHA:
821 case GL_RGBA:
822 if (colorbufferFormat != GL_RGBA4 &&
823 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500824 colorbufferFormat != GL_RGBA8_OES &&
825 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400826 {
Jamie Madill437fa652016-05-03 15:13:24 -0400827 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400828 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 }
830 break;
831 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
832 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
833 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
834 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400835 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800836 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400837 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400838 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 case GL_DEPTH_COMPONENT:
840 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400841 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400842 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400844 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400845 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500847
Jamie Madill0c8abca2016-07-22 20:21:26 -0400848 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
Jamie Madillbc393df2015-01-29 13:46:07 -0500849 {
Jamie Madill437fa652016-05-03 15:13:24 -0400850 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500851 return false;
852 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 }
854 else
855 {
856 switch (internalformat)
857 {
858 case GL_ALPHA:
859 if (colorbufferFormat != GL_ALPHA8_EXT &&
860 colorbufferFormat != GL_RGBA4 &&
861 colorbufferFormat != GL_RGB5_A1 &&
862 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500863 colorbufferFormat != GL_RGBA8_OES &&
864 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 {
Jamie Madill437fa652016-05-03 15:13:24 -0400866 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400867 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868 }
869 break;
870 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400871 if (colorbufferFormat != GL_R8_EXT &&
872 colorbufferFormat != GL_RG8_EXT &&
873 colorbufferFormat != GL_RGB565 &&
874 colorbufferFormat != GL_RGB8_OES &&
875 colorbufferFormat != GL_RGBA4 &&
876 colorbufferFormat != GL_RGB5_A1 &&
877 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500878 colorbufferFormat != GL_RGBA8_OES &&
879 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400880 {
Jamie Madill437fa652016-05-03 15:13:24 -0400881 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400882 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400883 }
884 break;
885 case GL_RED_EXT:
886 if (colorbufferFormat != GL_R8_EXT &&
887 colorbufferFormat != GL_RG8_EXT &&
888 colorbufferFormat != GL_RGB565 &&
889 colorbufferFormat != GL_RGB8_OES &&
890 colorbufferFormat != GL_RGBA4 &&
891 colorbufferFormat != GL_RGB5_A1 &&
892 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500893 colorbufferFormat != GL_RGBA8_OES &&
894 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400895 {
Jamie Madill437fa652016-05-03 15:13:24 -0400896 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400897 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400898 }
899 break;
900 case GL_RG_EXT:
901 if (colorbufferFormat != GL_RG8_EXT &&
902 colorbufferFormat != GL_RGB565 &&
903 colorbufferFormat != GL_RGB8_OES &&
904 colorbufferFormat != GL_RGBA4 &&
905 colorbufferFormat != GL_RGB5_A1 &&
906 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500907 colorbufferFormat != GL_RGBA8_OES &&
908 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400909 {
Jamie Madill437fa652016-05-03 15:13:24 -0400910 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400911 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400912 }
913 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 case GL_RGB:
915 if (colorbufferFormat != GL_RGB565 &&
916 colorbufferFormat != GL_RGB8_OES &&
917 colorbufferFormat != GL_RGBA4 &&
918 colorbufferFormat != GL_RGB5_A1 &&
919 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500920 colorbufferFormat != GL_RGBA8_OES &&
921 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 {
Jamie Madill437fa652016-05-03 15:13:24 -0400923 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400924 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 }
926 break;
927 case GL_LUMINANCE_ALPHA:
928 case GL_RGBA:
929 if (colorbufferFormat != GL_RGBA4 &&
930 colorbufferFormat != GL_RGB5_A1 &&
931 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500932 colorbufferFormat != GL_RGBA8_OES &&
933 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 {
Jamie Madill437fa652016-05-03 15:13:24 -0400935 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400937 }
938 break;
939 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
940 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400941 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 {
Jamie Madill437fa652016-05-03 15:13:24 -0400943 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400944 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 }
946 else
947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 }
951 break;
952 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400953 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 {
Jamie Madill437fa652016-05-03 15:13:24 -0400955 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400956 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957 }
958 else
959 {
Jamie Madill437fa652016-05-03 15:13:24 -0400960 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400961 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400962 }
963 break;
964 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400965 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966 {
Jamie Madill437fa652016-05-03 15:13:24 -0400967 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400968 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 }
970 else
971 {
Jamie Madill437fa652016-05-03 15:13:24 -0400972 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400973 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 }
975 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400976 case GL_ETC1_RGB8_OES:
977 if (context->getExtensions().compressedETC1RGB8Texture)
978 {
Jamie Madill437fa652016-05-03 15:13:24 -0400979 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400980 return false;
981 }
982 else
983 {
Jamie Madill437fa652016-05-03 15:13:24 -0400984 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400985 return false;
986 }
987 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800988 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
989 if (context->getExtensions().lossyETCDecode)
990 {
Jamie Madill437fa652016-05-03 15:13:24 -0400991 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800992 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
993 return false;
994 }
995 else
996 {
Jamie Madill437fa652016-05-03 15:13:24 -0400997 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800998 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
999 return false;
1000 }
1001 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001002 case GL_DEPTH_COMPONENT:
1003 case GL_DEPTH_COMPONENT16:
1004 case GL_DEPTH_COMPONENT32_OES:
1005 case GL_DEPTH_STENCIL_OES:
1006 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001007 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 {
Jamie Madill437fa652016-05-03 15:13:24 -04001009 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001010 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 }
1012 else
1013 {
Jamie Madill437fa652016-05-03 15:13:24 -04001014 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001015 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 }
1017 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001018 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001019 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 }
1021 }
1022
Geoff Lang784a8fd2013-09-24 12:33:16 -04001023 // If width or height is zero, it is a no-op. Return false without setting an error.
1024 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001025}
1026
Geoff Langb1196682014-07-23 13:47:29 -04001027bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001028 GLsizei width, GLsizei height)
1029{
1030 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1031 {
Jamie Madill437fa652016-05-03 15:13:24 -04001032 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001033 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 }
1035
1036 if (width < 1 || height < 1 || levels < 1)
1037 {
Jamie Madill437fa652016-05-03 15:13:24 -04001038 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041
1042 if (target == GL_TEXTURE_CUBE_MAP && width != height)
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 (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053
Geoff Lang5d601382014-07-22 15:14:06 -04001054 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1055 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 {
Jamie Madill437fa652016-05-03 15:13:24 -04001057 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001058 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 }
1060
Geoff Langaae65a42014-05-26 12:43:44 -04001061 const gl::Caps &caps = context->getCaps();
1062
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001063 switch (target)
1064 {
1065 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -04001066 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1067 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001068 {
Jamie Madill437fa652016-05-03 15:13:24 -04001069 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 }
1072 break;
1073 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -04001074 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1075 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 {
Jamie Madill437fa652016-05-03 15:13:24 -04001077 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001078 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 }
1080 break;
1081 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001082 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001084 }
1085
Geoff Langc0b9ef42014-07-02 10:02:37 -04001086 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001087 {
1088 if (!gl::isPow2(width) || !gl::isPow2(height))
1089 {
Jamie Madill437fa652016-05-03 15:13:24 -04001090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093 }
1094
1095 switch (internalformat)
1096 {
1097 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1098 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001099 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 {
Jamie Madill437fa652016-05-03 15:13:24 -04001101 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103 }
1104 break;
1105 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001106 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 {
Jamie Madill437fa652016-05-03 15:13:24 -04001108 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 }
1111 break;
1112 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001113 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001114 {
Jamie Madill437fa652016-05-03 15:13:24 -04001115 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001116 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 }
1118 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001119 case GL_ETC1_RGB8_OES:
1120 if (!context->getExtensions().compressedETC1RGB8Texture)
1121 {
Jamie Madill437fa652016-05-03 15:13:24 -04001122 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001123 return false;
1124 }
1125 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001126 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1127 if (!context->getExtensions().lossyETCDecode)
1128 {
Jamie Madill437fa652016-05-03 15:13:24 -04001129 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001130 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1131 return false;
1132 }
1133 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 case GL_RGBA32F_EXT:
1135 case GL_RGB32F_EXT:
1136 case GL_ALPHA32F_EXT:
1137 case GL_LUMINANCE32F_EXT:
1138 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001139 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001140 {
Jamie Madill437fa652016-05-03 15:13:24 -04001141 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144 break;
1145 case GL_RGBA16F_EXT:
1146 case GL_RGB16F_EXT:
1147 case GL_ALPHA16F_EXT:
1148 case GL_LUMINANCE16F_EXT:
1149 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001150 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 {
Jamie Madill437fa652016-05-03 15:13:24 -04001152 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001153 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 }
1155 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001156 case GL_R8_EXT:
1157 case GL_RG8_EXT:
1158 case GL_R16F_EXT:
1159 case GL_RG16F_EXT:
1160 case GL_R32F_EXT:
1161 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001162 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001163 {
Jamie Madill437fa652016-05-03 15:13:24 -04001164 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001166 }
1167 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 case GL_DEPTH_COMPONENT16:
1169 case GL_DEPTH_COMPONENT32_OES:
1170 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001171 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 {
Jamie Madill437fa652016-05-03 15:13:24 -04001173 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001174 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001175 }
1176 if (target != GL_TEXTURE_2D)
1177 {
Jamie Madill437fa652016-05-03 15:13:24 -04001178 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 }
1181 // ANGLE_depth_texture only supports 1-level textures
1182 if (levels != 1)
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 break;
1188 default:
1189 break;
1190 }
1191
Geoff Lang691e58c2014-12-19 17:03:25 -05001192 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001193 if (!texture || texture->id() == 0)
1194 {
Jamie Madill437fa652016-05-03 15:13:24 -04001195 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001196 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001197 }
1198
Geoff Lang69cce582015-09-17 13:20:36 -04001199 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001200 {
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
1205 return true;
1206}
1207
Austin Kinross08332632015-05-05 13:35:47 -07001208bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1209 const GLenum *attachments)
1210{
Jamie Madillc29968b2016-01-20 11:17:23 -05001211 if (!context->getExtensions().discardFramebuffer)
1212 {
Jamie Madill437fa652016-05-03 15:13:24 -04001213 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001214 return false;
1215 }
1216
Austin Kinross08332632015-05-05 13:35:47 -07001217 bool defaultFramebuffer = false;
1218
1219 switch (target)
1220 {
1221 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001222 defaultFramebuffer =
1223 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1224 break;
Austin Kinross08332632015-05-05 13:35:47 -07001225 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001226 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001227 return false;
1228 }
1229
1230 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1231}
1232
Austin Kinrossbc781f32015-10-26 09:27:38 -07001233bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1234{
1235 if (!context->getExtensions().vertexArrayObject)
1236 {
Jamie Madill437fa652016-05-03 15:13:24 -04001237 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001238 return false;
1239 }
1240
1241 return ValidateBindVertexArrayBase(context, array);
1242}
1243
1244bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1245{
1246 if (!context->getExtensions().vertexArrayObject)
1247 {
Jamie Madill437fa652016-05-03 15:13:24 -04001248 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001249 return false;
1250 }
1251
Olli Etuaho41997e72016-03-10 13:38:39 +02001252 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001253}
1254
1255bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1256{
1257 if (!context->getExtensions().vertexArrayObject)
1258 {
Jamie Madill437fa652016-05-03 15:13:24 -04001259 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001260 return false;
1261 }
1262
Olli Etuaho41997e72016-03-10 13:38:39 +02001263 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001264}
1265
1266bool ValidateIsVertexArrayOES(Context *context)
1267{
1268 if (!context->getExtensions().vertexArrayObject)
1269 {
Jamie Madill437fa652016-05-03 15:13:24 -04001270 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001271 return false;
1272 }
1273
1274 return true;
1275}
Geoff Langc5629752015-12-07 16:29:04 -05001276
1277bool ValidateProgramBinaryOES(Context *context,
1278 GLuint program,
1279 GLenum binaryFormat,
1280 const void *binary,
1281 GLint length)
1282{
1283 if (!context->getExtensions().getProgramBinary)
1284 {
Jamie Madill437fa652016-05-03 15:13:24 -04001285 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001286 return false;
1287 }
1288
1289 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1290}
1291
1292bool ValidateGetProgramBinaryOES(Context *context,
1293 GLuint program,
1294 GLsizei bufSize,
1295 GLsizei *length,
1296 GLenum *binaryFormat,
1297 void *binary)
1298{
1299 if (!context->getExtensions().getProgramBinary)
1300 {
Jamie Madill437fa652016-05-03 15:13:24 -04001301 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001302 return false;
1303 }
1304
1305 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1306}
Geoff Lange102fee2015-12-10 11:23:30 -05001307
Geoff Lang70d0f492015-12-10 17:45:46 -05001308static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1309{
1310 switch (source)
1311 {
1312 case GL_DEBUG_SOURCE_API:
1313 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1314 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1315 case GL_DEBUG_SOURCE_OTHER:
1316 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1317 return !mustBeThirdPartyOrApplication;
1318
1319 case GL_DEBUG_SOURCE_THIRD_PARTY:
1320 case GL_DEBUG_SOURCE_APPLICATION:
1321 return true;
1322
1323 default:
1324 return false;
1325 }
1326}
1327
1328static bool ValidDebugType(GLenum type)
1329{
1330 switch (type)
1331 {
1332 case GL_DEBUG_TYPE_ERROR:
1333 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1334 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1335 case GL_DEBUG_TYPE_PERFORMANCE:
1336 case GL_DEBUG_TYPE_PORTABILITY:
1337 case GL_DEBUG_TYPE_OTHER:
1338 case GL_DEBUG_TYPE_MARKER:
1339 case GL_DEBUG_TYPE_PUSH_GROUP:
1340 case GL_DEBUG_TYPE_POP_GROUP:
1341 return true;
1342
1343 default:
1344 return false;
1345 }
1346}
1347
1348static bool ValidDebugSeverity(GLenum severity)
1349{
1350 switch (severity)
1351 {
1352 case GL_DEBUG_SEVERITY_HIGH:
1353 case GL_DEBUG_SEVERITY_MEDIUM:
1354 case GL_DEBUG_SEVERITY_LOW:
1355 case GL_DEBUG_SEVERITY_NOTIFICATION:
1356 return true;
1357
1358 default:
1359 return false;
1360 }
1361}
1362
Geoff Lange102fee2015-12-10 11:23:30 -05001363bool ValidateDebugMessageControlKHR(Context *context,
1364 GLenum source,
1365 GLenum type,
1366 GLenum severity,
1367 GLsizei count,
1368 const GLuint *ids,
1369 GLboolean enabled)
1370{
1371 if (!context->getExtensions().debug)
1372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001374 return false;
1375 }
1376
Geoff Lang70d0f492015-12-10 17:45:46 -05001377 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1378 {
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001380 return false;
1381 }
1382
1383 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001386 return false;
1387 }
1388
1389 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1390 {
Jamie Madill437fa652016-05-03 15:13:24 -04001391 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001392 return false;
1393 }
1394
1395 if (count > 0)
1396 {
1397 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001400 GL_INVALID_OPERATION,
1401 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1402 return false;
1403 }
1404
1405 if (severity != GL_DONT_CARE)
1406 {
Jamie Madill437fa652016-05-03 15:13:24 -04001407 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001408 Error(GL_INVALID_OPERATION,
1409 "If count is greater than zero, severity must be GL_DONT_CARE."));
1410 return false;
1411 }
1412 }
1413
Geoff Lange102fee2015-12-10 11:23:30 -05001414 return true;
1415}
1416
1417bool ValidateDebugMessageInsertKHR(Context *context,
1418 GLenum source,
1419 GLenum type,
1420 GLuint id,
1421 GLenum severity,
1422 GLsizei length,
1423 const GLchar *buf)
1424{
1425 if (!context->getExtensions().debug)
1426 {
Jamie Madill437fa652016-05-03 15:13:24 -04001427 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001428 return false;
1429 }
1430
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001431 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001432 {
1433 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1434 // not generate an error.
1435 return false;
1436 }
1437
1438 if (!ValidDebugSeverity(severity))
1439 {
Jamie Madill437fa652016-05-03 15:13:24 -04001440 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001441 return false;
1442 }
1443
1444 if (!ValidDebugType(type))
1445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001447 return false;
1448 }
1449
1450 if (!ValidDebugSource(source, true))
1451 {
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001453 return false;
1454 }
1455
1456 size_t messageLength = (length < 0) ? strlen(buf) : length;
1457 if (messageLength > context->getExtensions().maxDebugMessageLength)
1458 {
Jamie Madill437fa652016-05-03 15:13:24 -04001459 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001460 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1461 return false;
1462 }
1463
Geoff Lange102fee2015-12-10 11:23:30 -05001464 return true;
1465}
1466
1467bool ValidateDebugMessageCallbackKHR(Context *context,
1468 GLDEBUGPROCKHR callback,
1469 const void *userParam)
1470{
1471 if (!context->getExtensions().debug)
1472 {
Jamie Madill437fa652016-05-03 15:13:24 -04001473 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001474 return false;
1475 }
1476
Geoff Lange102fee2015-12-10 11:23:30 -05001477 return true;
1478}
1479
1480bool ValidateGetDebugMessageLogKHR(Context *context,
1481 GLuint count,
1482 GLsizei bufSize,
1483 GLenum *sources,
1484 GLenum *types,
1485 GLuint *ids,
1486 GLenum *severities,
1487 GLsizei *lengths,
1488 GLchar *messageLog)
1489{
1490 if (!context->getExtensions().debug)
1491 {
Jamie Madill437fa652016-05-03 15:13:24 -04001492 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001493 return false;
1494 }
1495
Geoff Lang70d0f492015-12-10 17:45:46 -05001496 if (bufSize < 0 && messageLog != nullptr)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001499 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1500 return false;
1501 }
1502
Geoff Lange102fee2015-12-10 11:23:30 -05001503 return true;
1504}
1505
1506bool ValidatePushDebugGroupKHR(Context *context,
1507 GLenum source,
1508 GLuint id,
1509 GLsizei length,
1510 const GLchar *message)
1511{
1512 if (!context->getExtensions().debug)
1513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001515 return false;
1516 }
1517
Geoff Lang70d0f492015-12-10 17:45:46 -05001518 if (!ValidDebugSource(source, true))
1519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001521 return false;
1522 }
1523
1524 size_t messageLength = (length < 0) ? strlen(message) : length;
1525 if (messageLength > context->getExtensions().maxDebugMessageLength)
1526 {
Jamie Madill437fa652016-05-03 15:13:24 -04001527 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001528 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1529 return false;
1530 }
1531
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001532 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001533 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001536 Error(GL_STACK_OVERFLOW,
1537 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1538 return false;
1539 }
1540
Geoff Lange102fee2015-12-10 11:23:30 -05001541 return true;
1542}
1543
1544bool ValidatePopDebugGroupKHR(Context *context)
1545{
1546 if (!context->getExtensions().debug)
1547 {
Jamie Madill437fa652016-05-03 15:13:24 -04001548 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001549 return false;
1550 }
1551
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001552 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001553 if (currentStackSize <= 1)
1554 {
Jamie Madill437fa652016-05-03 15:13:24 -04001555 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001556 return false;
1557 }
1558
1559 return true;
1560}
1561
1562static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1563{
1564 switch (identifier)
1565 {
1566 case GL_BUFFER:
1567 if (context->getBuffer(name) == nullptr)
1568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001570 return false;
1571 }
1572 return true;
1573
1574 case GL_SHADER:
1575 if (context->getShader(name) == nullptr)
1576 {
Jamie Madill437fa652016-05-03 15:13:24 -04001577 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001578 return false;
1579 }
1580 return true;
1581
1582 case GL_PROGRAM:
1583 if (context->getProgram(name) == nullptr)
1584 {
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001586 return false;
1587 }
1588 return true;
1589
1590 case GL_VERTEX_ARRAY:
1591 if (context->getVertexArray(name) == nullptr)
1592 {
Jamie Madill437fa652016-05-03 15:13:24 -04001593 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001594 return false;
1595 }
1596 return true;
1597
1598 case GL_QUERY:
1599 if (context->getQuery(name) == nullptr)
1600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001602 return false;
1603 }
1604 return true;
1605
1606 case GL_TRANSFORM_FEEDBACK:
1607 if (context->getTransformFeedback(name) == nullptr)
1608 {
Jamie Madill437fa652016-05-03 15:13:24 -04001609 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001610 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1611 return false;
1612 }
1613 return true;
1614
1615 case GL_SAMPLER:
1616 if (context->getSampler(name) == nullptr)
1617 {
Jamie Madill437fa652016-05-03 15:13:24 -04001618 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001619 return false;
1620 }
1621 return true;
1622
1623 case GL_TEXTURE:
1624 if (context->getTexture(name) == nullptr)
1625 {
Jamie Madill437fa652016-05-03 15:13:24 -04001626 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001627 return false;
1628 }
1629 return true;
1630
1631 case GL_RENDERBUFFER:
1632 if (context->getRenderbuffer(name) == nullptr)
1633 {
Jamie Madill437fa652016-05-03 15:13:24 -04001634 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001635 return false;
1636 }
1637 return true;
1638
1639 case GL_FRAMEBUFFER:
1640 if (context->getFramebuffer(name) == nullptr)
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001643 return false;
1644 }
1645 return true;
1646
1647 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 return false;
1650 }
Geoff Lange102fee2015-12-10 11:23:30 -05001651}
1652
Martin Radev9d901792016-07-15 15:58:58 +03001653static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1654{
1655 size_t labelLength = 0;
1656
1657 if (length < 0)
1658 {
1659 if (label != nullptr)
1660 {
1661 labelLength = strlen(label);
1662 }
1663 }
1664 else
1665 {
1666 labelLength = static_cast<size_t>(length);
1667 }
1668
1669 if (labelLength > context->getExtensions().maxLabelLength)
1670 {
1671 context->handleError(
1672 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1673 return false;
1674 }
1675
1676 return true;
1677}
1678
Geoff Lange102fee2015-12-10 11:23:30 -05001679bool ValidateObjectLabelKHR(Context *context,
1680 GLenum identifier,
1681 GLuint name,
1682 GLsizei length,
1683 const GLchar *label)
1684{
1685 if (!context->getExtensions().debug)
1686 {
Jamie Madill437fa652016-05-03 15:13:24 -04001687 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001688 return false;
1689 }
1690
Geoff Lang70d0f492015-12-10 17:45:46 -05001691 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1692 {
1693 return false;
1694 }
1695
Martin Radev9d901792016-07-15 15:58:58 +03001696 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001697 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001698 return false;
1699 }
1700
Geoff Lange102fee2015-12-10 11:23:30 -05001701 return true;
1702}
1703
1704bool ValidateGetObjectLabelKHR(Context *context,
1705 GLenum identifier,
1706 GLuint name,
1707 GLsizei bufSize,
1708 GLsizei *length,
1709 GLchar *label)
1710{
1711 if (!context->getExtensions().debug)
1712 {
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001714 return false;
1715 }
1716
Geoff Lang70d0f492015-12-10 17:45:46 -05001717 if (bufSize < 0)
1718 {
Jamie Madill437fa652016-05-03 15:13:24 -04001719 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001720 return false;
1721 }
1722
1723 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1724 {
1725 return false;
1726 }
1727
Martin Radev9d901792016-07-15 15:58:58 +03001728 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001729}
1730
1731static bool ValidateObjectPtrName(Context *context, const void *ptr)
1732{
1733 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1734 {
Jamie Madill437fa652016-05-03 15:13:24 -04001735 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001736 return false;
1737 }
1738
Geoff Lange102fee2015-12-10 11:23:30 -05001739 return true;
1740}
1741
1742bool ValidateObjectPtrLabelKHR(Context *context,
1743 const void *ptr,
1744 GLsizei length,
1745 const GLchar *label)
1746{
1747 if (!context->getExtensions().debug)
1748 {
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001750 return false;
1751 }
1752
Geoff Lang70d0f492015-12-10 17:45:46 -05001753 if (!ValidateObjectPtrName(context, ptr))
1754 {
1755 return false;
1756 }
1757
Martin Radev9d901792016-07-15 15:58:58 +03001758 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001759 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001760 return false;
1761 }
1762
Geoff Lange102fee2015-12-10 11:23:30 -05001763 return true;
1764}
1765
1766bool ValidateGetObjectPtrLabelKHR(Context *context,
1767 const void *ptr,
1768 GLsizei bufSize,
1769 GLsizei *length,
1770 GLchar *label)
1771{
1772 if (!context->getExtensions().debug)
1773 {
Jamie Madill437fa652016-05-03 15:13:24 -04001774 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001775 return false;
1776 }
1777
Geoff Lang70d0f492015-12-10 17:45:46 -05001778 if (bufSize < 0)
1779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001781 return false;
1782 }
1783
1784 if (!ValidateObjectPtrName(context, ptr))
1785 {
1786 return false;
1787 }
1788
Martin Radev9d901792016-07-15 15:58:58 +03001789 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001790}
1791
1792bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1793{
1794 if (!context->getExtensions().debug)
1795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001797 return false;
1798 }
1799
Geoff Lang70d0f492015-12-10 17:45:46 -05001800 // TODO: represent this in Context::getQueryParameterInfo.
1801 switch (pname)
1802 {
1803 case GL_DEBUG_CALLBACK_FUNCTION:
1804 case GL_DEBUG_CALLBACK_USER_PARAM:
1805 break;
1806
1807 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001808 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001809 return false;
1810 }
1811
Geoff Lange102fee2015-12-10 11:23:30 -05001812 return true;
1813}
Jamie Madillc29968b2016-01-20 11:17:23 -05001814
1815bool ValidateBlitFramebufferANGLE(Context *context,
1816 GLint srcX0,
1817 GLint srcY0,
1818 GLint srcX1,
1819 GLint srcY1,
1820 GLint dstX0,
1821 GLint dstY0,
1822 GLint dstX1,
1823 GLint dstY1,
1824 GLbitfield mask,
1825 GLenum filter)
1826{
1827 if (!context->getExtensions().framebufferBlit)
1828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832
1833 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1834 {
1835 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001837 GL_INVALID_OPERATION,
1838 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1839 return false;
1840 }
1841
1842 if (filter == GL_LINEAR)
1843 {
Jamie Madill437fa652016-05-03 15:13:24 -04001844 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 return false;
1846 }
1847
Jamie Madill51f40ec2016-06-15 14:06:00 -04001848 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1849 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001850
1851 if (mask & GL_COLOR_BUFFER_BIT)
1852 {
1853 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1854 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1855
1856 if (readColorAttachment && drawColorAttachment)
1857 {
1858 if (!(readColorAttachment->type() == GL_TEXTURE &&
1859 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1860 readColorAttachment->type() != GL_RENDERBUFFER &&
1861 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return false;
1865 }
1866
Geoff Langa15472a2015-08-11 11:48:03 -04001867 for (size_t drawbufferIdx = 0;
1868 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 {
Geoff Langa15472a2015-08-11 11:48:03 -04001870 const FramebufferAttachment *attachment =
1871 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1872 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001873 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001874 if (!(attachment->type() == GL_TEXTURE &&
1875 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1876 attachment->type() != GL_RENDERBUFFER &&
1877 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
1883 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04001884 if (!Format::SameSized(attachment->getFormat(),
1885 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 {
Jamie Madill437fa652016-05-03 15:13:24 -04001887 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 return false;
1889 }
1890 }
1891 }
1892
Jamie Madill51f40ec2016-06-15 14:06:00 -04001893 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001894 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1895 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1896 {
Jamie Madill437fa652016-05-03 15:13:24 -04001897 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001898 return false;
1899 }
1900 }
1901 }
1902
1903 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1904 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1905 for (size_t i = 0; i < 2; i++)
1906 {
1907 if (mask & masks[i])
1908 {
1909 const FramebufferAttachment *readBuffer =
1910 readFramebuffer->getAttachment(attachments[i]);
1911 const FramebufferAttachment *drawBuffer =
1912 drawFramebuffer->getAttachment(attachments[i]);
1913
1914 if (readBuffer && drawBuffer)
1915 {
1916 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1917 dstX0, dstY0, dstX1, dstY1))
1918 {
1919 // only whole-buffer copies are permitted
1920 ERR(
1921 "Only whole-buffer depth and stencil blits are supported by this "
1922 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001923 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001924 return false;
1925 }
1926
1927 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1928 {
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 }
1934 }
1935
1936 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1937 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001938}
Jamie Madillc29968b2016-01-20 11:17:23 -05001939
1940bool ValidateClear(ValidationContext *context, GLbitfield mask)
1941{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001942 auto fbo = context->getGLState().getDrawFramebuffer();
1943 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001944 {
Jamie Madill437fa652016-05-03 15:13:24 -04001945 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001946 return false;
1947 }
1948
1949 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1950 {
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001952 return false;
1953 }
1954
1955 return true;
1956}
1957
1958bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1959{
1960 if (!context->getExtensions().drawBuffers)
1961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001963 return false;
1964 }
1965
1966 return ValidateDrawBuffersBase(context, n, bufs);
1967}
1968
Jamie Madill73a84962016-02-12 09:27:23 -05001969bool ValidateTexImage2D(Context *context,
1970 GLenum target,
1971 GLint level,
1972 GLint internalformat,
1973 GLsizei width,
1974 GLsizei height,
1975 GLint border,
1976 GLenum format,
1977 GLenum type,
1978 const GLvoid *pixels)
1979{
Martin Radev1be913c2016-07-11 17:59:16 +03001980 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05001981 {
1982 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04001983 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05001984 }
1985
Martin Radev1be913c2016-07-11 17:59:16 +03001986 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05001987 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04001988 0, 0, width, height, 1, border, format, type, -1,
1989 pixels);
1990}
1991
1992bool ValidateTexImage2DRobust(Context *context,
1993 GLenum target,
1994 GLint level,
1995 GLint internalformat,
1996 GLsizei width,
1997 GLsizei height,
1998 GLint border,
1999 GLenum format,
2000 GLenum type,
2001 GLsizei bufSize,
2002 const GLvoid *pixels)
2003{
2004 if (!ValidateRobustEntryPoint(context, bufSize))
2005 {
2006 return false;
2007 }
2008
2009 if (context->getClientMajorVersion() < 3)
2010 {
2011 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2012 0, 0, width, height, border, format, type, bufSize,
2013 pixels);
2014 }
2015
2016 ASSERT(context->getClientMajorVersion() >= 3);
2017 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2018 0, 0, width, height, 1, border, format, type, bufSize,
2019 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002020}
2021
2022bool ValidateTexSubImage2D(Context *context,
2023 GLenum target,
2024 GLint level,
2025 GLint xoffset,
2026 GLint yoffset,
2027 GLsizei width,
2028 GLsizei height,
2029 GLenum format,
2030 GLenum type,
2031 const GLvoid *pixels)
2032{
2033
Martin Radev1be913c2016-07-11 17:59:16 +03002034 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002035 {
2036 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002037 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002038 }
2039
Martin Radev1be913c2016-07-11 17:59:16 +03002040 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002041 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002042 yoffset, 0, width, height, 1, 0, format, type, -1,
2043 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002044}
2045
Geoff Langc52f6f12016-10-14 10:18:00 -04002046bool ValidateTexSubImage2DRobustANGLE(Context *context,
2047 GLenum target,
2048 GLint level,
2049 GLint xoffset,
2050 GLint yoffset,
2051 GLsizei width,
2052 GLsizei height,
2053 GLenum format,
2054 GLenum type,
2055 GLsizei bufSize,
2056 const GLvoid *pixels)
2057{
2058 if (!ValidateRobustEntryPoint(context, bufSize))
2059 {
2060 return false;
2061 }
2062
2063 if (context->getClientMajorVersion() < 3)
2064 {
2065 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2066 yoffset, width, height, 0, format, type, bufSize,
2067 pixels);
2068 }
2069
2070 ASSERT(context->getClientMajorVersion() >= 3);
2071 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2072 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2073 pixels);
2074}
2075
Jamie Madill73a84962016-02-12 09:27:23 -05002076bool ValidateCompressedTexImage2D(Context *context,
2077 GLenum target,
2078 GLint level,
2079 GLenum internalformat,
2080 GLsizei width,
2081 GLsizei height,
2082 GLint border,
2083 GLsizei imageSize,
2084 const GLvoid *data)
2085{
Martin Radev1be913c2016-07-11 17:59:16 +03002086 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002087 {
2088 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002089 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002090 {
2091 return false;
2092 }
2093 }
2094 else
2095 {
Martin Radev1be913c2016-07-11 17:59:16 +03002096 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002097 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002098 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002099 data))
2100 {
2101 return false;
2102 }
2103 }
2104
2105 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002106 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002107 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002108 if (blockSizeOrErr.isError())
2109 {
2110 context->handleError(blockSizeOrErr.getError());
2111 return false;
2112 }
2113
2114 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002115 {
Jamie Madill437fa652016-05-03 15:13:24 -04002116 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002117 return false;
2118 }
2119
2120 return true;
2121}
2122
2123bool ValidateCompressedTexSubImage2D(Context *context,
2124 GLenum target,
2125 GLint level,
2126 GLint xoffset,
2127 GLint yoffset,
2128 GLsizei width,
2129 GLsizei height,
2130 GLenum format,
2131 GLsizei imageSize,
2132 const GLvoid *data)
2133{
Martin Radev1be913c2016-07-11 17:59:16 +03002134 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002135 {
2136 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002137 yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002138 {
2139 return false;
2140 }
2141 }
2142 else
2143 {
Martin Radev1be913c2016-07-11 17:59:16 +03002144 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002145 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002146 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002147 data))
2148 {
2149 return false;
2150 }
2151 }
2152
2153 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002154 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002155 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002156 if (blockSizeOrErr.isError())
2157 {
2158 context->handleError(blockSizeOrErr.getError());
2159 return false;
2160 }
2161
2162 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002163 {
Jamie Madill437fa652016-05-03 15:13:24 -04002164 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002165 return false;
2166 }
2167
2168 return true;
2169}
2170
Olli Etuaho4f667482016-03-30 15:56:35 +03002171bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2172{
2173 if (!context->getExtensions().mapBuffer)
2174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002176 return false;
2177 }
2178
2179 return ValidateGetBufferPointervBase(context, target, pname, params);
2180}
2181
2182bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2183{
2184 if (!context->getExtensions().mapBuffer)
2185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002187 return false;
2188 }
2189
2190 if (!ValidBufferTarget(context, target))
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002193 return false;
2194 }
2195
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002196 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002197
2198 if (buffer == nullptr)
2199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002201 return false;
2202 }
2203
2204 if (access != GL_WRITE_ONLY_OES)
2205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 return false;
2208 }
2209
2210 if (buffer->isMapped())
2211 {
Jamie Madill437fa652016-05-03 15:13:24 -04002212 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002213 return false;
2214 }
2215
2216 return true;
2217}
2218
2219bool ValidateUnmapBufferOES(Context *context, GLenum target)
2220{
2221 if (!context->getExtensions().mapBuffer)
2222 {
Jamie Madill437fa652016-05-03 15:13:24 -04002223 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002224 return false;
2225 }
2226
2227 return ValidateUnmapBufferBase(context, target);
2228}
2229
2230bool ValidateMapBufferRangeEXT(Context *context,
2231 GLenum target,
2232 GLintptr offset,
2233 GLsizeiptr length,
2234 GLbitfield access)
2235{
2236 if (!context->getExtensions().mapBufferRange)
2237 {
Jamie Madill437fa652016-05-03 15:13:24 -04002238 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002239 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2240 return false;
2241 }
2242
2243 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2244}
2245
2246bool ValidateFlushMappedBufferRangeEXT(Context *context,
2247 GLenum target,
2248 GLintptr offset,
2249 GLsizeiptr length)
2250{
2251 if (!context->getExtensions().mapBufferRange)
2252 {
Jamie Madill437fa652016-05-03 15:13:24 -04002253 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002254 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2255 return false;
2256 }
2257
2258 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2259}
2260
Ian Ewell54f87462016-03-10 13:47:21 -05002261bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2262{
2263 Texture *textureObject = context->getTexture(texture);
2264 if (textureObject && textureObject->getTarget() != target && texture != 0)
2265 {
Jamie Madill437fa652016-05-03 15:13:24 -04002266 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002267 return false;
2268 }
2269
Geoff Langf41a7152016-09-19 15:11:17 -04002270 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2271 !context->isTextureGenerated(texture))
2272 {
2273 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2274 return false;
2275 }
2276
Ian Ewell54f87462016-03-10 13:47:21 -05002277 switch (target)
2278 {
2279 case GL_TEXTURE_2D:
2280 case GL_TEXTURE_CUBE_MAP:
2281 break;
2282
2283 case GL_TEXTURE_3D:
2284 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002285 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002286 {
Jamie Madill437fa652016-05-03 15:13:24 -04002287 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002288 return false;
2289 }
2290 break;
2291 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002292 if (!context->getExtensions().eglImageExternal &&
2293 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002294 {
Jamie Madill437fa652016-05-03 15:13:24 -04002295 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002296 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2297 return false;
2298 }
2299 break;
2300 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002301 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002302 return false;
2303 }
2304
2305 return true;
2306}
2307
Geoff Langd8605522016-04-13 10:19:12 -04002308bool ValidateBindUniformLocationCHROMIUM(Context *context,
2309 GLuint program,
2310 GLint location,
2311 const GLchar *name)
2312{
2313 if (!context->getExtensions().bindUniformLocation)
2314 {
Jamie Madill437fa652016-05-03 15:13:24 -04002315 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002316 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2317 return false;
2318 }
2319
2320 Program *programObject = GetValidProgram(context, program);
2321 if (!programObject)
2322 {
2323 return false;
2324 }
2325
2326 if (location < 0)
2327 {
Jamie Madill437fa652016-05-03 15:13:24 -04002328 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002329 return false;
2330 }
2331
2332 const Caps &caps = context->getCaps();
2333 if (static_cast<size_t>(location) >=
2334 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2335 {
Jamie Madill437fa652016-05-03 15:13:24 -04002336 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002337 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2338 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2339 return false;
2340 }
2341
2342 if (strncmp(name, "gl_", 3) == 0)
2343 {
Jamie Madill437fa652016-05-03 15:13:24 -04002344 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002345 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2346 return false;
2347 }
2348
2349 return true;
2350}
2351
Jamie Madille2e406c2016-06-02 13:04:10 -04002352bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002353{
2354 if (!context->getExtensions().framebufferMixedSamples)
2355 {
2356 context->handleError(
2357 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2358 return false;
2359 }
2360 switch (components)
2361 {
2362 case GL_RGB:
2363 case GL_RGBA:
2364 case GL_ALPHA:
2365 case GL_NONE:
2366 break;
2367 default:
2368 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002369 Error(GL_INVALID_ENUM,
2370 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002371 return false;
2372 }
2373
2374 return true;
2375}
2376
Sami Väisänene45e53b2016-05-25 10:36:04 +03002377// CHROMIUM_path_rendering
2378
2379bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2380{
2381 if (!context->getExtensions().pathRendering)
2382 {
2383 context->handleError(
2384 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2385 return false;
2386 }
2387 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2388 {
2389 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2390 return false;
2391 }
2392 if (matrix == nullptr)
2393 {
2394 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2395 return false;
2396 }
2397 return true;
2398}
2399
2400bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2401{
2402 if (!context->getExtensions().pathRendering)
2403 {
2404 context->handleError(
2405 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2406 return false;
2407 }
2408 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2409 {
2410 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2411 return false;
2412 }
2413 return true;
2414}
2415
2416bool ValidateGenPaths(Context *context, GLsizei range)
2417{
2418 if (!context->getExtensions().pathRendering)
2419 {
2420 context->handleError(
2421 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2422 return false;
2423 }
2424
2425 // range = 0 is undefined in NV_path_rendering.
2426 // we add stricter semantic check here and require a non zero positive range.
2427 if (range <= 0)
2428 {
2429 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2430 return false;
2431 }
2432
2433 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2434 {
2435 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2436 return false;
2437 }
2438
2439 return true;
2440}
2441
2442bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2443{
2444 if (!context->getExtensions().pathRendering)
2445 {
2446 context->handleError(
2447 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2448 return false;
2449 }
2450
2451 // range = 0 is undefined in NV_path_rendering.
2452 // we add stricter semantic check here and require a non zero positive range.
2453 if (range <= 0)
2454 {
2455 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2456 return false;
2457 }
2458
2459 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2460 checkedRange += range;
2461
2462 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2463 {
2464 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2465 return false;
2466 }
2467 return true;
2468}
2469
2470bool ValidatePathCommands(Context *context,
2471 GLuint path,
2472 GLsizei numCommands,
2473 const GLubyte *commands,
2474 GLsizei numCoords,
2475 GLenum coordType,
2476 const void *coords)
2477{
2478 if (!context->getExtensions().pathRendering)
2479 {
2480 context->handleError(
2481 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2482 return false;
2483 }
2484 if (!context->hasPath(path))
2485 {
2486 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2487 return false;
2488 }
2489
2490 if (numCommands < 0)
2491 {
2492 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2493 return false;
2494 }
2495 else if (numCommands > 0)
2496 {
2497 if (!commands)
2498 {
2499 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2500 return false;
2501 }
2502 }
2503
2504 if (numCoords < 0)
2505 {
2506 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2507 return false;
2508 }
2509 else if (numCoords > 0)
2510 {
2511 if (!coords)
2512 {
2513 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2514 return false;
2515 }
2516 }
2517
2518 std::uint32_t coordTypeSize = 0;
2519 switch (coordType)
2520 {
2521 case GL_BYTE:
2522 coordTypeSize = sizeof(GLbyte);
2523 break;
2524
2525 case GL_UNSIGNED_BYTE:
2526 coordTypeSize = sizeof(GLubyte);
2527 break;
2528
2529 case GL_SHORT:
2530 coordTypeSize = sizeof(GLshort);
2531 break;
2532
2533 case GL_UNSIGNED_SHORT:
2534 coordTypeSize = sizeof(GLushort);
2535 break;
2536
2537 case GL_FLOAT:
2538 coordTypeSize = sizeof(GLfloat);
2539 break;
2540
2541 default:
2542 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2543 return false;
2544 }
2545
2546 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2547 checkedSize += (coordTypeSize * numCoords);
2548 if (!checkedSize.IsValid())
2549 {
2550 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2551 return false;
2552 }
2553
2554 // early return skips command data validation when it doesn't exist.
2555 if (!commands)
2556 return true;
2557
2558 GLsizei expectedNumCoords = 0;
2559 for (GLsizei i = 0; i < numCommands; ++i)
2560 {
2561 switch (commands[i])
2562 {
2563 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2564 break;
2565 case GL_MOVE_TO_CHROMIUM:
2566 case GL_LINE_TO_CHROMIUM:
2567 expectedNumCoords += 2;
2568 break;
2569 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2570 expectedNumCoords += 4;
2571 break;
2572 case GL_CUBIC_CURVE_TO_CHROMIUM:
2573 expectedNumCoords += 6;
2574 break;
2575 case GL_CONIC_CURVE_TO_CHROMIUM:
2576 expectedNumCoords += 5;
2577 break;
2578 default:
2579 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2580 return false;
2581 }
2582 }
2583 if (expectedNumCoords != numCoords)
2584 {
2585 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2586 return false;
2587 }
2588
2589 return true;
2590}
2591
2592bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2593{
2594 if (!context->getExtensions().pathRendering)
2595 {
2596 context->handleError(
2597 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2598 return false;
2599 }
2600 if (!context->hasPath(path))
2601 {
2602 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2603 return false;
2604 }
2605
2606 switch (pname)
2607 {
2608 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2609 if (value < 0.0f)
2610 {
2611 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2612 return false;
2613 }
2614 break;
2615 case GL_PATH_END_CAPS_CHROMIUM:
2616 switch (static_cast<GLenum>(value))
2617 {
2618 case GL_FLAT_CHROMIUM:
2619 case GL_SQUARE_CHROMIUM:
2620 case GL_ROUND_CHROMIUM:
2621 break;
2622 default:
2623 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2624 return false;
2625 }
2626 break;
2627 case GL_PATH_JOIN_STYLE_CHROMIUM:
2628 switch (static_cast<GLenum>(value))
2629 {
2630 case GL_MITER_REVERT_CHROMIUM:
2631 case GL_BEVEL_CHROMIUM:
2632 case GL_ROUND_CHROMIUM:
2633 break;
2634 default:
2635 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2636 return false;
2637 }
2638 case GL_PATH_MITER_LIMIT_CHROMIUM:
2639 if (value < 0.0f)
2640 {
2641 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2642 return false;
2643 }
2644 break;
2645
2646 case GL_PATH_STROKE_BOUND_CHROMIUM:
2647 // no errors, only clamping.
2648 break;
2649
2650 default:
2651 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2652 return false;
2653 }
2654 return true;
2655}
2656
2657bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2658{
2659 if (!context->getExtensions().pathRendering)
2660 {
2661 context->handleError(
2662 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2663 return false;
2664 }
2665
2666 if (!context->hasPath(path))
2667 {
2668 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2669 return false;
2670 }
2671 if (!value)
2672 {
2673 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2674 return false;
2675 }
2676
2677 switch (pname)
2678 {
2679 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2680 case GL_PATH_END_CAPS_CHROMIUM:
2681 case GL_PATH_JOIN_STYLE_CHROMIUM:
2682 case GL_PATH_MITER_LIMIT_CHROMIUM:
2683 case GL_PATH_STROKE_BOUND_CHROMIUM:
2684 break;
2685
2686 default:
2687 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2688 return false;
2689 }
2690
2691 return true;
2692}
2693
2694bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2695{
2696 if (!context->getExtensions().pathRendering)
2697 {
2698 context->handleError(
2699 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2700 return false;
2701 }
2702
2703 switch (func)
2704 {
2705 case GL_NEVER:
2706 case GL_ALWAYS:
2707 case GL_LESS:
2708 case GL_LEQUAL:
2709 case GL_EQUAL:
2710 case GL_GEQUAL:
2711 case GL_GREATER:
2712 case GL_NOTEQUAL:
2713 break;
2714 default:
2715 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2716 return false;
2717 }
2718
2719 return true;
2720}
2721
2722// Note that the spec specifies that for the path drawing commands
2723// if the path object is not an existing path object the command
2724// does nothing and no error is generated.
2725// However if the path object exists but has not been specified any
2726// commands then an error is generated.
2727
2728bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2729{
2730 if (!context->getExtensions().pathRendering)
2731 {
2732 context->handleError(
2733 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2734 return false;
2735 }
2736 if (context->hasPath(path) && !context->hasPathData(path))
2737 {
2738 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2739 return false;
2740 }
2741
2742 switch (fillMode)
2743 {
2744 case GL_COUNT_UP_CHROMIUM:
2745 case GL_COUNT_DOWN_CHROMIUM:
2746 break;
2747 default:
2748 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2749 return false;
2750 }
2751
2752 if (!isPow2(mask + 1))
2753 {
2754 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2755 return false;
2756 }
2757
2758 return true;
2759}
2760
2761bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2762{
2763 if (!context->getExtensions().pathRendering)
2764 {
2765 context->handleError(
2766 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2767 return false;
2768 }
2769 if (context->hasPath(path) && !context->hasPathData(path))
2770 {
2771 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2772 return false;
2773 }
2774
2775 return true;
2776}
2777
2778bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2779{
2780 if (!context->getExtensions().pathRendering)
2781 {
2782 context->handleError(
2783 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2784 return false;
2785 }
2786 if (context->hasPath(path) && !context->hasPathData(path))
2787 {
2788 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2789 return false;
2790 }
2791
2792 switch (coverMode)
2793 {
2794 case GL_CONVEX_HULL_CHROMIUM:
2795 case GL_BOUNDING_BOX_CHROMIUM:
2796 break;
2797 default:
2798 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2799 return false;
2800 }
2801 return true;
2802}
2803
2804bool ValidateStencilThenCoverFillPath(Context *context,
2805 GLuint path,
2806 GLenum fillMode,
2807 GLuint mask,
2808 GLenum coverMode)
2809{
2810 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2811 ValidateCoverPath(context, path, coverMode);
2812}
2813
2814bool ValidateStencilThenCoverStrokePath(Context *context,
2815 GLuint path,
2816 GLint reference,
2817 GLuint mask,
2818 GLenum coverMode)
2819{
2820 return ValidateStencilStrokePath(context, path, reference, mask) &&
2821 ValidateCoverPath(context, path, coverMode);
2822}
2823
2824bool ValidateIsPath(Context *context)
2825{
2826 if (!context->getExtensions().pathRendering)
2827 {
2828 context->handleError(
2829 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2830 return false;
2831 }
2832 return true;
2833}
2834
Sami Väisänend59ca052016-06-21 16:10:00 +03002835bool ValidateCoverFillPathInstanced(Context *context,
2836 GLsizei numPaths,
2837 GLenum pathNameType,
2838 const void *paths,
2839 GLuint pathBase,
2840 GLenum coverMode,
2841 GLenum transformType,
2842 const GLfloat *transformValues)
2843{
2844 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2845 transformType, transformValues))
2846 return false;
2847
2848 switch (coverMode)
2849 {
2850 case GL_CONVEX_HULL_CHROMIUM:
2851 case GL_BOUNDING_BOX_CHROMIUM:
2852 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2853 break;
2854 default:
2855 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2856 return false;
2857 }
2858
2859 return true;
2860}
2861
2862bool ValidateCoverStrokePathInstanced(Context *context,
2863 GLsizei numPaths,
2864 GLenum pathNameType,
2865 const void *paths,
2866 GLuint pathBase,
2867 GLenum coverMode,
2868 GLenum transformType,
2869 const GLfloat *transformValues)
2870{
2871 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2872 transformType, transformValues))
2873 return false;
2874
2875 switch (coverMode)
2876 {
2877 case GL_CONVEX_HULL_CHROMIUM:
2878 case GL_BOUNDING_BOX_CHROMIUM:
2879 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2880 break;
2881 default:
2882 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2883 return false;
2884 }
2885
2886 return true;
2887}
2888
2889bool ValidateStencilFillPathInstanced(Context *context,
2890 GLsizei numPaths,
2891 GLenum pathNameType,
2892 const void *paths,
2893 GLuint pathBase,
2894 GLenum fillMode,
2895 GLuint mask,
2896 GLenum transformType,
2897 const GLfloat *transformValues)
2898{
2899
2900 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2901 transformType, transformValues))
2902 return false;
2903
2904 switch (fillMode)
2905 {
2906 case GL_COUNT_UP_CHROMIUM:
2907 case GL_COUNT_DOWN_CHROMIUM:
2908 break;
2909 default:
2910 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2911 return false;
2912 }
2913 if (!isPow2(mask + 1))
2914 {
2915 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2916 return false;
2917 }
2918 return true;
2919}
2920
2921bool ValidateStencilStrokePathInstanced(Context *context,
2922 GLsizei numPaths,
2923 GLenum pathNameType,
2924 const void *paths,
2925 GLuint pathBase,
2926 GLint reference,
2927 GLuint mask,
2928 GLenum transformType,
2929 const GLfloat *transformValues)
2930{
2931 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2932 transformType, transformValues))
2933 return false;
2934
2935 // no more validation here.
2936
2937 return true;
2938}
2939
2940bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2941 GLsizei numPaths,
2942 GLenum pathNameType,
2943 const void *paths,
2944 GLuint pathBase,
2945 GLenum fillMode,
2946 GLuint mask,
2947 GLenum coverMode,
2948 GLenum transformType,
2949 const GLfloat *transformValues)
2950{
2951 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2952 transformType, transformValues))
2953 return false;
2954
2955 switch (coverMode)
2956 {
2957 case GL_CONVEX_HULL_CHROMIUM:
2958 case GL_BOUNDING_BOX_CHROMIUM:
2959 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2960 break;
2961 default:
2962 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2963 return false;
2964 }
2965
2966 switch (fillMode)
2967 {
2968 case GL_COUNT_UP_CHROMIUM:
2969 case GL_COUNT_DOWN_CHROMIUM:
2970 break;
2971 default:
2972 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2973 return false;
2974 }
2975 if (!isPow2(mask + 1))
2976 {
2977 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2978 return false;
2979 }
2980
2981 return true;
2982}
2983
2984bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2985 GLsizei numPaths,
2986 GLenum pathNameType,
2987 const void *paths,
2988 GLuint pathBase,
2989 GLint reference,
2990 GLuint mask,
2991 GLenum coverMode,
2992 GLenum transformType,
2993 const GLfloat *transformValues)
2994{
2995 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2996 transformType, transformValues))
2997 return false;
2998
2999 switch (coverMode)
3000 {
3001 case GL_CONVEX_HULL_CHROMIUM:
3002 case GL_BOUNDING_BOX_CHROMIUM:
3003 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3004 break;
3005 default:
3006 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3007 return false;
3008 }
3009
3010 return true;
3011}
3012
Sami Väisänen46eaa942016-06-29 10:26:37 +03003013bool ValidateBindFragmentInputLocation(Context *context,
3014 GLuint program,
3015 GLint location,
3016 const GLchar *name)
3017{
3018 if (!context->getExtensions().pathRendering)
3019 {
3020 context->handleError(
3021 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3022 return false;
3023 }
3024
3025 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3026 if (location >= MaxLocation)
3027 {
3028 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3029 return false;
3030 }
3031
3032 const auto *programObject = context->getProgram(program);
3033 if (!programObject)
3034 {
3035 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3036 return false;
3037 }
3038
3039 if (!name)
3040 {
3041 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3042 return false;
3043 }
3044
3045 if (angle::BeginsWith(name, "gl_"))
3046 {
3047 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3048 return false;
3049 }
3050
3051 return true;
3052}
3053
3054bool ValidateProgramPathFragmentInputGen(Context *context,
3055 GLuint program,
3056 GLint location,
3057 GLenum genMode,
3058 GLint components,
3059 const GLfloat *coeffs)
3060{
3061 if (!context->getExtensions().pathRendering)
3062 {
3063 context->handleError(
3064 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3065 return false;
3066 }
3067
3068 const auto *programObject = context->getProgram(program);
3069 if (!programObject || programObject->isFlaggedForDeletion())
3070 {
3071 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3072 return false;
3073 }
3074
3075 if (!programObject->isLinked())
3076 {
3077 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3078 return false;
3079 }
3080
3081 switch (genMode)
3082 {
3083 case GL_NONE:
3084 if (components != 0)
3085 {
3086 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3087 return false;
3088 }
3089 break;
3090
3091 case GL_OBJECT_LINEAR_CHROMIUM:
3092 case GL_EYE_LINEAR_CHROMIUM:
3093 case GL_CONSTANT_CHROMIUM:
3094 if (components < 1 || components > 4)
3095 {
3096 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3097 return false;
3098 }
3099 if (!coeffs)
3100 {
3101 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3102 return false;
3103 }
3104 break;
3105
3106 default:
3107 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3108 return false;
3109 }
3110
3111 // If the location is -1 then the command is silently ignored
3112 // and no further validation is needed.
3113 if (location == -1)
3114 return true;
3115
3116 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3117
3118 if (!binding.valid)
3119 {
3120 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3121 return false;
3122 }
3123
3124 if (binding.type != GL_NONE)
3125 {
3126 GLint expectedComponents = 0;
3127 switch (binding.type)
3128 {
3129 case GL_FLOAT:
3130 expectedComponents = 1;
3131 break;
3132 case GL_FLOAT_VEC2:
3133 expectedComponents = 2;
3134 break;
3135 case GL_FLOAT_VEC3:
3136 expectedComponents = 3;
3137 break;
3138 case GL_FLOAT_VEC4:
3139 expectedComponents = 4;
3140 break;
3141 default:
3142 context->handleError(Error(GL_INVALID_OPERATION,
3143 "Fragment input type is not a floating point scalar or vector."));
3144 return false;
3145 }
3146 if (expectedComponents != components && genMode != GL_NONE)
3147 {
3148 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3149 return false;
3150 }
3151 }
3152 return true;
3153}
3154
Geoff Lang97073d12016-04-20 10:42:34 -07003155bool ValidateCopyTextureCHROMIUM(Context *context,
3156 GLuint sourceId,
3157 GLuint destId,
3158 GLint internalFormat,
3159 GLenum destType,
3160 GLboolean unpackFlipY,
3161 GLboolean unpackPremultiplyAlpha,
3162 GLboolean unpackUnmultiplyAlpha)
3163{
3164 if (!context->getExtensions().copyTexture)
3165 {
3166 context->handleError(
3167 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3168 return false;
3169 }
3170
3171 const gl::Texture *source = context->getTexture(sourceId);
3172 if (source == nullptr)
3173 {
3174 context->handleError(
3175 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3176 return false;
3177 }
3178
3179 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3180 {
3181 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3182 return false;
3183 }
3184
3185 GLenum sourceTarget = source->getTarget();
3186 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3187 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3188 {
3189 context->handleError(
3190 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3191 return false;
3192 }
3193
3194 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3195 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3196 {
3197 context->handleError(
3198 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3199 return false;
3200 }
3201
3202 const gl::Texture *dest = context->getTexture(destId);
3203 if (dest == nullptr)
3204 {
3205 context->handleError(
3206 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3207 return false;
3208 }
3209
3210 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3211 {
3212 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3213 return false;
3214 }
3215
3216 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3217 {
3218 context->handleError(
3219 Error(GL_INVALID_OPERATION,
3220 "Destination internal format and type combination is not valid."));
3221 return false;
3222 }
3223
3224 if (dest->getImmutableFormat())
3225 {
3226 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3227 return false;
3228 }
3229
3230 return true;
3231}
3232
3233bool ValidateCopySubTextureCHROMIUM(Context *context,
3234 GLuint sourceId,
3235 GLuint destId,
3236 GLint xoffset,
3237 GLint yoffset,
3238 GLint x,
3239 GLint y,
3240 GLsizei width,
3241 GLsizei height,
3242 GLboolean unpackFlipY,
3243 GLboolean unpackPremultiplyAlpha,
3244 GLboolean unpackUnmultiplyAlpha)
3245{
3246 if (!context->getExtensions().copyTexture)
3247 {
3248 context->handleError(
3249 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3250 return false;
3251 }
3252
3253 const gl::Texture *source = context->getTexture(sourceId);
3254 if (source == nullptr)
3255 {
3256 context->handleError(
3257 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3258 return false;
3259 }
3260
3261 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3262 {
3263 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3264 return false;
3265 }
3266
3267 GLenum sourceTarget = source->getTarget();
3268 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3269 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3270 {
3271 context->handleError(
3272 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3273 return false;
3274 }
3275
3276 if (x < 0 || y < 0)
3277 {
3278 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3279 return false;
3280 }
3281
3282 if (width < 0 || height < 0)
3283 {
3284 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3285 return false;
3286 }
3287
3288 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3289 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3290 {
3291 context->handleError(
3292 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3293 return false;
3294 }
3295
3296 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3297 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3298 {
3299 context->handleError(
3300 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3301 return false;
3302 }
3303
3304 const gl::Texture *dest = context->getTexture(destId);
3305 if (dest == nullptr)
3306 {
3307 context->handleError(
3308 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3309 return false;
3310 }
3311
3312 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3313 {
3314 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3315 return false;
3316 }
3317
3318 GLenum destTarget = dest->getTarget();
3319 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3320 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3321 {
3322 context->handleError(
3323 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3324 return false;
3325 }
3326
3327 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3328 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3329 {
3330 context->handleError(
3331 Error(GL_INVALID_OPERATION,
3332 "Destination internal format and type combination is not valid."));
3333 return false;
3334 }
3335
3336 if (xoffset < 0 || yoffset < 0)
3337 {
3338 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3339 return false;
3340 }
3341
3342 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3343 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3344 {
3345 context->handleError(
3346 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3347 return false;
3348 }
3349
3350 return true;
3351}
3352
Geoff Lang47110bf2016-04-20 11:13:22 -07003353bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3354{
3355 if (!context->getExtensions().copyCompressedTexture)
3356 {
3357 context->handleError(Error(GL_INVALID_OPERATION,
3358 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3359 return false;
3360 }
3361
3362 const gl::Texture *source = context->getTexture(sourceId);
3363 if (source == nullptr)
3364 {
3365 context->handleError(
3366 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3367 return false;
3368 }
3369
3370 if (source->getTarget() != GL_TEXTURE_2D)
3371 {
3372 context->handleError(
3373 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3374 return false;
3375 }
3376
3377 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3378 {
3379 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3380 return false;
3381 }
3382
3383 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3384 if (!sourceFormat.info->compressed)
3385 {
3386 context->handleError(
3387 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3388 return false;
3389 }
3390
3391 const gl::Texture *dest = context->getTexture(destId);
3392 if (dest == nullptr)
3393 {
3394 context->handleError(
3395 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3396 return false;
3397 }
3398
3399 if (dest->getTarget() != GL_TEXTURE_2D)
3400 {
3401 context->handleError(
3402 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3403 return false;
3404 }
3405
3406 if (dest->getImmutableFormat())
3407 {
3408 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3409 return false;
3410 }
3411
3412 return true;
3413}
3414
Martin Radev4c4c8e72016-08-04 12:25:34 +03003415bool ValidateCreateShader(Context *context, GLenum type)
3416{
3417 switch (type)
3418 {
3419 case GL_VERTEX_SHADER:
3420 case GL_FRAGMENT_SHADER:
3421 break;
3422 case GL_COMPUTE_SHADER:
3423 if (context->getGLVersion().isES31())
3424 {
3425 break;
3426 }
3427 default:
3428 context->handleError(Error(GL_INVALID_ENUM));
3429 return false;
3430 }
Jamie Madill29639852016-09-02 15:00:09 -04003431
3432 return true;
3433}
3434
3435bool ValidateBufferData(ValidationContext *context,
3436 GLenum target,
3437 GLsizeiptr size,
3438 const GLvoid *data,
3439 GLenum usage)
3440{
3441 if (size < 0)
3442 {
3443 context->handleError(Error(GL_INVALID_VALUE));
3444 return false;
3445 }
3446
3447 switch (usage)
3448 {
3449 case GL_STREAM_DRAW:
3450 case GL_STATIC_DRAW:
3451 case GL_DYNAMIC_DRAW:
3452 break;
3453
3454 case GL_STREAM_READ:
3455 case GL_STREAM_COPY:
3456 case GL_STATIC_READ:
3457 case GL_STATIC_COPY:
3458 case GL_DYNAMIC_READ:
3459 case GL_DYNAMIC_COPY:
3460 if (context->getClientMajorVersion() < 3)
3461 {
3462 context->handleError(Error(GL_INVALID_ENUM));
3463 return false;
3464 }
3465 break;
3466
3467 default:
3468 context->handleError(Error(GL_INVALID_ENUM));
3469 return false;
3470 }
3471
3472 if (!ValidBufferTarget(context, target))
3473 {
3474 context->handleError(Error(GL_INVALID_ENUM));
3475 return false;
3476 }
3477
3478 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3479
3480 if (!buffer)
3481 {
3482 context->handleError(Error(GL_INVALID_OPERATION));
3483 return false;
3484 }
3485
3486 return true;
3487}
3488
3489bool ValidateBufferSubData(ValidationContext *context,
3490 GLenum target,
3491 GLintptr offset,
3492 GLsizeiptr size,
3493 const GLvoid *data)
3494{
3495 if (size < 0 || offset < 0)
3496 {
3497 context->handleError(Error(GL_INVALID_VALUE));
3498 return false;
3499 }
3500
3501 if (!ValidBufferTarget(context, target))
3502 {
3503 context->handleError(Error(GL_INVALID_ENUM));
3504 return false;
3505 }
3506
3507 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3508
3509 if (!buffer)
3510 {
3511 context->handleError(Error(GL_INVALID_OPERATION));
3512 return false;
3513 }
3514
3515 if (buffer->isMapped())
3516 {
3517 context->handleError(Error(GL_INVALID_OPERATION));
3518 return false;
3519 }
3520
3521 // Check for possible overflow of size + offset
3522 angle::CheckedNumeric<size_t> checkedSize(size);
3523 checkedSize += offset;
3524 if (!checkedSize.IsValid())
3525 {
3526 context->handleError(Error(GL_OUT_OF_MEMORY));
3527 return false;
3528 }
3529
3530 if (size + offset > buffer->getSize())
3531 {
3532 context->handleError(Error(GL_INVALID_VALUE));
3533 return false;
3534 }
3535
Martin Radev4c4c8e72016-08-04 12:25:34 +03003536 return true;
3537}
3538
Geoff Langc287ea62016-09-16 14:46:51 -04003539bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3540{
3541 if (!context->getExtensions().webglCompatibility)
3542 {
3543 context->handleError(
3544 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3545 return false;
3546 }
3547
3548 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3549 auto extension = extensionInfos.find(name);
3550 if (extension == extensionInfos.end() || !extension->second.Enableable)
3551 {
3552 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3553 return false;
3554 }
3555
3556 return true;
3557}
3558
Jamie Madillef300b12016-10-07 15:12:09 -04003559bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3560{
3561 if (texture < GL_TEXTURE0 ||
3562 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3563 {
3564 context->handleError(Error(GL_INVALID_ENUM));
3565 return false;
3566 }
3567
3568 return true;
3569}
3570
3571bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3572{
3573 Program *programObject = GetValidProgram(context, program);
3574 if (!programObject)
3575 {
3576 return false;
3577 }
3578
3579 Shader *shaderObject = GetValidShader(context, shader);
3580 if (!shaderObject)
3581 {
3582 return false;
3583 }
3584
3585 switch (shaderObject->getType())
3586 {
3587 case GL_VERTEX_SHADER:
3588 {
3589 if (programObject->getAttachedVertexShader())
3590 {
3591 context->handleError(Error(GL_INVALID_OPERATION));
3592 return false;
3593 }
3594 break;
3595 }
3596 case GL_FRAGMENT_SHADER:
3597 {
3598 if (programObject->getAttachedFragmentShader())
3599 {
3600 context->handleError(Error(GL_INVALID_OPERATION));
3601 return false;
3602 }
3603 break;
3604 }
3605 case GL_COMPUTE_SHADER:
3606 {
3607 if (programObject->getAttachedComputeShader())
3608 {
3609 context->handleError(Error(GL_INVALID_OPERATION));
3610 return false;
3611 }
3612 break;
3613 }
3614 default:
3615 UNREACHABLE();
3616 break;
3617 }
3618
3619 return true;
3620}
3621
Jamie Madillc29968b2016-01-20 11:17:23 -05003622} // namespace gl