blob: 3f5b0cd5940bc72758f4851bc52b85a40ffbf1ff [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 Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/validationES.h"
Jamie Madill73a84962016-02-12 09:27:23 -050014#include "libANGLE/validationES3.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Context.h"
16#include "libANGLE/Texture.h"
17#include "libANGLE/Framebuffer.h"
18#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/formatutils.h"
20#include "libANGLE/FramebufferAttachment.h"
Geoff Langd8605522016-04-13 10:19:12 -040021#include "libANGLE/Uniform.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040022
23#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030024#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025#include "common/utilities.h"
26
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
Jamie Madillc29968b2016-01-20 11:17:23 -0500208} // anonymous namespace
209
Geoff Langb1196682014-07-23 13:47:29 -0400210bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400211 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
212 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
213{
Jamie Madill6f38f822014-06-06 17:12:20 -0400214 if (!ValidTexture2DDestinationTarget(context, target))
215 {
Jamie Madill437fa652016-05-03 15:13:24 -0400216 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400217 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400218 }
219
Austin Kinross08528e12015-10-07 16:24:40 -0700220 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400221 {
Jamie Madill437fa652016-05-03 15:13:24 -0400222 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400223 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400224 }
225
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400226 if (level < 0 || xoffset < 0 ||
227 std::numeric_limits<GLsizei>::max() - xoffset < width ||
228 std::numeric_limits<GLsizei>::max() - yoffset < height)
229 {
Jamie Madill437fa652016-05-03 15:13:24 -0400230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400232 }
233
Geoff Lang005df412013-10-16 14:12:50 -0400234 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400235 {
Jamie Madill437fa652016-05-03 15:13:24 -0400236 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400237 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400238 }
239
Geoff Langaae65a42014-05-26 12:43:44 -0400240 const gl::Caps &caps = context->getCaps();
241
Geoff Langa9be0dc2014-12-17 12:34:40 -0500242 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400243 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500244 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
245 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400246 {
Jamie Madill437fa652016-05-03 15:13:24 -0400247 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400249 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500250 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500251 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500252 {
253 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400254 {
Jamie Madill437fa652016-05-03 15:13:24 -0400255 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400257 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400258
Geoff Langa9be0dc2014-12-17 12:34:40 -0500259 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
260 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
261 {
Jamie Madill437fa652016-05-03 15:13:24 -0400262 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500263 return false;
264 }
265 }
266 else
267 {
Jamie Madill437fa652016-05-03 15:13:24 -0400268 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400270 }
271
Geoff Lang691e58c2014-12-19 17:03:25 -0500272 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400273 if (!texture)
274 {
Jamie Madill437fa652016-05-03 15:13:24 -0400275 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400276 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400277 }
278
Geoff Langa9be0dc2014-12-17 12:34:40 -0500279 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400280 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500281 if (format != GL_NONE)
282 {
Geoff Lang051dbc72015-01-05 15:48:58 -0500283 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500284 {
Jamie Madill437fa652016-05-03 15:13:24 -0400285 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500286 return false;
287 }
288 }
289
290 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
291 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
292 {
Jamie Madill437fa652016-05-03 15:13:24 -0400293 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500294 return false;
295 }
296 }
297 else
298 {
Geoff Lang69cce582015-09-17 13:20:36 -0400299 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500300 {
Jamie Madill437fa652016-05-03 15:13:24 -0400301 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500302 return false;
303 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400304 }
305
306 // Verify zero border
307 if (border != 0)
308 {
Jamie Madill437fa652016-05-03 15:13:24 -0400309 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400310 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400311 }
312
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400313 if (isCompressed)
314 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400315 GLenum actualInternalFormat =
316 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400317 switch (actualInternalFormat)
318 {
319 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
320 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400321 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 {
Jamie Madill437fa652016-05-03 15:13:24 -0400323 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400324 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 }
326 break;
327 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400328 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400329 {
Jamie Madill437fa652016-05-03 15:13:24 -0400330 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400331 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400332 }
333 break;
334 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400335 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400336 {
Jamie Madill437fa652016-05-03 15:13:24 -0400337 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
340 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400341 case GL_ETC1_RGB8_OES:
342 if (!context->getExtensions().compressedETC1RGB8Texture)
343 {
Jamie Madill437fa652016-05-03 15:13:24 -0400344 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400345 return false;
346 }
347 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800348 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
349 if (!context->getExtensions().lossyETCDecode)
350 {
Jamie Madill437fa652016-05-03 15:13:24 -0400351 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800352 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
353 return false;
354 }
355 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400357 context->handleError(Error(
tmartino0ccd5ae2015-10-01 14:33:14 -0400358 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
359 return false;
360 }
361 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
362 {
Jamie Madill437fa652016-05-03 15:13:24 -0400363 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400365 }
366 }
367 else
368 {
369 // validate <type> by itself (used as secondary key below)
370 switch (type)
371 {
372 case GL_UNSIGNED_BYTE:
373 case GL_UNSIGNED_SHORT_5_6_5:
374 case GL_UNSIGNED_SHORT_4_4_4_4:
375 case GL_UNSIGNED_SHORT_5_5_5_1:
376 case GL_UNSIGNED_SHORT:
377 case GL_UNSIGNED_INT:
378 case GL_UNSIGNED_INT_24_8_OES:
379 case GL_HALF_FLOAT_OES:
380 case GL_FLOAT:
381 break;
382 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400383 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400385 }
386
387 // validate <format> + <type> combinations
388 // - invalid <format> -> sets INVALID_ENUM
389 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
390 switch (format)
391 {
392 case GL_ALPHA:
393 case GL_LUMINANCE:
394 case GL_LUMINANCE_ALPHA:
395 switch (type)
396 {
397 case GL_UNSIGNED_BYTE:
398 case GL_FLOAT:
399 case GL_HALF_FLOAT_OES:
400 break;
Geoff Langb1196682014-07-23 13:47:29 -0400401 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400402 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 }
405 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400406 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400407 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400408 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400409 {
Jamie Madill437fa652016-05-03 15:13:24 -0400410 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400411 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400412 }
413 switch (type)
414 {
415 case GL_UNSIGNED_BYTE:
416 case GL_FLOAT:
417 case GL_HALF_FLOAT_OES:
418 break;
419 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400420 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400421 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400422 }
423 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 case GL_RGB:
425 switch (type)
426 {
427 case GL_UNSIGNED_BYTE:
428 case GL_UNSIGNED_SHORT_5_6_5:
429 case GL_FLOAT:
430 case GL_HALF_FLOAT_OES:
431 break;
432 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400433 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400435 }
436 break;
437 case GL_RGBA:
438 switch (type)
439 {
440 case GL_UNSIGNED_BYTE:
441 case GL_UNSIGNED_SHORT_4_4_4_4:
442 case GL_UNSIGNED_SHORT_5_5_5_1:
443 case GL_FLOAT:
444 case GL_HALF_FLOAT_OES:
445 break;
446 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400447 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400448 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400449 }
450 break;
451 case GL_BGRA_EXT:
452 switch (type)
453 {
454 case GL_UNSIGNED_BYTE:
455 break;
456 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400457 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400458 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400459 }
460 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400461 case GL_SRGB_EXT:
462 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400463 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400464 {
Jamie Madill437fa652016-05-03 15:13:24 -0400465 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400466 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400467 }
468 switch (type)
469 {
470 case GL_UNSIGNED_BYTE:
471 break;
472 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400473 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400474 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400475 }
476 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400477 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
478 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
479 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
480 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
481 break;
482 case GL_DEPTH_COMPONENT:
483 switch (type)
484 {
485 case GL_UNSIGNED_SHORT:
486 case GL_UNSIGNED_INT:
487 break;
488 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400489 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400490 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400491 }
492 break;
493 case GL_DEPTH_STENCIL_OES:
494 switch (type)
495 {
496 case GL_UNSIGNED_INT_24_8_OES:
497 break;
498 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400499 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400500 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400501 }
502 break;
503 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400504 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400505 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400506 }
507
508 switch (format)
509 {
510 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
511 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400512 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400513 {
Jamie Madill437fa652016-05-03 15:13:24 -0400514 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400515 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400516 }
517 else
518 {
Jamie Madill437fa652016-05-03 15:13:24 -0400519 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400520 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400521 }
522 break;
523 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400524 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400525 {
Jamie Madill437fa652016-05-03 15:13:24 -0400526 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400527 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400528 }
529 else
530 {
Jamie Madill437fa652016-05-03 15:13:24 -0400531 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400532 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400533 }
534 break;
535 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400536 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400537 {
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 else
542 {
Jamie Madill437fa652016-05-03 15:13:24 -0400543 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400544 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400545 }
546 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400547 case GL_ETC1_RGB8_OES:
548 if (context->getExtensions().compressedETC1RGB8Texture)
549 {
Jamie Madill437fa652016-05-03 15:13:24 -0400550 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400551 return false;
552 }
553 else
554 {
Jamie Madill437fa652016-05-03 15:13:24 -0400555 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400556 return false;
557 }
558 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800559 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
560 if (context->getExtensions().lossyETCDecode)
561 {
Jamie Madill437fa652016-05-03 15:13:24 -0400562 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800563 Error(GL_INVALID_OPERATION,
564 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
565 return false;
566 }
567 else
568 {
Jamie Madill437fa652016-05-03 15:13:24 -0400569 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800570 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
571 return false;
572 }
573 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400574 case GL_DEPTH_COMPONENT:
575 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400576 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400577 {
Jamie Madill437fa652016-05-03 15:13:24 -0400578 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400579 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400580 }
581 if (target != GL_TEXTURE_2D)
582 {
Jamie Madill437fa652016-05-03 15:13:24 -0400583 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400584 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400585 }
586 // OES_depth_texture supports loading depth data and multiple levels,
587 // but ANGLE_depth_texture does not
588 if (pixels != NULL || level != 0)
589 {
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:
595 break;
596 }
597
598 if (type == GL_FLOAT)
599 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400600 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400601 {
Jamie Madill437fa652016-05-03 15:13:24 -0400602 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400603 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 }
605 }
606 else if (type == GL_HALF_FLOAT_OES)
607 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400608 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400609 {
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 }
614 }
615
616 return true;
617}
618
Jamie Madillc29968b2016-01-20 11:17:23 -0500619bool ValidateES2CopyTexImageParameters(ValidationContext *context,
620 GLenum target,
621 GLint level,
622 GLenum internalformat,
623 bool isSubImage,
624 GLint xoffset,
625 GLint yoffset,
626 GLint x,
627 GLint y,
628 GLsizei width,
629 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400630 GLint border)
631{
Jamie Madill560a8d82014-05-21 13:06:20 -0400632 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400633
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500634 if (!ValidTexture2DDestinationTarget(context, target))
635 {
Jamie Madill437fa652016-05-03 15:13:24 -0400636 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500637 return false;
638 }
639
Jamie Madill560a8d82014-05-21 13:06:20 -0400640 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
641 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400642 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400643 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400644 }
645
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700646 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400647 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500648 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
649 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400650
651 // [OpenGL ES 2.0.24] table 3.9
652 if (isSubImage)
653 {
654 switch (textureFormat)
655 {
656 case GL_ALPHA:
657 if (colorbufferFormat != GL_ALPHA8_EXT &&
658 colorbufferFormat != GL_RGBA4 &&
659 colorbufferFormat != GL_RGB5_A1 &&
660 colorbufferFormat != GL_RGBA8_OES)
661 {
Jamie Madill437fa652016-05-03 15:13:24 -0400662 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400663 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664 }
665 break;
666 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400667 if (colorbufferFormat != GL_R8_EXT &&
668 colorbufferFormat != GL_RG8_EXT &&
669 colorbufferFormat != GL_RGB565 &&
670 colorbufferFormat != GL_RGB8_OES &&
671 colorbufferFormat != GL_RGBA4 &&
672 colorbufferFormat != GL_RGB5_A1 &&
673 colorbufferFormat != GL_RGBA8_OES)
674 {
Jamie Madill437fa652016-05-03 15:13:24 -0400675 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400676 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400677 }
678 break;
679 case GL_RED_EXT:
680 if (colorbufferFormat != GL_R8_EXT &&
681 colorbufferFormat != GL_RG8_EXT &&
682 colorbufferFormat != GL_RGB565 &&
683 colorbufferFormat != GL_RGB8_OES &&
684 colorbufferFormat != GL_RGBA4 &&
685 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500686 colorbufferFormat != GL_RGBA8_OES &&
687 colorbufferFormat != GL_R32F &&
688 colorbufferFormat != GL_RG32F &&
689 colorbufferFormat != GL_RGB32F &&
690 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400691 {
Jamie Madill437fa652016-05-03 15:13:24 -0400692 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400693 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400694 }
695 break;
696 case GL_RG_EXT:
697 if (colorbufferFormat != GL_RG8_EXT &&
698 colorbufferFormat != GL_RGB565 &&
699 colorbufferFormat != GL_RGB8_OES &&
700 colorbufferFormat != GL_RGBA4 &&
701 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500702 colorbufferFormat != GL_RGBA8_OES &&
703 colorbufferFormat != GL_RG32F &&
704 colorbufferFormat != GL_RGB32F &&
705 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400706 {
Jamie Madill437fa652016-05-03 15:13:24 -0400707 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400708 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400709 }
710 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400711 case GL_RGB:
712 if (colorbufferFormat != GL_RGB565 &&
713 colorbufferFormat != GL_RGB8_OES &&
714 colorbufferFormat != GL_RGBA4 &&
715 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500716 colorbufferFormat != GL_RGBA8_OES &&
717 colorbufferFormat != GL_RGB32F &&
718 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 {
Jamie Madill437fa652016-05-03 15:13:24 -0400720 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400721 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 }
723 break;
724 case GL_LUMINANCE_ALPHA:
725 case GL_RGBA:
726 if (colorbufferFormat != GL_RGBA4 &&
727 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500728 colorbufferFormat != GL_RGBA8_OES &&
729 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400730 {
Jamie Madill437fa652016-05-03 15:13:24 -0400731 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400732 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 }
734 break;
735 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
736 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
737 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
738 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400739 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800740 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Jamie Madill437fa652016-05-03 15:13:24 -0400741 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400742 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400743 case GL_DEPTH_COMPONENT:
744 case GL_DEPTH_STENCIL_OES:
Jamie Madill437fa652016-05-03 15:13:24 -0400745 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400748 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400749 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400750 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500751
752 if (internalFormatInfo.type == GL_FLOAT &&
753 !context->getExtensions().textureFloat)
754 {
Jamie Madill437fa652016-05-03 15:13:24 -0400755 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillbc393df2015-01-29 13:46:07 -0500756 return false;
757 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400758 }
759 else
760 {
761 switch (internalformat)
762 {
763 case GL_ALPHA:
764 if (colorbufferFormat != GL_ALPHA8_EXT &&
765 colorbufferFormat != GL_RGBA4 &&
766 colorbufferFormat != GL_RGB5_A1 &&
767 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500768 colorbufferFormat != GL_RGBA8_OES &&
769 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770 {
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 Lange8ebe7f2013-08-05 15:03:13 -0400773 }
774 break;
775 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400776 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 &&
782 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500783 colorbufferFormat != GL_RGBA8_OES &&
784 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400785 {
Jamie Madill437fa652016-05-03 15:13:24 -0400786 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400787 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400788 }
789 break;
790 case GL_RED_EXT:
791 if (colorbufferFormat != GL_R8_EXT &&
792 colorbufferFormat != GL_RG8_EXT &&
793 colorbufferFormat != GL_RGB565 &&
794 colorbufferFormat != GL_RGB8_OES &&
795 colorbufferFormat != GL_RGBA4 &&
796 colorbufferFormat != GL_RGB5_A1 &&
797 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500798 colorbufferFormat != GL_RGBA8_OES &&
799 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400800 {
Jamie Madill437fa652016-05-03 15:13:24 -0400801 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400802 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400803 }
804 break;
805 case GL_RG_EXT:
806 if (colorbufferFormat != GL_RG8_EXT &&
807 colorbufferFormat != GL_RGB565 &&
808 colorbufferFormat != GL_RGB8_OES &&
809 colorbufferFormat != GL_RGBA4 &&
810 colorbufferFormat != GL_RGB5_A1 &&
811 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500812 colorbufferFormat != GL_RGBA8_OES &&
813 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400814 {
Jamie Madill437fa652016-05-03 15:13:24 -0400815 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400816 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400817 }
818 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 case GL_RGB:
820 if (colorbufferFormat != GL_RGB565 &&
821 colorbufferFormat != GL_RGB8_OES &&
822 colorbufferFormat != GL_RGBA4 &&
823 colorbufferFormat != GL_RGB5_A1 &&
824 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500825 colorbufferFormat != GL_RGBA8_OES &&
826 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 {
Jamie Madill437fa652016-05-03 15:13:24 -0400828 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830 }
831 break;
832 case GL_LUMINANCE_ALPHA:
833 case GL_RGBA:
834 if (colorbufferFormat != GL_RGBA4 &&
835 colorbufferFormat != GL_RGB5_A1 &&
836 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500837 colorbufferFormat != GL_RGBA8_OES &&
838 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 {
Jamie Madill437fa652016-05-03 15:13:24 -0400840 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400841 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 }
843 break;
844 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
845 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400846 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400850 }
851 else
852 {
Jamie Madill437fa652016-05-03 15:13:24 -0400853 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400854 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 }
856 break;
857 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400858 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 {
Jamie Madill437fa652016-05-03 15:13:24 -0400860 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400861 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400862 }
863 else
864 {
Jamie Madill437fa652016-05-03 15:13:24 -0400865 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400866 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400867 }
868 break;
869 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400870 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400871 {
Jamie Madill437fa652016-05-03 15:13:24 -0400872 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400873 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 }
875 else
876 {
Jamie Madill437fa652016-05-03 15:13:24 -0400877 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400878 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400879 }
880 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400881 case GL_ETC1_RGB8_OES:
882 if (context->getExtensions().compressedETC1RGB8Texture)
883 {
Jamie Madill437fa652016-05-03 15:13:24 -0400884 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400885 return false;
886 }
887 else
888 {
Jamie Madill437fa652016-05-03 15:13:24 -0400889 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -0400890 return false;
891 }
892 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800893 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
894 if (context->getExtensions().lossyETCDecode)
895 {
Jamie Madill437fa652016-05-03 15:13:24 -0400896 context->handleError(Error(GL_INVALID_OPERATION,
Minmin Gonge3939b92015-12-01 15:36:51 -0800897 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
898 return false;
899 }
900 else
901 {
Jamie Madill437fa652016-05-03 15:13:24 -0400902 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -0800903 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
904 return false;
905 }
906 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 case GL_DEPTH_COMPONENT:
908 case GL_DEPTH_COMPONENT16:
909 case GL_DEPTH_COMPONENT32_OES:
910 case GL_DEPTH_STENCIL_OES:
911 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400912 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400913 {
Jamie Madill437fa652016-05-03 15:13:24 -0400914 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400915 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916 }
917 else
918 {
Jamie Madill437fa652016-05-03 15:13:24 -0400919 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400920 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 }
922 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400923 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400924 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925 }
926 }
927
Geoff Lang784a8fd2013-09-24 12:33:16 -0400928 // If width or height is zero, it is a no-op. Return false without setting an error.
929 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930}
931
Geoff Langb1196682014-07-23 13:47:29 -0400932bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400933 GLsizei width, GLsizei height)
934{
935 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
936 {
Jamie Madill437fa652016-05-03 15:13:24 -0400937 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 }
940
941 if (width < 1 || height < 1 || levels < 1)
942 {
Jamie Madill437fa652016-05-03 15:13:24 -0400943 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400944 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400945 }
946
947 if (target == GL_TEXTURE_CUBE_MAP && width != height)
948 {
Jamie Madill437fa652016-05-03 15:13:24 -0400949 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400951 }
952
953 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
954 {
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
Geoff Lang5d601382014-07-22 15:14:06 -0400959 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
960 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400961 {
Jamie Madill437fa652016-05-03 15:13:24 -0400962 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964 }
965
Geoff Langaae65a42014-05-26 12:43:44 -0400966 const gl::Caps &caps = context->getCaps();
967
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400968 switch (target)
969 {
970 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400971 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
972 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973 {
Jamie Madill437fa652016-05-03 15:13:24 -0400974 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400975 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976 }
977 break;
978 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400979 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
980 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400981 {
Jamie Madill437fa652016-05-03 15:13:24 -0400982 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400983 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400984 }
985 break;
986 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400987 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400989 }
990
Geoff Langc0b9ef42014-07-02 10:02:37 -0400991 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400992 {
993 if (!gl::isPow2(width) || !gl::isPow2(height))
994 {
Jamie Madill437fa652016-05-03 15:13:24 -0400995 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400996 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400997 }
998 }
999
1000 switch (internalformat)
1001 {
1002 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1003 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001004 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001005 {
Jamie Madill437fa652016-05-03 15:13:24 -04001006 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 }
1009 break;
1010 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001011 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001012 {
Jamie Madill437fa652016-05-03 15:13:24 -04001013 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 }
1016 break;
1017 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001018 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 {
Jamie Madill437fa652016-05-03 15:13:24 -04001020 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001021 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001022 }
1023 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -04001024 case GL_ETC1_RGB8_OES:
1025 if (!context->getExtensions().compressedETC1RGB8Texture)
1026 {
Jamie Madill437fa652016-05-03 15:13:24 -04001027 context->handleError(Error(GL_INVALID_ENUM));
Geoff Lang6ea6f942015-09-11 13:11:22 -04001028 return false;
1029 }
1030 break;
Minmin Gonge3939b92015-12-01 15:36:51 -08001031 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1032 if (!context->getExtensions().lossyETCDecode)
1033 {
Jamie Madill437fa652016-05-03 15:13:24 -04001034 context->handleError(
Minmin Gonge3939b92015-12-01 15:36:51 -08001035 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1036 return false;
1037 }
1038 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001039 case GL_RGBA32F_EXT:
1040 case GL_RGB32F_EXT:
1041 case GL_ALPHA32F_EXT:
1042 case GL_LUMINANCE32F_EXT:
1043 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001044 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 {
Jamie Madill437fa652016-05-03 15:13:24 -04001046 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001047 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048 }
1049 break;
1050 case GL_RGBA16F_EXT:
1051 case GL_RGB16F_EXT:
1052 case GL_ALPHA16F_EXT:
1053 case GL_LUMINANCE16F_EXT:
1054 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001055 if (!context->getExtensions().textureHalfFloat)
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 break;
Geoff Lang632192d2013-10-04 13:40:46 -04001061 case GL_R8_EXT:
1062 case GL_RG8_EXT:
1063 case GL_R16F_EXT:
1064 case GL_RG16F_EXT:
1065 case GL_R32F_EXT:
1066 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001067 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -04001068 {
Jamie Madill437fa652016-05-03 15:13:24 -04001069 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001070 return false;
Geoff Lang632192d2013-10-04 13:40:46 -04001071 }
1072 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001073 case GL_DEPTH_COMPONENT16:
1074 case GL_DEPTH_COMPONENT32_OES:
1075 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001076 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001077 {
Jamie Madill437fa652016-05-03 15:13:24 -04001078 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001079 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 }
1081 if (target != GL_TEXTURE_2D)
1082 {
Jamie Madill437fa652016-05-03 15:13:24 -04001083 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001085 }
1086 // ANGLE_depth_texture only supports 1-level textures
1087 if (levels != 1)
1088 {
Jamie Madill437fa652016-05-03 15:13:24 -04001089 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092 break;
1093 default:
1094 break;
1095 }
1096
Geoff Lang691e58c2014-12-19 17:03:25 -05001097 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 if (!texture || texture->id() == 0)
1099 {
Jamie Madill437fa652016-05-03 15:13:24 -04001100 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001101 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001102 }
1103
Geoff Lang69cce582015-09-17 13:20:36 -04001104 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 {
Jamie Madill437fa652016-05-03 15:13:24 -04001106 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 }
1109
1110 return true;
1111}
1112
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113// check for combinations of format and type that are valid for ReadPixels
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001114bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115{
1116 switch (format)
1117 {
1118 case GL_RGBA:
1119 switch (type)
1120 {
1121 case GL_UNSIGNED_BYTE:
1122 break;
1123 default:
1124 return false;
1125 }
1126 break;
1127 case GL_BGRA_EXT:
1128 switch (type)
1129 {
1130 case GL_UNSIGNED_BYTE:
1131 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1132 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1133 break;
1134 default:
1135 return false;
1136 }
1137 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001138 case GL_RG_EXT:
1139 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001140 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001141 {
1142 return false;
1143 }
1144 switch (type)
1145 {
1146 case GL_UNSIGNED_BYTE:
1147 break;
1148 default:
1149 return false;
1150 }
1151 break;
1152
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 default:
1154 return false;
1155 }
1156 return true;
1157}
1158
Austin Kinross08332632015-05-05 13:35:47 -07001159bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1160 const GLenum *attachments)
1161{
Jamie Madillc29968b2016-01-20 11:17:23 -05001162 if (!context->getExtensions().discardFramebuffer)
1163 {
Jamie Madill437fa652016-05-03 15:13:24 -04001164 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001165 return false;
1166 }
1167
Austin Kinross08332632015-05-05 13:35:47 -07001168 bool defaultFramebuffer = false;
1169
1170 switch (target)
1171 {
1172 case GL_FRAMEBUFFER:
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001173 defaultFramebuffer =
1174 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1175 break;
Austin Kinross08332632015-05-05 13:35:47 -07001176 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001177 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
Austin Kinross08332632015-05-05 13:35:47 -07001178 return false;
1179 }
1180
1181 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1182}
1183
Austin Kinrossbc781f32015-10-26 09:27:38 -07001184bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1185{
1186 if (!context->getExtensions().vertexArrayObject)
1187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001189 return false;
1190 }
1191
1192 return ValidateBindVertexArrayBase(context, array);
1193}
1194
1195bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1196{
1197 if (!context->getExtensions().vertexArrayObject)
1198 {
Jamie Madill437fa652016-05-03 15:13:24 -04001199 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001200 return false;
1201 }
1202
Olli Etuaho41997e72016-03-10 13:38:39 +02001203 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001204}
1205
1206bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1207{
1208 if (!context->getExtensions().vertexArrayObject)
1209 {
Jamie Madill437fa652016-05-03 15:13:24 -04001210 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001211 return false;
1212 }
1213
Olli Etuaho41997e72016-03-10 13:38:39 +02001214 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001215}
1216
1217bool ValidateIsVertexArrayOES(Context *context)
1218{
1219 if (!context->getExtensions().vertexArrayObject)
1220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001222 return false;
1223 }
1224
1225 return true;
1226}
Geoff Langc5629752015-12-07 16:29:04 -05001227
1228bool ValidateProgramBinaryOES(Context *context,
1229 GLuint program,
1230 GLenum binaryFormat,
1231 const void *binary,
1232 GLint length)
1233{
1234 if (!context->getExtensions().getProgramBinary)
1235 {
Jamie Madill437fa652016-05-03 15:13:24 -04001236 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001237 return false;
1238 }
1239
1240 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1241}
1242
1243bool ValidateGetProgramBinaryOES(Context *context,
1244 GLuint program,
1245 GLsizei bufSize,
1246 GLsizei *length,
1247 GLenum *binaryFormat,
1248 void *binary)
1249{
1250 if (!context->getExtensions().getProgramBinary)
1251 {
Jamie Madill437fa652016-05-03 15:13:24 -04001252 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001253 return false;
1254 }
1255
1256 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1257}
Geoff Lange102fee2015-12-10 11:23:30 -05001258
Geoff Lang70d0f492015-12-10 17:45:46 -05001259static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1260{
1261 switch (source)
1262 {
1263 case GL_DEBUG_SOURCE_API:
1264 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1265 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1266 case GL_DEBUG_SOURCE_OTHER:
1267 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1268 return !mustBeThirdPartyOrApplication;
1269
1270 case GL_DEBUG_SOURCE_THIRD_PARTY:
1271 case GL_DEBUG_SOURCE_APPLICATION:
1272 return true;
1273
1274 default:
1275 return false;
1276 }
1277}
1278
1279static bool ValidDebugType(GLenum type)
1280{
1281 switch (type)
1282 {
1283 case GL_DEBUG_TYPE_ERROR:
1284 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1285 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1286 case GL_DEBUG_TYPE_PERFORMANCE:
1287 case GL_DEBUG_TYPE_PORTABILITY:
1288 case GL_DEBUG_TYPE_OTHER:
1289 case GL_DEBUG_TYPE_MARKER:
1290 case GL_DEBUG_TYPE_PUSH_GROUP:
1291 case GL_DEBUG_TYPE_POP_GROUP:
1292 return true;
1293
1294 default:
1295 return false;
1296 }
1297}
1298
1299static bool ValidDebugSeverity(GLenum severity)
1300{
1301 switch (severity)
1302 {
1303 case GL_DEBUG_SEVERITY_HIGH:
1304 case GL_DEBUG_SEVERITY_MEDIUM:
1305 case GL_DEBUG_SEVERITY_LOW:
1306 case GL_DEBUG_SEVERITY_NOTIFICATION:
1307 return true;
1308
1309 default:
1310 return false;
1311 }
1312}
1313
Geoff Lange102fee2015-12-10 11:23:30 -05001314bool ValidateDebugMessageControlKHR(Context *context,
1315 GLenum source,
1316 GLenum type,
1317 GLenum severity,
1318 GLsizei count,
1319 const GLuint *ids,
1320 GLboolean enabled)
1321{
1322 if (!context->getExtensions().debug)
1323 {
Jamie Madill437fa652016-05-03 15:13:24 -04001324 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001325 return false;
1326 }
1327
Geoff Lang70d0f492015-12-10 17:45:46 -05001328 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1329 {
Jamie Madill437fa652016-05-03 15:13:24 -04001330 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001331 return false;
1332 }
1333
1334 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1335 {
Jamie Madill437fa652016-05-03 15:13:24 -04001336 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001337 return false;
1338 }
1339
1340 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1341 {
Jamie Madill437fa652016-05-03 15:13:24 -04001342 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001343 return false;
1344 }
1345
1346 if (count > 0)
1347 {
1348 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1349 {
Jamie Madill437fa652016-05-03 15:13:24 -04001350 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001351 GL_INVALID_OPERATION,
1352 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1353 return false;
1354 }
1355
1356 if (severity != GL_DONT_CARE)
1357 {
Jamie Madill437fa652016-05-03 15:13:24 -04001358 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001359 Error(GL_INVALID_OPERATION,
1360 "If count is greater than zero, severity must be GL_DONT_CARE."));
1361 return false;
1362 }
1363 }
1364
Geoff Lange102fee2015-12-10 11:23:30 -05001365 return true;
1366}
1367
1368bool ValidateDebugMessageInsertKHR(Context *context,
1369 GLenum source,
1370 GLenum type,
1371 GLuint id,
1372 GLenum severity,
1373 GLsizei length,
1374 const GLchar *buf)
1375{
1376 if (!context->getExtensions().debug)
1377 {
Jamie Madill437fa652016-05-03 15:13:24 -04001378 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001379 return false;
1380 }
1381
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001382 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001383 {
1384 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1385 // not generate an error.
1386 return false;
1387 }
1388
1389 if (!ValidDebugSeverity(severity))
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 (!ValidDebugType(type))
1396 {
Jamie Madill437fa652016-05-03 15:13:24 -04001397 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001398 return false;
1399 }
1400
1401 if (!ValidDebugSource(source, true))
1402 {
Jamie Madill437fa652016-05-03 15:13:24 -04001403 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001404 return false;
1405 }
1406
1407 size_t messageLength = (length < 0) ? strlen(buf) : length;
1408 if (messageLength > context->getExtensions().maxDebugMessageLength)
1409 {
Jamie Madill437fa652016-05-03 15:13:24 -04001410 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001411 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1412 return false;
1413 }
1414
Geoff Lange102fee2015-12-10 11:23:30 -05001415 return true;
1416}
1417
1418bool ValidateDebugMessageCallbackKHR(Context *context,
1419 GLDEBUGPROCKHR callback,
1420 const void *userParam)
1421{
1422 if (!context->getExtensions().debug)
1423 {
Jamie Madill437fa652016-05-03 15:13:24 -04001424 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001425 return false;
1426 }
1427
Geoff Lange102fee2015-12-10 11:23:30 -05001428 return true;
1429}
1430
1431bool ValidateGetDebugMessageLogKHR(Context *context,
1432 GLuint count,
1433 GLsizei bufSize,
1434 GLenum *sources,
1435 GLenum *types,
1436 GLuint *ids,
1437 GLenum *severities,
1438 GLsizei *lengths,
1439 GLchar *messageLog)
1440{
1441 if (!context->getExtensions().debug)
1442 {
Jamie Madill437fa652016-05-03 15:13:24 -04001443 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001444 return false;
1445 }
1446
Geoff Lang70d0f492015-12-10 17:45:46 -05001447 if (bufSize < 0 && messageLog != nullptr)
1448 {
Jamie Madill437fa652016-05-03 15:13:24 -04001449 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001450 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1451 return false;
1452 }
1453
Geoff Lange102fee2015-12-10 11:23:30 -05001454 return true;
1455}
1456
1457bool ValidatePushDebugGroupKHR(Context *context,
1458 GLenum source,
1459 GLuint id,
1460 GLsizei length,
1461 const GLchar *message)
1462{
1463 if (!context->getExtensions().debug)
1464 {
Jamie Madill437fa652016-05-03 15:13:24 -04001465 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001466 return false;
1467 }
1468
Geoff Lang70d0f492015-12-10 17:45:46 -05001469 if (!ValidDebugSource(source, true))
1470 {
Jamie Madill437fa652016-05-03 15:13:24 -04001471 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001472 return false;
1473 }
1474
1475 size_t messageLength = (length < 0) ? strlen(message) : length;
1476 if (messageLength > context->getExtensions().maxDebugMessageLength)
1477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001479 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1480 return false;
1481 }
1482
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001483 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001484 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1485 {
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001487 Error(GL_STACK_OVERFLOW,
1488 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1489 return false;
1490 }
1491
Geoff Lange102fee2015-12-10 11:23:30 -05001492 return true;
1493}
1494
1495bool ValidatePopDebugGroupKHR(Context *context)
1496{
1497 if (!context->getExtensions().debug)
1498 {
Jamie Madill437fa652016-05-03 15:13:24 -04001499 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001500 return false;
1501 }
1502
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001503 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001504 if (currentStackSize <= 1)
1505 {
Jamie Madill437fa652016-05-03 15:13:24 -04001506 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001507 return false;
1508 }
1509
1510 return true;
1511}
1512
1513static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1514{
1515 switch (identifier)
1516 {
1517 case GL_BUFFER:
1518 if (context->getBuffer(name) == nullptr)
1519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001521 return false;
1522 }
1523 return true;
1524
1525 case GL_SHADER:
1526 if (context->getShader(name) == nullptr)
1527 {
Jamie Madill437fa652016-05-03 15:13:24 -04001528 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001529 return false;
1530 }
1531 return true;
1532
1533 case GL_PROGRAM:
1534 if (context->getProgram(name) == nullptr)
1535 {
Jamie Madill437fa652016-05-03 15:13:24 -04001536 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001537 return false;
1538 }
1539 return true;
1540
1541 case GL_VERTEX_ARRAY:
1542 if (context->getVertexArray(name) == nullptr)
1543 {
Jamie Madill437fa652016-05-03 15:13:24 -04001544 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001545 return false;
1546 }
1547 return true;
1548
1549 case GL_QUERY:
1550 if (context->getQuery(name) == nullptr)
1551 {
Jamie Madill437fa652016-05-03 15:13:24 -04001552 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001553 return false;
1554 }
1555 return true;
1556
1557 case GL_TRANSFORM_FEEDBACK:
1558 if (context->getTransformFeedback(name) == nullptr)
1559 {
Jamie Madill437fa652016-05-03 15:13:24 -04001560 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001561 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1562 return false;
1563 }
1564 return true;
1565
1566 case GL_SAMPLER:
1567 if (context->getSampler(name) == nullptr)
1568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001570 return false;
1571 }
1572 return true;
1573
1574 case GL_TEXTURE:
1575 if (context->getTexture(name) == nullptr)
1576 {
Jamie Madill437fa652016-05-03 15:13:24 -04001577 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001578 return false;
1579 }
1580 return true;
1581
1582 case GL_RENDERBUFFER:
1583 if (context->getRenderbuffer(name) == nullptr)
1584 {
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001586 return false;
1587 }
1588 return true;
1589
1590 case GL_FRAMEBUFFER:
1591 if (context->getFramebuffer(name) == nullptr)
1592 {
Jamie Madill437fa652016-05-03 15:13:24 -04001593 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001594 return false;
1595 }
1596 return true;
1597
1598 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001599 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001600 return false;
1601 }
1602
Geoff Lange102fee2015-12-10 11:23:30 -05001603 return true;
1604}
1605
1606bool ValidateObjectLabelKHR(Context *context,
1607 GLenum identifier,
1608 GLuint name,
1609 GLsizei length,
1610 const GLchar *label)
1611{
1612 if (!context->getExtensions().debug)
1613 {
Jamie Madill437fa652016-05-03 15:13:24 -04001614 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001615 return false;
1616 }
1617
Geoff Lang70d0f492015-12-10 17:45:46 -05001618 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1619 {
1620 return false;
1621 }
1622
1623 size_t labelLength = (length < 0) ? strlen(label) : length;
1624 if (labelLength > context->getExtensions().maxLabelLength)
1625 {
Jamie Madill437fa652016-05-03 15:13:24 -04001626 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001627 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1628 return false;
1629 }
1630
Geoff Lange102fee2015-12-10 11:23:30 -05001631 return true;
1632}
1633
1634bool ValidateGetObjectLabelKHR(Context *context,
1635 GLenum identifier,
1636 GLuint name,
1637 GLsizei bufSize,
1638 GLsizei *length,
1639 GLchar *label)
1640{
1641 if (!context->getExtensions().debug)
1642 {
Jamie Madill437fa652016-05-03 15:13:24 -04001643 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001644 return false;
1645 }
1646
Geoff Lang70d0f492015-12-10 17:45:46 -05001647 if (bufSize < 0)
1648 {
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001650 return false;
1651 }
1652
1653 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1654 {
1655 return false;
1656 }
1657
1658 // Can no-op if bufSize is zero.
1659 return bufSize > 0;
1660}
1661
1662static bool ValidateObjectPtrName(Context *context, const void *ptr)
1663{
1664 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1665 {
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001667 return false;
1668 }
1669
Geoff Lange102fee2015-12-10 11:23:30 -05001670 return true;
1671}
1672
1673bool ValidateObjectPtrLabelKHR(Context *context,
1674 const void *ptr,
1675 GLsizei length,
1676 const GLchar *label)
1677{
1678 if (!context->getExtensions().debug)
1679 {
Jamie Madill437fa652016-05-03 15:13:24 -04001680 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001681 return false;
1682 }
1683
Geoff Lang70d0f492015-12-10 17:45:46 -05001684 if (!ValidateObjectPtrName(context, ptr))
1685 {
1686 return false;
1687 }
1688
1689 size_t labelLength = (length < 0) ? strlen(label) : length;
1690 if (labelLength > context->getExtensions().maxLabelLength)
1691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001693 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1694 return false;
1695 }
1696
Geoff Lange102fee2015-12-10 11:23:30 -05001697 return true;
1698}
1699
1700bool ValidateGetObjectPtrLabelKHR(Context *context,
1701 const void *ptr,
1702 GLsizei bufSize,
1703 GLsizei *length,
1704 GLchar *label)
1705{
1706 if (!context->getExtensions().debug)
1707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001709 return false;
1710 }
1711
Geoff Lang70d0f492015-12-10 17:45:46 -05001712 if (bufSize < 0)
1713 {
Jamie Madill437fa652016-05-03 15:13:24 -04001714 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001715 return false;
1716 }
1717
1718 if (!ValidateObjectPtrName(context, ptr))
1719 {
1720 return false;
1721 }
1722
1723 // Can no-op if bufSize is zero.
1724 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001725}
1726
1727bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1728{
1729 if (!context->getExtensions().debug)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001732 return false;
1733 }
1734
Geoff Lang70d0f492015-12-10 17:45:46 -05001735 // TODO: represent this in Context::getQueryParameterInfo.
1736 switch (pname)
1737 {
1738 case GL_DEBUG_CALLBACK_FUNCTION:
1739 case GL_DEBUG_CALLBACK_USER_PARAM:
1740 break;
1741
1742 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001744 return false;
1745 }
1746
Geoff Lange102fee2015-12-10 11:23:30 -05001747 return true;
1748}
Jamie Madillc29968b2016-01-20 11:17:23 -05001749
1750bool ValidateBlitFramebufferANGLE(Context *context,
1751 GLint srcX0,
1752 GLint srcY0,
1753 GLint srcX1,
1754 GLint srcY1,
1755 GLint dstX0,
1756 GLint dstY0,
1757 GLint dstX1,
1758 GLint dstY1,
1759 GLbitfield mask,
1760 GLenum filter)
1761{
1762 if (!context->getExtensions().framebufferBlit)
1763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001765 return false;
1766 }
1767
1768 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1769 {
1770 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001772 GL_INVALID_OPERATION,
1773 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1774 return false;
1775 }
1776
1777 if (filter == GL_LINEAR)
1778 {
Jamie Madill437fa652016-05-03 15:13:24 -04001779 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001780 return false;
1781 }
1782
Jamie Madill51f40ec2016-06-15 14:06:00 -04001783 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1784 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001785
1786 if (mask & GL_COLOR_BUFFER_BIT)
1787 {
1788 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1789 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1790
1791 if (readColorAttachment && drawColorAttachment)
1792 {
1793 if (!(readColorAttachment->type() == GL_TEXTURE &&
1794 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1795 readColorAttachment->type() != GL_RENDERBUFFER &&
1796 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001799 return false;
1800 }
1801
Geoff Langa15472a2015-08-11 11:48:03 -04001802 for (size_t drawbufferIdx = 0;
1803 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001804 {
Geoff Langa15472a2015-08-11 11:48:03 -04001805 const FramebufferAttachment *attachment =
1806 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1807 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001808 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001809 if (!(attachment->type() == GL_TEXTURE &&
1810 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1811 attachment->type() != GL_RENDERBUFFER &&
1812 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1813 {
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001815 return false;
1816 }
1817
1818 // Return an error if the destination formats do not match
1819 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1820 {
Jamie Madill437fa652016-05-03 15:13:24 -04001821 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001822 return false;
1823 }
1824 }
1825 }
1826
Jamie Madill51f40ec2016-06-15 14:06:00 -04001827 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1829 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1830 {
Jamie Madill437fa652016-05-03 15:13:24 -04001831 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001832 return false;
1833 }
1834 }
1835 }
1836
1837 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1838 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1839 for (size_t i = 0; i < 2; i++)
1840 {
1841 if (mask & masks[i])
1842 {
1843 const FramebufferAttachment *readBuffer =
1844 readFramebuffer->getAttachment(attachments[i]);
1845 const FramebufferAttachment *drawBuffer =
1846 drawFramebuffer->getAttachment(attachments[i]);
1847
1848 if (readBuffer && drawBuffer)
1849 {
1850 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1851 dstX0, dstY0, dstX1, dstY1))
1852 {
1853 // only whole-buffer copies are permitted
1854 ERR(
1855 "Only whole-buffer depth and stencil blits are supported by this "
1856 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860
1861 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
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 }
1867 }
1868 }
1869
1870 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1871 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001872}
Jamie Madillc29968b2016-01-20 11:17:23 -05001873
1874bool ValidateClear(ValidationContext *context, GLbitfield mask)
1875{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001876 auto fbo = context->getGLState().getDrawFramebuffer();
1877 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
1883 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1884 {
Jamie Madill437fa652016-05-03 15:13:24 -04001885 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 return false;
1887 }
1888
1889 return true;
1890}
1891
1892bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1893{
1894 if (!context->getExtensions().drawBuffers)
1895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001897 return false;
1898 }
1899
1900 return ValidateDrawBuffersBase(context, n, bufs);
1901}
1902
Jamie Madill73a84962016-02-12 09:27:23 -05001903bool ValidateTexImage2D(Context *context,
1904 GLenum target,
1905 GLint level,
1906 GLint internalformat,
1907 GLsizei width,
1908 GLsizei height,
1909 GLint border,
1910 GLenum format,
1911 GLenum type,
1912 const GLvoid *pixels)
1913{
1914 if (context->getClientVersion() < 3)
1915 {
1916 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1917 0, 0, width, height, border, format, type, pixels);
1918 }
1919
1920 ASSERT(context->getClientVersion() >= 3);
1921 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1922 0, 0, width, height, 1, border, format, type, pixels);
1923}
1924
1925bool ValidateTexSubImage2D(Context *context,
1926 GLenum target,
1927 GLint level,
1928 GLint xoffset,
1929 GLint yoffset,
1930 GLsizei width,
1931 GLsizei height,
1932 GLenum format,
1933 GLenum type,
1934 const GLvoid *pixels)
1935{
1936
1937 if (context->getClientVersion() < 3)
1938 {
1939 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1940 yoffset, width, height, 0, format, type, pixels);
1941 }
1942
1943 ASSERT(context->getClientVersion() >= 3);
1944 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1945 yoffset, 0, width, height, 1, 0, format, type, pixels);
1946}
1947
1948bool ValidateCompressedTexImage2D(Context *context,
1949 GLenum target,
1950 GLint level,
1951 GLenum internalformat,
1952 GLsizei width,
1953 GLsizei height,
1954 GLint border,
1955 GLsizei imageSize,
1956 const GLvoid *data)
1957{
1958 if (context->getClientVersion() < 3)
1959 {
1960 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1961 0, width, height, border, GL_NONE, GL_NONE, data))
1962 {
1963 return false;
1964 }
1965 }
1966 else
1967 {
1968 ASSERT(context->getClientVersion() >= 3);
1969 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1970 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1971 data))
1972 {
1973 return false;
1974 }
1975 }
1976
1977 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001978 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001979 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001980 if (blockSizeOrErr.isError())
1981 {
1982 context->handleError(blockSizeOrErr.getError());
1983 return false;
1984 }
1985
1986 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001987 {
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001989 return false;
1990 }
1991
1992 return true;
1993}
1994
1995bool ValidateCompressedTexSubImage2D(Context *context,
1996 GLenum target,
1997 GLint level,
1998 GLint xoffset,
1999 GLint yoffset,
2000 GLsizei width,
2001 GLsizei height,
2002 GLenum format,
2003 GLsizei imageSize,
2004 const GLvoid *data)
2005{
2006 if (context->getClientVersion() < 3)
2007 {
2008 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2009 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2010 {
2011 return false;
2012 }
2013 }
2014 else
2015 {
2016 ASSERT(context->getClientVersion() >= 3);
2017 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2018 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2019 data))
2020 {
2021 return false;
2022 }
2023 }
2024
2025 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002026 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002027 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002028 if (blockSizeOrErr.isError())
2029 {
2030 context->handleError(blockSizeOrErr.getError());
2031 return false;
2032 }
2033
2034 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002037 return false;
2038 }
2039
2040 return true;
2041}
2042
Olli Etuaho4f667482016-03-30 15:56:35 +03002043bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2044{
2045 if (!context->getExtensions().mapBuffer)
2046 {
Jamie Madill437fa652016-05-03 15:13:24 -04002047 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002048 return false;
2049 }
2050
2051 return ValidateGetBufferPointervBase(context, target, pname, params);
2052}
2053
2054bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2055{
2056 if (!context->getExtensions().mapBuffer)
2057 {
Jamie Madill437fa652016-05-03 15:13:24 -04002058 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002059 return false;
2060 }
2061
2062 if (!ValidBufferTarget(context, target))
2063 {
Jamie Madill437fa652016-05-03 15:13:24 -04002064 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002065 return false;
2066 }
2067
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002068 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002069
2070 if (buffer == nullptr)
2071 {
Jamie Madill437fa652016-05-03 15:13:24 -04002072 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002073 return false;
2074 }
2075
2076 if (access != GL_WRITE_ONLY_OES)
2077 {
Jamie Madill437fa652016-05-03 15:13:24 -04002078 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002079 return false;
2080 }
2081
2082 if (buffer->isMapped())
2083 {
Jamie Madill437fa652016-05-03 15:13:24 -04002084 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002085 return false;
2086 }
2087
2088 return true;
2089}
2090
2091bool ValidateUnmapBufferOES(Context *context, GLenum target)
2092{
2093 if (!context->getExtensions().mapBuffer)
2094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002096 return false;
2097 }
2098
2099 return ValidateUnmapBufferBase(context, target);
2100}
2101
2102bool ValidateMapBufferRangeEXT(Context *context,
2103 GLenum target,
2104 GLintptr offset,
2105 GLsizeiptr length,
2106 GLbitfield access)
2107{
2108 if (!context->getExtensions().mapBufferRange)
2109 {
Jamie Madill437fa652016-05-03 15:13:24 -04002110 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002111 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2112 return false;
2113 }
2114
2115 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2116}
2117
2118bool ValidateFlushMappedBufferRangeEXT(Context *context,
2119 GLenum target,
2120 GLintptr offset,
2121 GLsizeiptr length)
2122{
2123 if (!context->getExtensions().mapBufferRange)
2124 {
Jamie Madill437fa652016-05-03 15:13:24 -04002125 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002126 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2127 return false;
2128 }
2129
2130 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2131}
2132
Ian Ewell54f87462016-03-10 13:47:21 -05002133bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2134{
2135 Texture *textureObject = context->getTexture(texture);
2136 if (textureObject && textureObject->getTarget() != target && texture != 0)
2137 {
Jamie Madill437fa652016-05-03 15:13:24 -04002138 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002139 return false;
2140 }
2141
2142 switch (target)
2143 {
2144 case GL_TEXTURE_2D:
2145 case GL_TEXTURE_CUBE_MAP:
2146 break;
2147
2148 case GL_TEXTURE_3D:
2149 case GL_TEXTURE_2D_ARRAY:
2150 if (context->getClientVersion() < 3)
2151 {
Jamie Madill437fa652016-05-03 15:13:24 -04002152 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002153 return false;
2154 }
2155 break;
2156 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002157 if (!context->getExtensions().eglImageExternal &&
2158 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002159 {
Jamie Madill437fa652016-05-03 15:13:24 -04002160 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002161 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2162 return false;
2163 }
2164 break;
2165 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002166 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002167 return false;
2168 }
2169
2170 return true;
2171}
2172
Geoff Langd8605522016-04-13 10:19:12 -04002173bool ValidateBindUniformLocationCHROMIUM(Context *context,
2174 GLuint program,
2175 GLint location,
2176 const GLchar *name)
2177{
2178 if (!context->getExtensions().bindUniformLocation)
2179 {
Jamie Madill437fa652016-05-03 15:13:24 -04002180 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002181 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2182 return false;
2183 }
2184
2185 Program *programObject = GetValidProgram(context, program);
2186 if (!programObject)
2187 {
2188 return false;
2189 }
2190
2191 if (location < 0)
2192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002194 return false;
2195 }
2196
2197 const Caps &caps = context->getCaps();
2198 if (static_cast<size_t>(location) >=
2199 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2200 {
Jamie Madill437fa652016-05-03 15:13:24 -04002201 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002202 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2203 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2204 return false;
2205 }
2206
2207 if (strncmp(name, "gl_", 3) == 0)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002210 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2211 return false;
2212 }
2213
2214 return true;
2215}
2216
Jamie Madille2e406c2016-06-02 13:04:10 -04002217bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002218{
2219 if (!context->getExtensions().framebufferMixedSamples)
2220 {
2221 context->handleError(
2222 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2223 return false;
2224 }
2225 switch (components)
2226 {
2227 case GL_RGB:
2228 case GL_RGBA:
2229 case GL_ALPHA:
2230 case GL_NONE:
2231 break;
2232 default:
2233 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002234 Error(GL_INVALID_ENUM,
2235 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002236 return false;
2237 }
2238
2239 return true;
2240}
2241
Sami Väisänene45e53b2016-05-25 10:36:04 +03002242// CHROMIUM_path_rendering
2243
2244bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2245{
2246 if (!context->getExtensions().pathRendering)
2247 {
2248 context->handleError(
2249 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2250 return false;
2251 }
2252 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2253 {
2254 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2255 return false;
2256 }
2257 if (matrix == nullptr)
2258 {
2259 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2260 return false;
2261 }
2262 return true;
2263}
2264
2265bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2266{
2267 if (!context->getExtensions().pathRendering)
2268 {
2269 context->handleError(
2270 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2271 return false;
2272 }
2273 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2274 {
2275 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2276 return false;
2277 }
2278 return true;
2279}
2280
2281bool ValidateGenPaths(Context *context, GLsizei range)
2282{
2283 if (!context->getExtensions().pathRendering)
2284 {
2285 context->handleError(
2286 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2287 return false;
2288 }
2289
2290 // range = 0 is undefined in NV_path_rendering.
2291 // we add stricter semantic check here and require a non zero positive range.
2292 if (range <= 0)
2293 {
2294 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2295 return false;
2296 }
2297
2298 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2299 {
2300 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2301 return false;
2302 }
2303
2304 return true;
2305}
2306
2307bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2308{
2309 if (!context->getExtensions().pathRendering)
2310 {
2311 context->handleError(
2312 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2313 return false;
2314 }
2315
2316 // range = 0 is undefined in NV_path_rendering.
2317 // we add stricter semantic check here and require a non zero positive range.
2318 if (range <= 0)
2319 {
2320 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2321 return false;
2322 }
2323
2324 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2325 checkedRange += range;
2326
2327 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2328 {
2329 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2330 return false;
2331 }
2332 return true;
2333}
2334
2335bool ValidatePathCommands(Context *context,
2336 GLuint path,
2337 GLsizei numCommands,
2338 const GLubyte *commands,
2339 GLsizei numCoords,
2340 GLenum coordType,
2341 const void *coords)
2342{
2343 if (!context->getExtensions().pathRendering)
2344 {
2345 context->handleError(
2346 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2347 return false;
2348 }
2349 if (!context->hasPath(path))
2350 {
2351 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2352 return false;
2353 }
2354
2355 if (numCommands < 0)
2356 {
2357 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2358 return false;
2359 }
2360 else if (numCommands > 0)
2361 {
2362 if (!commands)
2363 {
2364 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2365 return false;
2366 }
2367 }
2368
2369 if (numCoords < 0)
2370 {
2371 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2372 return false;
2373 }
2374 else if (numCoords > 0)
2375 {
2376 if (!coords)
2377 {
2378 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2379 return false;
2380 }
2381 }
2382
2383 std::uint32_t coordTypeSize = 0;
2384 switch (coordType)
2385 {
2386 case GL_BYTE:
2387 coordTypeSize = sizeof(GLbyte);
2388 break;
2389
2390 case GL_UNSIGNED_BYTE:
2391 coordTypeSize = sizeof(GLubyte);
2392 break;
2393
2394 case GL_SHORT:
2395 coordTypeSize = sizeof(GLshort);
2396 break;
2397
2398 case GL_UNSIGNED_SHORT:
2399 coordTypeSize = sizeof(GLushort);
2400 break;
2401
2402 case GL_FLOAT:
2403 coordTypeSize = sizeof(GLfloat);
2404 break;
2405
2406 default:
2407 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2408 return false;
2409 }
2410
2411 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2412 checkedSize += (coordTypeSize * numCoords);
2413 if (!checkedSize.IsValid())
2414 {
2415 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2416 return false;
2417 }
2418
2419 // early return skips command data validation when it doesn't exist.
2420 if (!commands)
2421 return true;
2422
2423 GLsizei expectedNumCoords = 0;
2424 for (GLsizei i = 0; i < numCommands; ++i)
2425 {
2426 switch (commands[i])
2427 {
2428 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2429 break;
2430 case GL_MOVE_TO_CHROMIUM:
2431 case GL_LINE_TO_CHROMIUM:
2432 expectedNumCoords += 2;
2433 break;
2434 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2435 expectedNumCoords += 4;
2436 break;
2437 case GL_CUBIC_CURVE_TO_CHROMIUM:
2438 expectedNumCoords += 6;
2439 break;
2440 case GL_CONIC_CURVE_TO_CHROMIUM:
2441 expectedNumCoords += 5;
2442 break;
2443 default:
2444 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2445 return false;
2446 }
2447 }
2448 if (expectedNumCoords != numCoords)
2449 {
2450 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2451 return false;
2452 }
2453
2454 return true;
2455}
2456
2457bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2458{
2459 if (!context->getExtensions().pathRendering)
2460 {
2461 context->handleError(
2462 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2463 return false;
2464 }
2465 if (!context->hasPath(path))
2466 {
2467 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2468 return false;
2469 }
2470
2471 switch (pname)
2472 {
2473 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2474 if (value < 0.0f)
2475 {
2476 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2477 return false;
2478 }
2479 break;
2480 case GL_PATH_END_CAPS_CHROMIUM:
2481 switch (static_cast<GLenum>(value))
2482 {
2483 case GL_FLAT_CHROMIUM:
2484 case GL_SQUARE_CHROMIUM:
2485 case GL_ROUND_CHROMIUM:
2486 break;
2487 default:
2488 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2489 return false;
2490 }
2491 break;
2492 case GL_PATH_JOIN_STYLE_CHROMIUM:
2493 switch (static_cast<GLenum>(value))
2494 {
2495 case GL_MITER_REVERT_CHROMIUM:
2496 case GL_BEVEL_CHROMIUM:
2497 case GL_ROUND_CHROMIUM:
2498 break;
2499 default:
2500 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2501 return false;
2502 }
2503 case GL_PATH_MITER_LIMIT_CHROMIUM:
2504 if (value < 0.0f)
2505 {
2506 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2507 return false;
2508 }
2509 break;
2510
2511 case GL_PATH_STROKE_BOUND_CHROMIUM:
2512 // no errors, only clamping.
2513 break;
2514
2515 default:
2516 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2517 return false;
2518 }
2519 return true;
2520}
2521
2522bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2523{
2524 if (!context->getExtensions().pathRendering)
2525 {
2526 context->handleError(
2527 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2528 return false;
2529 }
2530
2531 if (!context->hasPath(path))
2532 {
2533 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2534 return false;
2535 }
2536 if (!value)
2537 {
2538 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2539 return false;
2540 }
2541
2542 switch (pname)
2543 {
2544 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2545 case GL_PATH_END_CAPS_CHROMIUM:
2546 case GL_PATH_JOIN_STYLE_CHROMIUM:
2547 case GL_PATH_MITER_LIMIT_CHROMIUM:
2548 case GL_PATH_STROKE_BOUND_CHROMIUM:
2549 break;
2550
2551 default:
2552 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2553 return false;
2554 }
2555
2556 return true;
2557}
2558
2559bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2560{
2561 if (!context->getExtensions().pathRendering)
2562 {
2563 context->handleError(
2564 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2565 return false;
2566 }
2567
2568 switch (func)
2569 {
2570 case GL_NEVER:
2571 case GL_ALWAYS:
2572 case GL_LESS:
2573 case GL_LEQUAL:
2574 case GL_EQUAL:
2575 case GL_GEQUAL:
2576 case GL_GREATER:
2577 case GL_NOTEQUAL:
2578 break;
2579 default:
2580 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2581 return false;
2582 }
2583
2584 return true;
2585}
2586
2587// Note that the spec specifies that for the path drawing commands
2588// if the path object is not an existing path object the command
2589// does nothing and no error is generated.
2590// However if the path object exists but has not been specified any
2591// commands then an error is generated.
2592
2593bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2594{
2595 if (!context->getExtensions().pathRendering)
2596 {
2597 context->handleError(
2598 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2599 return false;
2600 }
2601 if (context->hasPath(path) && !context->hasPathData(path))
2602 {
2603 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2604 return false;
2605 }
2606
2607 switch (fillMode)
2608 {
2609 case GL_COUNT_UP_CHROMIUM:
2610 case GL_COUNT_DOWN_CHROMIUM:
2611 break;
2612 default:
2613 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2614 return false;
2615 }
2616
2617 if (!isPow2(mask + 1))
2618 {
2619 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2620 return false;
2621 }
2622
2623 return true;
2624}
2625
2626bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2627{
2628 if (!context->getExtensions().pathRendering)
2629 {
2630 context->handleError(
2631 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2632 return false;
2633 }
2634 if (context->hasPath(path) && !context->hasPathData(path))
2635 {
2636 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2637 return false;
2638 }
2639
2640 return true;
2641}
2642
2643bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2644{
2645 if (!context->getExtensions().pathRendering)
2646 {
2647 context->handleError(
2648 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2649 return false;
2650 }
2651 if (context->hasPath(path) && !context->hasPathData(path))
2652 {
2653 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2654 return false;
2655 }
2656
2657 switch (coverMode)
2658 {
2659 case GL_CONVEX_HULL_CHROMIUM:
2660 case GL_BOUNDING_BOX_CHROMIUM:
2661 break;
2662 default:
2663 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2664 return false;
2665 }
2666 return true;
2667}
2668
2669bool ValidateStencilThenCoverFillPath(Context *context,
2670 GLuint path,
2671 GLenum fillMode,
2672 GLuint mask,
2673 GLenum coverMode)
2674{
2675 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2676 ValidateCoverPath(context, path, coverMode);
2677}
2678
2679bool ValidateStencilThenCoverStrokePath(Context *context,
2680 GLuint path,
2681 GLint reference,
2682 GLuint mask,
2683 GLenum coverMode)
2684{
2685 return ValidateStencilStrokePath(context, path, reference, mask) &&
2686 ValidateCoverPath(context, path, coverMode);
2687}
2688
2689bool ValidateIsPath(Context *context)
2690{
2691 if (!context->getExtensions().pathRendering)
2692 {
2693 context->handleError(
2694 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2695 return false;
2696 }
2697 return true;
2698}
2699
Sami Väisänend59ca052016-06-21 16:10:00 +03002700bool ValidateCoverFillPathInstanced(Context *context,
2701 GLsizei numPaths,
2702 GLenum pathNameType,
2703 const void *paths,
2704 GLuint pathBase,
2705 GLenum coverMode,
2706 GLenum transformType,
2707 const GLfloat *transformValues)
2708{
2709 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2710 transformType, transformValues))
2711 return false;
2712
2713 switch (coverMode)
2714 {
2715 case GL_CONVEX_HULL_CHROMIUM:
2716 case GL_BOUNDING_BOX_CHROMIUM:
2717 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2718 break;
2719 default:
2720 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2721 return false;
2722 }
2723
2724 return true;
2725}
2726
2727bool ValidateCoverStrokePathInstanced(Context *context,
2728 GLsizei numPaths,
2729 GLenum pathNameType,
2730 const void *paths,
2731 GLuint pathBase,
2732 GLenum coverMode,
2733 GLenum transformType,
2734 const GLfloat *transformValues)
2735{
2736 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2737 transformType, transformValues))
2738 return false;
2739
2740 switch (coverMode)
2741 {
2742 case GL_CONVEX_HULL_CHROMIUM:
2743 case GL_BOUNDING_BOX_CHROMIUM:
2744 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2745 break;
2746 default:
2747 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2748 return false;
2749 }
2750
2751 return true;
2752}
2753
2754bool ValidateStencilFillPathInstanced(Context *context,
2755 GLsizei numPaths,
2756 GLenum pathNameType,
2757 const void *paths,
2758 GLuint pathBase,
2759 GLenum fillMode,
2760 GLuint mask,
2761 GLenum transformType,
2762 const GLfloat *transformValues)
2763{
2764
2765 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2766 transformType, transformValues))
2767 return false;
2768
2769 switch (fillMode)
2770 {
2771 case GL_COUNT_UP_CHROMIUM:
2772 case GL_COUNT_DOWN_CHROMIUM:
2773 break;
2774 default:
2775 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2776 return false;
2777 }
2778 if (!isPow2(mask + 1))
2779 {
2780 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2781 return false;
2782 }
2783 return true;
2784}
2785
2786bool ValidateStencilStrokePathInstanced(Context *context,
2787 GLsizei numPaths,
2788 GLenum pathNameType,
2789 const void *paths,
2790 GLuint pathBase,
2791 GLint reference,
2792 GLuint mask,
2793 GLenum transformType,
2794 const GLfloat *transformValues)
2795{
2796 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2797 transformType, transformValues))
2798 return false;
2799
2800 // no more validation here.
2801
2802 return true;
2803}
2804
2805bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2806 GLsizei numPaths,
2807 GLenum pathNameType,
2808 const void *paths,
2809 GLuint pathBase,
2810 GLenum fillMode,
2811 GLuint mask,
2812 GLenum coverMode,
2813 GLenum transformType,
2814 const GLfloat *transformValues)
2815{
2816 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2817 transformType, transformValues))
2818 return false;
2819
2820 switch (coverMode)
2821 {
2822 case GL_CONVEX_HULL_CHROMIUM:
2823 case GL_BOUNDING_BOX_CHROMIUM:
2824 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2825 break;
2826 default:
2827 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2828 return false;
2829 }
2830
2831 switch (fillMode)
2832 {
2833 case GL_COUNT_UP_CHROMIUM:
2834 case GL_COUNT_DOWN_CHROMIUM:
2835 break;
2836 default:
2837 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2838 return false;
2839 }
2840 if (!isPow2(mask + 1))
2841 {
2842 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2843 return false;
2844 }
2845
2846 return true;
2847}
2848
2849bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2850 GLsizei numPaths,
2851 GLenum pathNameType,
2852 const void *paths,
2853 GLuint pathBase,
2854 GLint reference,
2855 GLuint mask,
2856 GLenum coverMode,
2857 GLenum transformType,
2858 const GLfloat *transformValues)
2859{
2860 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2861 transformType, transformValues))
2862 return false;
2863
2864 switch (coverMode)
2865 {
2866 case GL_CONVEX_HULL_CHROMIUM:
2867 case GL_BOUNDING_BOX_CHROMIUM:
2868 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2869 break;
2870 default:
2871 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2872 return false;
2873 }
2874
2875 return true;
2876}
2877
Sami Väisänen46eaa942016-06-29 10:26:37 +03002878bool ValidateBindFragmentInputLocation(Context *context,
2879 GLuint program,
2880 GLint location,
2881 const GLchar *name)
2882{
2883 if (!context->getExtensions().pathRendering)
2884 {
2885 context->handleError(
2886 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2887 return false;
2888 }
2889
2890 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2891 if (location >= MaxLocation)
2892 {
2893 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2894 return false;
2895 }
2896
2897 const auto *programObject = context->getProgram(program);
2898 if (!programObject)
2899 {
2900 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2901 return false;
2902 }
2903
2904 if (!name)
2905 {
2906 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2907 return false;
2908 }
2909
2910 if (angle::BeginsWith(name, "gl_"))
2911 {
2912 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2913 return false;
2914 }
2915
2916 return true;
2917}
2918
2919bool ValidateProgramPathFragmentInputGen(Context *context,
2920 GLuint program,
2921 GLint location,
2922 GLenum genMode,
2923 GLint components,
2924 const GLfloat *coeffs)
2925{
2926 if (!context->getExtensions().pathRendering)
2927 {
2928 context->handleError(
2929 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2930 return false;
2931 }
2932
2933 const auto *programObject = context->getProgram(program);
2934 if (!programObject || programObject->isFlaggedForDeletion())
2935 {
2936 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2937 return false;
2938 }
2939
2940 if (!programObject->isLinked())
2941 {
2942 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2943 return false;
2944 }
2945
2946 switch (genMode)
2947 {
2948 case GL_NONE:
2949 if (components != 0)
2950 {
2951 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2952 return false;
2953 }
2954 break;
2955
2956 case GL_OBJECT_LINEAR_CHROMIUM:
2957 case GL_EYE_LINEAR_CHROMIUM:
2958 case GL_CONSTANT_CHROMIUM:
2959 if (components < 1 || components > 4)
2960 {
2961 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2962 return false;
2963 }
2964 if (!coeffs)
2965 {
2966 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2967 return false;
2968 }
2969 break;
2970
2971 default:
2972 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2973 return false;
2974 }
2975
2976 // If the location is -1 then the command is silently ignored
2977 // and no further validation is needed.
2978 if (location == -1)
2979 return true;
2980
2981 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2982
2983 if (!binding.valid)
2984 {
2985 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
2986 return false;
2987 }
2988
2989 if (binding.type != GL_NONE)
2990 {
2991 GLint expectedComponents = 0;
2992 switch (binding.type)
2993 {
2994 case GL_FLOAT:
2995 expectedComponents = 1;
2996 break;
2997 case GL_FLOAT_VEC2:
2998 expectedComponents = 2;
2999 break;
3000 case GL_FLOAT_VEC3:
3001 expectedComponents = 3;
3002 break;
3003 case GL_FLOAT_VEC4:
3004 expectedComponents = 4;
3005 break;
3006 default:
3007 context->handleError(Error(GL_INVALID_OPERATION,
3008 "Fragment input type is not a floating point scalar or vector."));
3009 return false;
3010 }
3011 if (expectedComponents != components && genMode != GL_NONE)
3012 {
3013 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3014 return false;
3015 }
3016 }
3017 return true;
3018}
3019
Jamie Madillc29968b2016-01-20 11:17:23 -05003020} // namespace gl