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