blob: b3de87e0097719e3f13a2717ecf2d0ddeb71910a [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{
Geoff Lang496c02d2016-10-20 11:38:11 -07002173 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002174}
2175
2176bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2177{
2178 if (!context->getExtensions().mapBuffer)
2179 {
Jamie Madill437fa652016-05-03 15:13:24 -04002180 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002181 return false;
2182 }
2183
2184 if (!ValidBufferTarget(context, target))
2185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002187 return false;
2188 }
2189
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002190 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002191
2192 if (buffer == nullptr)
2193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002195 return false;
2196 }
2197
2198 if (access != GL_WRITE_ONLY_OES)
2199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002201 return false;
2202 }
2203
2204 if (buffer->isMapped())
2205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002207 return false;
2208 }
2209
2210 return true;
2211}
2212
2213bool ValidateUnmapBufferOES(Context *context, GLenum target)
2214{
2215 if (!context->getExtensions().mapBuffer)
2216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002218 return false;
2219 }
2220
2221 return ValidateUnmapBufferBase(context, target);
2222}
2223
2224bool ValidateMapBufferRangeEXT(Context *context,
2225 GLenum target,
2226 GLintptr offset,
2227 GLsizeiptr length,
2228 GLbitfield access)
2229{
2230 if (!context->getExtensions().mapBufferRange)
2231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002233 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2234 return false;
2235 }
2236
2237 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2238}
2239
2240bool ValidateFlushMappedBufferRangeEXT(Context *context,
2241 GLenum target,
2242 GLintptr offset,
2243 GLsizeiptr length)
2244{
2245 if (!context->getExtensions().mapBufferRange)
2246 {
Jamie Madill437fa652016-05-03 15:13:24 -04002247 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002248 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2249 return false;
2250 }
2251
2252 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2253}
2254
Ian Ewell54f87462016-03-10 13:47:21 -05002255bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2256{
2257 Texture *textureObject = context->getTexture(texture);
2258 if (textureObject && textureObject->getTarget() != target && texture != 0)
2259 {
Jamie Madill437fa652016-05-03 15:13:24 -04002260 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002261 return false;
2262 }
2263
Geoff Langf41a7152016-09-19 15:11:17 -04002264 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2265 !context->isTextureGenerated(texture))
2266 {
2267 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2268 return false;
2269 }
2270
Ian Ewell54f87462016-03-10 13:47:21 -05002271 switch (target)
2272 {
2273 case GL_TEXTURE_2D:
2274 case GL_TEXTURE_CUBE_MAP:
2275 break;
2276
2277 case GL_TEXTURE_3D:
2278 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002279 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002280 {
Jamie Madill437fa652016-05-03 15:13:24 -04002281 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002282 return false;
2283 }
2284 break;
2285 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002286 if (!context->getExtensions().eglImageExternal &&
2287 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002288 {
Jamie Madill437fa652016-05-03 15:13:24 -04002289 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002290 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2291 return false;
2292 }
2293 break;
2294 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002295 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002296 return false;
2297 }
2298
2299 return true;
2300}
2301
Geoff Langd8605522016-04-13 10:19:12 -04002302bool ValidateBindUniformLocationCHROMIUM(Context *context,
2303 GLuint program,
2304 GLint location,
2305 const GLchar *name)
2306{
2307 if (!context->getExtensions().bindUniformLocation)
2308 {
Jamie Madill437fa652016-05-03 15:13:24 -04002309 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002310 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2311 return false;
2312 }
2313
2314 Program *programObject = GetValidProgram(context, program);
2315 if (!programObject)
2316 {
2317 return false;
2318 }
2319
2320 if (location < 0)
2321 {
Jamie Madill437fa652016-05-03 15:13:24 -04002322 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002323 return false;
2324 }
2325
2326 const Caps &caps = context->getCaps();
2327 if (static_cast<size_t>(location) >=
2328 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2329 {
Jamie Madill437fa652016-05-03 15:13:24 -04002330 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002331 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2332 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2333 return false;
2334 }
2335
2336 if (strncmp(name, "gl_", 3) == 0)
2337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002339 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2340 return false;
2341 }
2342
2343 return true;
2344}
2345
Jamie Madille2e406c2016-06-02 13:04:10 -04002346bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002347{
2348 if (!context->getExtensions().framebufferMixedSamples)
2349 {
2350 context->handleError(
2351 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2352 return false;
2353 }
2354 switch (components)
2355 {
2356 case GL_RGB:
2357 case GL_RGBA:
2358 case GL_ALPHA:
2359 case GL_NONE:
2360 break;
2361 default:
2362 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002363 Error(GL_INVALID_ENUM,
2364 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002365 return false;
2366 }
2367
2368 return true;
2369}
2370
Sami Väisänene45e53b2016-05-25 10:36:04 +03002371// CHROMIUM_path_rendering
2372
2373bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2374{
2375 if (!context->getExtensions().pathRendering)
2376 {
2377 context->handleError(
2378 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2379 return false;
2380 }
2381 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2382 {
2383 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2384 return false;
2385 }
2386 if (matrix == nullptr)
2387 {
2388 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2389 return false;
2390 }
2391 return true;
2392}
2393
2394bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2395{
2396 if (!context->getExtensions().pathRendering)
2397 {
2398 context->handleError(
2399 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2400 return false;
2401 }
2402 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2403 {
2404 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2405 return false;
2406 }
2407 return true;
2408}
2409
2410bool ValidateGenPaths(Context *context, GLsizei range)
2411{
2412 if (!context->getExtensions().pathRendering)
2413 {
2414 context->handleError(
2415 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2416 return false;
2417 }
2418
2419 // range = 0 is undefined in NV_path_rendering.
2420 // we add stricter semantic check here and require a non zero positive range.
2421 if (range <= 0)
2422 {
2423 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2424 return false;
2425 }
2426
2427 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2428 {
2429 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2430 return false;
2431 }
2432
2433 return true;
2434}
2435
2436bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2437{
2438 if (!context->getExtensions().pathRendering)
2439 {
2440 context->handleError(
2441 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2442 return false;
2443 }
2444
2445 // range = 0 is undefined in NV_path_rendering.
2446 // we add stricter semantic check here and require a non zero positive range.
2447 if (range <= 0)
2448 {
2449 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2450 return false;
2451 }
2452
2453 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2454 checkedRange += range;
2455
2456 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2457 {
2458 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2459 return false;
2460 }
2461 return true;
2462}
2463
2464bool ValidatePathCommands(Context *context,
2465 GLuint path,
2466 GLsizei numCommands,
2467 const GLubyte *commands,
2468 GLsizei numCoords,
2469 GLenum coordType,
2470 const void *coords)
2471{
2472 if (!context->getExtensions().pathRendering)
2473 {
2474 context->handleError(
2475 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2476 return false;
2477 }
2478 if (!context->hasPath(path))
2479 {
2480 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2481 return false;
2482 }
2483
2484 if (numCommands < 0)
2485 {
2486 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2487 return false;
2488 }
2489 else if (numCommands > 0)
2490 {
2491 if (!commands)
2492 {
2493 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2494 return false;
2495 }
2496 }
2497
2498 if (numCoords < 0)
2499 {
2500 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2501 return false;
2502 }
2503 else if (numCoords > 0)
2504 {
2505 if (!coords)
2506 {
2507 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2508 return false;
2509 }
2510 }
2511
2512 std::uint32_t coordTypeSize = 0;
2513 switch (coordType)
2514 {
2515 case GL_BYTE:
2516 coordTypeSize = sizeof(GLbyte);
2517 break;
2518
2519 case GL_UNSIGNED_BYTE:
2520 coordTypeSize = sizeof(GLubyte);
2521 break;
2522
2523 case GL_SHORT:
2524 coordTypeSize = sizeof(GLshort);
2525 break;
2526
2527 case GL_UNSIGNED_SHORT:
2528 coordTypeSize = sizeof(GLushort);
2529 break;
2530
2531 case GL_FLOAT:
2532 coordTypeSize = sizeof(GLfloat);
2533 break;
2534
2535 default:
2536 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2537 return false;
2538 }
2539
2540 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2541 checkedSize += (coordTypeSize * numCoords);
2542 if (!checkedSize.IsValid())
2543 {
2544 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2545 return false;
2546 }
2547
2548 // early return skips command data validation when it doesn't exist.
2549 if (!commands)
2550 return true;
2551
2552 GLsizei expectedNumCoords = 0;
2553 for (GLsizei i = 0; i < numCommands; ++i)
2554 {
2555 switch (commands[i])
2556 {
2557 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2558 break;
2559 case GL_MOVE_TO_CHROMIUM:
2560 case GL_LINE_TO_CHROMIUM:
2561 expectedNumCoords += 2;
2562 break;
2563 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2564 expectedNumCoords += 4;
2565 break;
2566 case GL_CUBIC_CURVE_TO_CHROMIUM:
2567 expectedNumCoords += 6;
2568 break;
2569 case GL_CONIC_CURVE_TO_CHROMIUM:
2570 expectedNumCoords += 5;
2571 break;
2572 default:
2573 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2574 return false;
2575 }
2576 }
2577 if (expectedNumCoords != numCoords)
2578 {
2579 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2580 return false;
2581 }
2582
2583 return true;
2584}
2585
2586bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2587{
2588 if (!context->getExtensions().pathRendering)
2589 {
2590 context->handleError(
2591 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2592 return false;
2593 }
2594 if (!context->hasPath(path))
2595 {
2596 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2597 return false;
2598 }
2599
2600 switch (pname)
2601 {
2602 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2603 if (value < 0.0f)
2604 {
2605 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2606 return false;
2607 }
2608 break;
2609 case GL_PATH_END_CAPS_CHROMIUM:
2610 switch (static_cast<GLenum>(value))
2611 {
2612 case GL_FLAT_CHROMIUM:
2613 case GL_SQUARE_CHROMIUM:
2614 case GL_ROUND_CHROMIUM:
2615 break;
2616 default:
2617 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2618 return false;
2619 }
2620 break;
2621 case GL_PATH_JOIN_STYLE_CHROMIUM:
2622 switch (static_cast<GLenum>(value))
2623 {
2624 case GL_MITER_REVERT_CHROMIUM:
2625 case GL_BEVEL_CHROMIUM:
2626 case GL_ROUND_CHROMIUM:
2627 break;
2628 default:
2629 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2630 return false;
2631 }
2632 case GL_PATH_MITER_LIMIT_CHROMIUM:
2633 if (value < 0.0f)
2634 {
2635 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2636 return false;
2637 }
2638 break;
2639
2640 case GL_PATH_STROKE_BOUND_CHROMIUM:
2641 // no errors, only clamping.
2642 break;
2643
2644 default:
2645 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2646 return false;
2647 }
2648 return true;
2649}
2650
2651bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2652{
2653 if (!context->getExtensions().pathRendering)
2654 {
2655 context->handleError(
2656 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2657 return false;
2658 }
2659
2660 if (!context->hasPath(path))
2661 {
2662 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2663 return false;
2664 }
2665 if (!value)
2666 {
2667 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2668 return false;
2669 }
2670
2671 switch (pname)
2672 {
2673 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2674 case GL_PATH_END_CAPS_CHROMIUM:
2675 case GL_PATH_JOIN_STYLE_CHROMIUM:
2676 case GL_PATH_MITER_LIMIT_CHROMIUM:
2677 case GL_PATH_STROKE_BOUND_CHROMIUM:
2678 break;
2679
2680 default:
2681 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2682 return false;
2683 }
2684
2685 return true;
2686}
2687
2688bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2689{
2690 if (!context->getExtensions().pathRendering)
2691 {
2692 context->handleError(
2693 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2694 return false;
2695 }
2696
2697 switch (func)
2698 {
2699 case GL_NEVER:
2700 case GL_ALWAYS:
2701 case GL_LESS:
2702 case GL_LEQUAL:
2703 case GL_EQUAL:
2704 case GL_GEQUAL:
2705 case GL_GREATER:
2706 case GL_NOTEQUAL:
2707 break;
2708 default:
2709 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2710 return false;
2711 }
2712
2713 return true;
2714}
2715
2716// Note that the spec specifies that for the path drawing commands
2717// if the path object is not an existing path object the command
2718// does nothing and no error is generated.
2719// However if the path object exists but has not been specified any
2720// commands then an error is generated.
2721
2722bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2723{
2724 if (!context->getExtensions().pathRendering)
2725 {
2726 context->handleError(
2727 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2728 return false;
2729 }
2730 if (context->hasPath(path) && !context->hasPathData(path))
2731 {
2732 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2733 return false;
2734 }
2735
2736 switch (fillMode)
2737 {
2738 case GL_COUNT_UP_CHROMIUM:
2739 case GL_COUNT_DOWN_CHROMIUM:
2740 break;
2741 default:
2742 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2743 return false;
2744 }
2745
2746 if (!isPow2(mask + 1))
2747 {
2748 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2749 return false;
2750 }
2751
2752 return true;
2753}
2754
2755bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2756{
2757 if (!context->getExtensions().pathRendering)
2758 {
2759 context->handleError(
2760 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2761 return false;
2762 }
2763 if (context->hasPath(path) && !context->hasPathData(path))
2764 {
2765 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2766 return false;
2767 }
2768
2769 return true;
2770}
2771
2772bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2773{
2774 if (!context->getExtensions().pathRendering)
2775 {
2776 context->handleError(
2777 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2778 return false;
2779 }
2780 if (context->hasPath(path) && !context->hasPathData(path))
2781 {
2782 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2783 return false;
2784 }
2785
2786 switch (coverMode)
2787 {
2788 case GL_CONVEX_HULL_CHROMIUM:
2789 case GL_BOUNDING_BOX_CHROMIUM:
2790 break;
2791 default:
2792 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2793 return false;
2794 }
2795 return true;
2796}
2797
2798bool ValidateStencilThenCoverFillPath(Context *context,
2799 GLuint path,
2800 GLenum fillMode,
2801 GLuint mask,
2802 GLenum coverMode)
2803{
2804 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2805 ValidateCoverPath(context, path, coverMode);
2806}
2807
2808bool ValidateStencilThenCoverStrokePath(Context *context,
2809 GLuint path,
2810 GLint reference,
2811 GLuint mask,
2812 GLenum coverMode)
2813{
2814 return ValidateStencilStrokePath(context, path, reference, mask) &&
2815 ValidateCoverPath(context, path, coverMode);
2816}
2817
2818bool ValidateIsPath(Context *context)
2819{
2820 if (!context->getExtensions().pathRendering)
2821 {
2822 context->handleError(
2823 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2824 return false;
2825 }
2826 return true;
2827}
2828
Sami Väisänend59ca052016-06-21 16:10:00 +03002829bool ValidateCoverFillPathInstanced(Context *context,
2830 GLsizei numPaths,
2831 GLenum pathNameType,
2832 const void *paths,
2833 GLuint pathBase,
2834 GLenum coverMode,
2835 GLenum transformType,
2836 const GLfloat *transformValues)
2837{
2838 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2839 transformType, transformValues))
2840 return false;
2841
2842 switch (coverMode)
2843 {
2844 case GL_CONVEX_HULL_CHROMIUM:
2845 case GL_BOUNDING_BOX_CHROMIUM:
2846 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2847 break;
2848 default:
2849 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2850 return false;
2851 }
2852
2853 return true;
2854}
2855
2856bool ValidateCoverStrokePathInstanced(Context *context,
2857 GLsizei numPaths,
2858 GLenum pathNameType,
2859 const void *paths,
2860 GLuint pathBase,
2861 GLenum coverMode,
2862 GLenum transformType,
2863 const GLfloat *transformValues)
2864{
2865 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2866 transformType, transformValues))
2867 return false;
2868
2869 switch (coverMode)
2870 {
2871 case GL_CONVEX_HULL_CHROMIUM:
2872 case GL_BOUNDING_BOX_CHROMIUM:
2873 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2874 break;
2875 default:
2876 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2877 return false;
2878 }
2879
2880 return true;
2881}
2882
2883bool ValidateStencilFillPathInstanced(Context *context,
2884 GLsizei numPaths,
2885 GLenum pathNameType,
2886 const void *paths,
2887 GLuint pathBase,
2888 GLenum fillMode,
2889 GLuint mask,
2890 GLenum transformType,
2891 const GLfloat *transformValues)
2892{
2893
2894 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2895 transformType, transformValues))
2896 return false;
2897
2898 switch (fillMode)
2899 {
2900 case GL_COUNT_UP_CHROMIUM:
2901 case GL_COUNT_DOWN_CHROMIUM:
2902 break;
2903 default:
2904 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2905 return false;
2906 }
2907 if (!isPow2(mask + 1))
2908 {
2909 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2910 return false;
2911 }
2912 return true;
2913}
2914
2915bool ValidateStencilStrokePathInstanced(Context *context,
2916 GLsizei numPaths,
2917 GLenum pathNameType,
2918 const void *paths,
2919 GLuint pathBase,
2920 GLint reference,
2921 GLuint mask,
2922 GLenum transformType,
2923 const GLfloat *transformValues)
2924{
2925 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2926 transformType, transformValues))
2927 return false;
2928
2929 // no more validation here.
2930
2931 return true;
2932}
2933
2934bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2935 GLsizei numPaths,
2936 GLenum pathNameType,
2937 const void *paths,
2938 GLuint pathBase,
2939 GLenum fillMode,
2940 GLuint mask,
2941 GLenum coverMode,
2942 GLenum transformType,
2943 const GLfloat *transformValues)
2944{
2945 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2946 transformType, transformValues))
2947 return false;
2948
2949 switch (coverMode)
2950 {
2951 case GL_CONVEX_HULL_CHROMIUM:
2952 case GL_BOUNDING_BOX_CHROMIUM:
2953 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2954 break;
2955 default:
2956 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2957 return false;
2958 }
2959
2960 switch (fillMode)
2961 {
2962 case GL_COUNT_UP_CHROMIUM:
2963 case GL_COUNT_DOWN_CHROMIUM:
2964 break;
2965 default:
2966 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2967 return false;
2968 }
2969 if (!isPow2(mask + 1))
2970 {
2971 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2972 return false;
2973 }
2974
2975 return true;
2976}
2977
2978bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2979 GLsizei numPaths,
2980 GLenum pathNameType,
2981 const void *paths,
2982 GLuint pathBase,
2983 GLint reference,
2984 GLuint mask,
2985 GLenum coverMode,
2986 GLenum transformType,
2987 const GLfloat *transformValues)
2988{
2989 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2990 transformType, transformValues))
2991 return false;
2992
2993 switch (coverMode)
2994 {
2995 case GL_CONVEX_HULL_CHROMIUM:
2996 case GL_BOUNDING_BOX_CHROMIUM:
2997 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2998 break;
2999 default:
3000 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3001 return false;
3002 }
3003
3004 return true;
3005}
3006
Sami Väisänen46eaa942016-06-29 10:26:37 +03003007bool ValidateBindFragmentInputLocation(Context *context,
3008 GLuint program,
3009 GLint location,
3010 const GLchar *name)
3011{
3012 if (!context->getExtensions().pathRendering)
3013 {
3014 context->handleError(
3015 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3016 return false;
3017 }
3018
3019 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3020 if (location >= MaxLocation)
3021 {
3022 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3023 return false;
3024 }
3025
3026 const auto *programObject = context->getProgram(program);
3027 if (!programObject)
3028 {
3029 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3030 return false;
3031 }
3032
3033 if (!name)
3034 {
3035 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3036 return false;
3037 }
3038
3039 if (angle::BeginsWith(name, "gl_"))
3040 {
3041 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3042 return false;
3043 }
3044
3045 return true;
3046}
3047
3048bool ValidateProgramPathFragmentInputGen(Context *context,
3049 GLuint program,
3050 GLint location,
3051 GLenum genMode,
3052 GLint components,
3053 const GLfloat *coeffs)
3054{
3055 if (!context->getExtensions().pathRendering)
3056 {
3057 context->handleError(
3058 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3059 return false;
3060 }
3061
3062 const auto *programObject = context->getProgram(program);
3063 if (!programObject || programObject->isFlaggedForDeletion())
3064 {
3065 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3066 return false;
3067 }
3068
3069 if (!programObject->isLinked())
3070 {
3071 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3072 return false;
3073 }
3074
3075 switch (genMode)
3076 {
3077 case GL_NONE:
3078 if (components != 0)
3079 {
3080 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3081 return false;
3082 }
3083 break;
3084
3085 case GL_OBJECT_LINEAR_CHROMIUM:
3086 case GL_EYE_LINEAR_CHROMIUM:
3087 case GL_CONSTANT_CHROMIUM:
3088 if (components < 1 || components > 4)
3089 {
3090 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3091 return false;
3092 }
3093 if (!coeffs)
3094 {
3095 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3096 return false;
3097 }
3098 break;
3099
3100 default:
3101 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3102 return false;
3103 }
3104
3105 // If the location is -1 then the command is silently ignored
3106 // and no further validation is needed.
3107 if (location == -1)
3108 return true;
3109
3110 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3111
3112 if (!binding.valid)
3113 {
3114 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3115 return false;
3116 }
3117
3118 if (binding.type != GL_NONE)
3119 {
3120 GLint expectedComponents = 0;
3121 switch (binding.type)
3122 {
3123 case GL_FLOAT:
3124 expectedComponents = 1;
3125 break;
3126 case GL_FLOAT_VEC2:
3127 expectedComponents = 2;
3128 break;
3129 case GL_FLOAT_VEC3:
3130 expectedComponents = 3;
3131 break;
3132 case GL_FLOAT_VEC4:
3133 expectedComponents = 4;
3134 break;
3135 default:
3136 context->handleError(Error(GL_INVALID_OPERATION,
3137 "Fragment input type is not a floating point scalar or vector."));
3138 return false;
3139 }
3140 if (expectedComponents != components && genMode != GL_NONE)
3141 {
3142 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3143 return false;
3144 }
3145 }
3146 return true;
3147}
3148
Geoff Lang97073d12016-04-20 10:42:34 -07003149bool ValidateCopyTextureCHROMIUM(Context *context,
3150 GLuint sourceId,
3151 GLuint destId,
3152 GLint internalFormat,
3153 GLenum destType,
3154 GLboolean unpackFlipY,
3155 GLboolean unpackPremultiplyAlpha,
3156 GLboolean unpackUnmultiplyAlpha)
3157{
3158 if (!context->getExtensions().copyTexture)
3159 {
3160 context->handleError(
3161 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3162 return false;
3163 }
3164
3165 const gl::Texture *source = context->getTexture(sourceId);
3166 if (source == nullptr)
3167 {
3168 context->handleError(
3169 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3170 return false;
3171 }
3172
3173 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3174 {
3175 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3176 return false;
3177 }
3178
3179 GLenum sourceTarget = source->getTarget();
3180 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3181 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3182 {
3183 context->handleError(
3184 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3185 return false;
3186 }
3187
3188 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3189 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3190 {
3191 context->handleError(
3192 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3193 return false;
3194 }
3195
3196 const gl::Texture *dest = context->getTexture(destId);
3197 if (dest == nullptr)
3198 {
3199 context->handleError(
3200 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3201 return false;
3202 }
3203
3204 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3205 {
3206 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3207 return false;
3208 }
3209
3210 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3211 {
3212 context->handleError(
3213 Error(GL_INVALID_OPERATION,
3214 "Destination internal format and type combination is not valid."));
3215 return false;
3216 }
3217
3218 if (dest->getImmutableFormat())
3219 {
3220 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3221 return false;
3222 }
3223
3224 return true;
3225}
3226
3227bool ValidateCopySubTextureCHROMIUM(Context *context,
3228 GLuint sourceId,
3229 GLuint destId,
3230 GLint xoffset,
3231 GLint yoffset,
3232 GLint x,
3233 GLint y,
3234 GLsizei width,
3235 GLsizei height,
3236 GLboolean unpackFlipY,
3237 GLboolean unpackPremultiplyAlpha,
3238 GLboolean unpackUnmultiplyAlpha)
3239{
3240 if (!context->getExtensions().copyTexture)
3241 {
3242 context->handleError(
3243 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3244 return false;
3245 }
3246
3247 const gl::Texture *source = context->getTexture(sourceId);
3248 if (source == nullptr)
3249 {
3250 context->handleError(
3251 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3252 return false;
3253 }
3254
3255 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3256 {
3257 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3258 return false;
3259 }
3260
3261 GLenum sourceTarget = source->getTarget();
3262 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3263 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3264 {
3265 context->handleError(
3266 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3267 return false;
3268 }
3269
3270 if (x < 0 || y < 0)
3271 {
3272 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3273 return false;
3274 }
3275
3276 if (width < 0 || height < 0)
3277 {
3278 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3279 return false;
3280 }
3281
3282 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3283 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3284 {
3285 context->handleError(
3286 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3287 return false;
3288 }
3289
3290 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
3291 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3292 {
3293 context->handleError(
3294 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3295 return false;
3296 }
3297
3298 const gl::Texture *dest = context->getTexture(destId);
3299 if (dest == nullptr)
3300 {
3301 context->handleError(
3302 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3303 return false;
3304 }
3305
3306 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3307 {
3308 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3309 return false;
3310 }
3311
3312 GLenum destTarget = dest->getTarget();
3313 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3314 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3315 {
3316 context->handleError(
3317 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3318 return false;
3319 }
3320
3321 const gl::Format &destFormat = dest->getFormat(destTarget, 0);
3322 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3323 {
3324 context->handleError(
3325 Error(GL_INVALID_OPERATION,
3326 "Destination internal format and type combination is not valid."));
3327 return false;
3328 }
3329
3330 if (xoffset < 0 || yoffset < 0)
3331 {
3332 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3333 return false;
3334 }
3335
3336 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3337 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3338 {
3339 context->handleError(
3340 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3341 return false;
3342 }
3343
3344 return true;
3345}
3346
Geoff Lang47110bf2016-04-20 11:13:22 -07003347bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3348{
3349 if (!context->getExtensions().copyCompressedTexture)
3350 {
3351 context->handleError(Error(GL_INVALID_OPERATION,
3352 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3353 return false;
3354 }
3355
3356 const gl::Texture *source = context->getTexture(sourceId);
3357 if (source == nullptr)
3358 {
3359 context->handleError(
3360 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3361 return false;
3362 }
3363
3364 if (source->getTarget() != GL_TEXTURE_2D)
3365 {
3366 context->handleError(
3367 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3368 return false;
3369 }
3370
3371 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3372 {
3373 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3374 return false;
3375 }
3376
3377 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3378 if (!sourceFormat.info->compressed)
3379 {
3380 context->handleError(
3381 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3382 return false;
3383 }
3384
3385 const gl::Texture *dest = context->getTexture(destId);
3386 if (dest == nullptr)
3387 {
3388 context->handleError(
3389 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3390 return false;
3391 }
3392
3393 if (dest->getTarget() != GL_TEXTURE_2D)
3394 {
3395 context->handleError(
3396 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3397 return false;
3398 }
3399
3400 if (dest->getImmutableFormat())
3401 {
3402 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3403 return false;
3404 }
3405
3406 return true;
3407}
3408
Martin Radev4c4c8e72016-08-04 12:25:34 +03003409bool ValidateCreateShader(Context *context, GLenum type)
3410{
3411 switch (type)
3412 {
3413 case GL_VERTEX_SHADER:
3414 case GL_FRAGMENT_SHADER:
3415 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003416
Martin Radev4c4c8e72016-08-04 12:25:34 +03003417 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003418 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003419 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003420 context->handleError(
3421 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3422 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003423 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003424 break;
3425
Martin Radev4c4c8e72016-08-04 12:25:34 +03003426 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003427 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003428 return false;
3429 }
Jamie Madill29639852016-09-02 15:00:09 -04003430
3431 return true;
3432}
3433
3434bool ValidateBufferData(ValidationContext *context,
3435 GLenum target,
3436 GLsizeiptr size,
3437 const GLvoid *data,
3438 GLenum usage)
3439{
3440 if (size < 0)
3441 {
3442 context->handleError(Error(GL_INVALID_VALUE));
3443 return false;
3444 }
3445
3446 switch (usage)
3447 {
3448 case GL_STREAM_DRAW:
3449 case GL_STATIC_DRAW:
3450 case GL_DYNAMIC_DRAW:
3451 break;
3452
3453 case GL_STREAM_READ:
3454 case GL_STREAM_COPY:
3455 case GL_STATIC_READ:
3456 case GL_STATIC_COPY:
3457 case GL_DYNAMIC_READ:
3458 case GL_DYNAMIC_COPY:
3459 if (context->getClientMajorVersion() < 3)
3460 {
3461 context->handleError(Error(GL_INVALID_ENUM));
3462 return false;
3463 }
3464 break;
3465
3466 default:
3467 context->handleError(Error(GL_INVALID_ENUM));
3468 return false;
3469 }
3470
3471 if (!ValidBufferTarget(context, target))
3472 {
3473 context->handleError(Error(GL_INVALID_ENUM));
3474 return false;
3475 }
3476
3477 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3478
3479 if (!buffer)
3480 {
3481 context->handleError(Error(GL_INVALID_OPERATION));
3482 return false;
3483 }
3484
3485 return true;
3486}
3487
3488bool ValidateBufferSubData(ValidationContext *context,
3489 GLenum target,
3490 GLintptr offset,
3491 GLsizeiptr size,
3492 const GLvoid *data)
3493{
3494 if (size < 0 || offset < 0)
3495 {
3496 context->handleError(Error(GL_INVALID_VALUE));
3497 return false;
3498 }
3499
3500 if (!ValidBufferTarget(context, target))
3501 {
3502 context->handleError(Error(GL_INVALID_ENUM));
3503 return false;
3504 }
3505
3506 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3507
3508 if (!buffer)
3509 {
3510 context->handleError(Error(GL_INVALID_OPERATION));
3511 return false;
3512 }
3513
3514 if (buffer->isMapped())
3515 {
3516 context->handleError(Error(GL_INVALID_OPERATION));
3517 return false;
3518 }
3519
3520 // Check for possible overflow of size + offset
3521 angle::CheckedNumeric<size_t> checkedSize(size);
3522 checkedSize += offset;
3523 if (!checkedSize.IsValid())
3524 {
3525 context->handleError(Error(GL_OUT_OF_MEMORY));
3526 return false;
3527 }
3528
3529 if (size + offset > buffer->getSize())
3530 {
3531 context->handleError(Error(GL_INVALID_VALUE));
3532 return false;
3533 }
3534
Martin Radev4c4c8e72016-08-04 12:25:34 +03003535 return true;
3536}
3537
Geoff Langc287ea62016-09-16 14:46:51 -04003538bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
3539{
3540 if (!context->getExtensions().webglCompatibility)
3541 {
3542 context->handleError(
3543 Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
3544 return false;
3545 }
3546
3547 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3548 auto extension = extensionInfos.find(name);
3549 if (extension == extensionInfos.end() || !extension->second.Enableable)
3550 {
3551 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
3552 return false;
3553 }
3554
3555 return true;
3556}
3557
Jamie Madillef300b12016-10-07 15:12:09 -04003558bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3559{
3560 if (texture < GL_TEXTURE0 ||
3561 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3562 {
3563 context->handleError(Error(GL_INVALID_ENUM));
3564 return false;
3565 }
3566
3567 return true;
3568}
3569
3570bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3571{
3572 Program *programObject = GetValidProgram(context, program);
3573 if (!programObject)
3574 {
3575 return false;
3576 }
3577
3578 Shader *shaderObject = GetValidShader(context, shader);
3579 if (!shaderObject)
3580 {
3581 return false;
3582 }
3583
3584 switch (shaderObject->getType())
3585 {
3586 case GL_VERTEX_SHADER:
3587 {
3588 if (programObject->getAttachedVertexShader())
3589 {
3590 context->handleError(Error(GL_INVALID_OPERATION));
3591 return false;
3592 }
3593 break;
3594 }
3595 case GL_FRAGMENT_SHADER:
3596 {
3597 if (programObject->getAttachedFragmentShader())
3598 {
3599 context->handleError(Error(GL_INVALID_OPERATION));
3600 return false;
3601 }
3602 break;
3603 }
3604 case GL_COMPUTE_SHADER:
3605 {
3606 if (programObject->getAttachedComputeShader())
3607 {
3608 context->handleError(Error(GL_INVALID_OPERATION));
3609 return false;
3610 }
3611 break;
3612 }
3613 default:
3614 UNREACHABLE();
3615 break;
3616 }
3617
3618 return true;
3619}
3620
Jamie Madillc29968b2016-01-20 11:17:23 -05003621} // namespace gl