blob: 8acf7da5f4e0ab200826c0ee63e7baf0e39dd9d7 [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 }
Geoff Lange102fee2015-12-10 11:23:30 -05001602}
1603
1604bool ValidateObjectLabelKHR(Context *context,
1605 GLenum identifier,
1606 GLuint name,
1607 GLsizei length,
1608 const GLchar *label)
1609{
1610 if (!context->getExtensions().debug)
1611 {
Jamie Madill437fa652016-05-03 15:13:24 -04001612 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001613 return false;
1614 }
1615
Geoff Lang70d0f492015-12-10 17:45:46 -05001616 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1617 {
1618 return false;
1619 }
1620
1621 size_t labelLength = (length < 0) ? strlen(label) : length;
1622 if (labelLength > context->getExtensions().maxLabelLength)
1623 {
Jamie Madill437fa652016-05-03 15:13:24 -04001624 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001625 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1626 return false;
1627 }
1628
Geoff Lange102fee2015-12-10 11:23:30 -05001629 return true;
1630}
1631
1632bool ValidateGetObjectLabelKHR(Context *context,
1633 GLenum identifier,
1634 GLuint name,
1635 GLsizei bufSize,
1636 GLsizei *length,
1637 GLchar *label)
1638{
1639 if (!context->getExtensions().debug)
1640 {
Jamie Madill437fa652016-05-03 15:13:24 -04001641 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001642 return false;
1643 }
1644
Geoff Lang70d0f492015-12-10 17:45:46 -05001645 if (bufSize < 0)
1646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001648 return false;
1649 }
1650
1651 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1652 {
1653 return false;
1654 }
1655
1656 // Can no-op if bufSize is zero.
1657 return bufSize > 0;
1658}
1659
1660static bool ValidateObjectPtrName(Context *context, const void *ptr)
1661{
1662 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1663 {
Jamie Madill437fa652016-05-03 15:13:24 -04001664 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001665 return false;
1666 }
1667
Geoff Lange102fee2015-12-10 11:23:30 -05001668 return true;
1669}
1670
1671bool ValidateObjectPtrLabelKHR(Context *context,
1672 const void *ptr,
1673 GLsizei length,
1674 const GLchar *label)
1675{
1676 if (!context->getExtensions().debug)
1677 {
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001679 return false;
1680 }
1681
Geoff Lang70d0f492015-12-10 17:45:46 -05001682 if (!ValidateObjectPtrName(context, ptr))
1683 {
1684 return false;
1685 }
1686
1687 size_t labelLength = (length < 0) ? strlen(label) : length;
1688 if (labelLength > context->getExtensions().maxLabelLength)
1689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001691 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1692 return false;
1693 }
1694
Geoff Lange102fee2015-12-10 11:23:30 -05001695 return true;
1696}
1697
1698bool ValidateGetObjectPtrLabelKHR(Context *context,
1699 const void *ptr,
1700 GLsizei bufSize,
1701 GLsizei *length,
1702 GLchar *label)
1703{
1704 if (!context->getExtensions().debug)
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001707 return false;
1708 }
1709
Geoff Lang70d0f492015-12-10 17:45:46 -05001710 if (bufSize < 0)
1711 {
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001713 return false;
1714 }
1715
1716 if (!ValidateObjectPtrName(context, ptr))
1717 {
1718 return false;
1719 }
1720
1721 // Can no-op if bufSize is zero.
1722 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001723}
1724
1725bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1726{
1727 if (!context->getExtensions().debug)
1728 {
Jamie Madill437fa652016-05-03 15:13:24 -04001729 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001730 return false;
1731 }
1732
Geoff Lang70d0f492015-12-10 17:45:46 -05001733 // TODO: represent this in Context::getQueryParameterInfo.
1734 switch (pname)
1735 {
1736 case GL_DEBUG_CALLBACK_FUNCTION:
1737 case GL_DEBUG_CALLBACK_USER_PARAM:
1738 break;
1739
1740 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 return false;
1743 }
1744
Geoff Lange102fee2015-12-10 11:23:30 -05001745 return true;
1746}
Jamie Madillc29968b2016-01-20 11:17:23 -05001747
1748bool ValidateBlitFramebufferANGLE(Context *context,
1749 GLint srcX0,
1750 GLint srcY0,
1751 GLint srcX1,
1752 GLint srcY1,
1753 GLint dstX0,
1754 GLint dstY0,
1755 GLint dstX1,
1756 GLint dstY1,
1757 GLbitfield mask,
1758 GLenum filter)
1759{
1760 if (!context->getExtensions().framebufferBlit)
1761 {
Jamie Madill437fa652016-05-03 15:13:24 -04001762 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001763 return false;
1764 }
1765
1766 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1767 {
1768 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001769 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001770 GL_INVALID_OPERATION,
1771 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1772 return false;
1773 }
1774
1775 if (filter == GL_LINEAR)
1776 {
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001778 return false;
1779 }
1780
Jamie Madill51f40ec2016-06-15 14:06:00 -04001781 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1782 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001783
1784 if (mask & GL_COLOR_BUFFER_BIT)
1785 {
1786 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1787 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1788
1789 if (readColorAttachment && drawColorAttachment)
1790 {
1791 if (!(readColorAttachment->type() == GL_TEXTURE &&
1792 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1793 readColorAttachment->type() != GL_RENDERBUFFER &&
1794 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001797 return false;
1798 }
1799
Geoff Langa15472a2015-08-11 11:48:03 -04001800 for (size_t drawbufferIdx = 0;
1801 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001802 {
Geoff Langa15472a2015-08-11 11:48:03 -04001803 const FramebufferAttachment *attachment =
1804 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1805 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001806 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001807 if (!(attachment->type() == GL_TEXTURE &&
1808 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1809 attachment->type() != GL_RENDERBUFFER &&
1810 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1811 {
Jamie Madill437fa652016-05-03 15:13:24 -04001812 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 return false;
1814 }
1815
1816 // Return an error if the destination formats do not match
1817 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1818 {
Jamie Madill437fa652016-05-03 15:13:24 -04001819 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001820 return false;
1821 }
1822 }
1823 }
1824
Jamie Madill51f40ec2016-06-15 14:06:00 -04001825 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001826 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1827 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832 }
1833 }
1834
1835 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1836 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1837 for (size_t i = 0; i < 2; i++)
1838 {
1839 if (mask & masks[i])
1840 {
1841 const FramebufferAttachment *readBuffer =
1842 readFramebuffer->getAttachment(attachments[i]);
1843 const FramebufferAttachment *drawBuffer =
1844 drawFramebuffer->getAttachment(attachments[i]);
1845
1846 if (readBuffer && drawBuffer)
1847 {
1848 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1849 dstX0, dstY0, dstX1, dstY1))
1850 {
1851 // only whole-buffer copies are permitted
1852 ERR(
1853 "Only whole-buffer depth and stencil blits are supported by this "
1854 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 return false;
1857 }
1858
1859 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001862 return false;
1863 }
1864 }
1865 }
1866 }
1867
1868 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1869 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001870}
Jamie Madillc29968b2016-01-20 11:17:23 -05001871
1872bool ValidateClear(ValidationContext *context, GLbitfield mask)
1873{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001874 auto fbo = context->getGLState().getDrawFramebuffer();
1875 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 {
Jamie Madill437fa652016-05-03 15:13:24 -04001877 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001878 return false;
1879 }
1880
1881 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1882 {
Jamie Madill437fa652016-05-03 15:13:24 -04001883 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001884 return false;
1885 }
1886
1887 return true;
1888}
1889
1890bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1891{
1892 if (!context->getExtensions().drawBuffers)
1893 {
Jamie Madill437fa652016-05-03 15:13:24 -04001894 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001895 return false;
1896 }
1897
1898 return ValidateDrawBuffersBase(context, n, bufs);
1899}
1900
Jamie Madill73a84962016-02-12 09:27:23 -05001901bool ValidateTexImage2D(Context *context,
1902 GLenum target,
1903 GLint level,
1904 GLint internalformat,
1905 GLsizei width,
1906 GLsizei height,
1907 GLint border,
1908 GLenum format,
1909 GLenum type,
1910 const GLvoid *pixels)
1911{
1912 if (context->getClientVersion() < 3)
1913 {
1914 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1915 0, 0, width, height, border, format, type, pixels);
1916 }
1917
1918 ASSERT(context->getClientVersion() >= 3);
1919 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1920 0, 0, width, height, 1, border, format, type, pixels);
1921}
1922
1923bool ValidateTexSubImage2D(Context *context,
1924 GLenum target,
1925 GLint level,
1926 GLint xoffset,
1927 GLint yoffset,
1928 GLsizei width,
1929 GLsizei height,
1930 GLenum format,
1931 GLenum type,
1932 const GLvoid *pixels)
1933{
1934
1935 if (context->getClientVersion() < 3)
1936 {
1937 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1938 yoffset, width, height, 0, format, type, pixels);
1939 }
1940
1941 ASSERT(context->getClientVersion() >= 3);
1942 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1943 yoffset, 0, width, height, 1, 0, format, type, pixels);
1944}
1945
1946bool ValidateCompressedTexImage2D(Context *context,
1947 GLenum target,
1948 GLint level,
1949 GLenum internalformat,
1950 GLsizei width,
1951 GLsizei height,
1952 GLint border,
1953 GLsizei imageSize,
1954 const GLvoid *data)
1955{
1956 if (context->getClientVersion() < 3)
1957 {
1958 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1959 0, width, height, border, GL_NONE, GL_NONE, data))
1960 {
1961 return false;
1962 }
1963 }
1964 else
1965 {
1966 ASSERT(context->getClientVersion() >= 3);
1967 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1968 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1969 data))
1970 {
1971 return false;
1972 }
1973 }
1974
1975 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001976 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001977 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001978 if (blockSizeOrErr.isError())
1979 {
1980 context->handleError(blockSizeOrErr.getError());
1981 return false;
1982 }
1983
1984 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05001985 {
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05001987 return false;
1988 }
1989
1990 return true;
1991}
1992
1993bool ValidateCompressedTexSubImage2D(Context *context,
1994 GLenum target,
1995 GLint level,
1996 GLint xoffset,
1997 GLint yoffset,
1998 GLsizei width,
1999 GLsizei height,
2000 GLenum format,
2001 GLsizei imageSize,
2002 const GLvoid *data)
2003{
2004 if (context->getClientVersion() < 3)
2005 {
2006 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2007 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2008 {
2009 return false;
2010 }
2011 }
2012 else
2013 {
2014 ASSERT(context->getClientVersion() >= 3);
2015 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2016 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2017 data))
2018 {
2019 return false;
2020 }
2021 }
2022
2023 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002024 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002025 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002026 if (blockSizeOrErr.isError())
2027 {
2028 context->handleError(blockSizeOrErr.getError());
2029 return false;
2030 }
2031
2032 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002033 {
Jamie Madill437fa652016-05-03 15:13:24 -04002034 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002035 return false;
2036 }
2037
2038 return true;
2039}
2040
Olli Etuaho4f667482016-03-30 15:56:35 +03002041bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2042{
2043 if (!context->getExtensions().mapBuffer)
2044 {
Jamie Madill437fa652016-05-03 15:13:24 -04002045 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002046 return false;
2047 }
2048
2049 return ValidateGetBufferPointervBase(context, target, pname, params);
2050}
2051
2052bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2053{
2054 if (!context->getExtensions().mapBuffer)
2055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002057 return false;
2058 }
2059
2060 if (!ValidBufferTarget(context, target))
2061 {
Jamie Madill437fa652016-05-03 15:13:24 -04002062 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002063 return false;
2064 }
2065
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002066 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002067
2068 if (buffer == nullptr)
2069 {
Jamie Madill437fa652016-05-03 15:13:24 -04002070 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002071 return false;
2072 }
2073
2074 if (access != GL_WRITE_ONLY_OES)
2075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002077 return false;
2078 }
2079
2080 if (buffer->isMapped())
2081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002083 return false;
2084 }
2085
2086 return true;
2087}
2088
2089bool ValidateUnmapBufferOES(Context *context, GLenum target)
2090{
2091 if (!context->getExtensions().mapBuffer)
2092 {
Jamie Madill437fa652016-05-03 15:13:24 -04002093 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002094 return false;
2095 }
2096
2097 return ValidateUnmapBufferBase(context, target);
2098}
2099
2100bool ValidateMapBufferRangeEXT(Context *context,
2101 GLenum target,
2102 GLintptr offset,
2103 GLsizeiptr length,
2104 GLbitfield access)
2105{
2106 if (!context->getExtensions().mapBufferRange)
2107 {
Jamie Madill437fa652016-05-03 15:13:24 -04002108 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002109 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2110 return false;
2111 }
2112
2113 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2114}
2115
2116bool ValidateFlushMappedBufferRangeEXT(Context *context,
2117 GLenum target,
2118 GLintptr offset,
2119 GLsizeiptr length)
2120{
2121 if (!context->getExtensions().mapBufferRange)
2122 {
Jamie Madill437fa652016-05-03 15:13:24 -04002123 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002124 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2125 return false;
2126 }
2127
2128 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2129}
2130
Ian Ewell54f87462016-03-10 13:47:21 -05002131bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2132{
2133 Texture *textureObject = context->getTexture(texture);
2134 if (textureObject && textureObject->getTarget() != target && texture != 0)
2135 {
Jamie Madill437fa652016-05-03 15:13:24 -04002136 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002137 return false;
2138 }
2139
2140 switch (target)
2141 {
2142 case GL_TEXTURE_2D:
2143 case GL_TEXTURE_CUBE_MAP:
2144 break;
2145
2146 case GL_TEXTURE_3D:
2147 case GL_TEXTURE_2D_ARRAY:
2148 if (context->getClientVersion() < 3)
2149 {
Jamie Madill437fa652016-05-03 15:13:24 -04002150 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002151 return false;
2152 }
2153 break;
2154 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002155 if (!context->getExtensions().eglImageExternal &&
2156 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002157 {
Jamie Madill437fa652016-05-03 15:13:24 -04002158 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002159 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2160 return false;
2161 }
2162 break;
2163 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002164 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002165 return false;
2166 }
2167
2168 return true;
2169}
2170
Geoff Langd8605522016-04-13 10:19:12 -04002171bool ValidateBindUniformLocationCHROMIUM(Context *context,
2172 GLuint program,
2173 GLint location,
2174 const GLchar *name)
2175{
2176 if (!context->getExtensions().bindUniformLocation)
2177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002179 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2180 return false;
2181 }
2182
2183 Program *programObject = GetValidProgram(context, program);
2184 if (!programObject)
2185 {
2186 return false;
2187 }
2188
2189 if (location < 0)
2190 {
Jamie Madill437fa652016-05-03 15:13:24 -04002191 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002192 return false;
2193 }
2194
2195 const Caps &caps = context->getCaps();
2196 if (static_cast<size_t>(location) >=
2197 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2198 {
Jamie Madill437fa652016-05-03 15:13:24 -04002199 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002200 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2201 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2202 return false;
2203 }
2204
2205 if (strncmp(name, "gl_", 3) == 0)
2206 {
Jamie Madill437fa652016-05-03 15:13:24 -04002207 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002208 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2209 return false;
2210 }
2211
2212 return true;
2213}
2214
Jamie Madille2e406c2016-06-02 13:04:10 -04002215bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002216{
2217 if (!context->getExtensions().framebufferMixedSamples)
2218 {
2219 context->handleError(
2220 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2221 return false;
2222 }
2223 switch (components)
2224 {
2225 case GL_RGB:
2226 case GL_RGBA:
2227 case GL_ALPHA:
2228 case GL_NONE:
2229 break;
2230 default:
2231 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002232 Error(GL_INVALID_ENUM,
2233 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002234 return false;
2235 }
2236
2237 return true;
2238}
2239
Sami Väisänene45e53b2016-05-25 10:36:04 +03002240// CHROMIUM_path_rendering
2241
2242bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2243{
2244 if (!context->getExtensions().pathRendering)
2245 {
2246 context->handleError(
2247 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2248 return false;
2249 }
2250 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2251 {
2252 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2253 return false;
2254 }
2255 if (matrix == nullptr)
2256 {
2257 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2258 return false;
2259 }
2260 return true;
2261}
2262
2263bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2264{
2265 if (!context->getExtensions().pathRendering)
2266 {
2267 context->handleError(
2268 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2269 return false;
2270 }
2271 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2272 {
2273 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2274 return false;
2275 }
2276 return true;
2277}
2278
2279bool ValidateGenPaths(Context *context, GLsizei range)
2280{
2281 if (!context->getExtensions().pathRendering)
2282 {
2283 context->handleError(
2284 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2285 return false;
2286 }
2287
2288 // range = 0 is undefined in NV_path_rendering.
2289 // we add stricter semantic check here and require a non zero positive range.
2290 if (range <= 0)
2291 {
2292 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2293 return false;
2294 }
2295
2296 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2297 {
2298 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2299 return false;
2300 }
2301
2302 return true;
2303}
2304
2305bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2306{
2307 if (!context->getExtensions().pathRendering)
2308 {
2309 context->handleError(
2310 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2311 return false;
2312 }
2313
2314 // range = 0 is undefined in NV_path_rendering.
2315 // we add stricter semantic check here and require a non zero positive range.
2316 if (range <= 0)
2317 {
2318 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2319 return false;
2320 }
2321
2322 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2323 checkedRange += range;
2324
2325 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2326 {
2327 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2328 return false;
2329 }
2330 return true;
2331}
2332
2333bool ValidatePathCommands(Context *context,
2334 GLuint path,
2335 GLsizei numCommands,
2336 const GLubyte *commands,
2337 GLsizei numCoords,
2338 GLenum coordType,
2339 const void *coords)
2340{
2341 if (!context->getExtensions().pathRendering)
2342 {
2343 context->handleError(
2344 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2345 return false;
2346 }
2347 if (!context->hasPath(path))
2348 {
2349 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2350 return false;
2351 }
2352
2353 if (numCommands < 0)
2354 {
2355 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2356 return false;
2357 }
2358 else if (numCommands > 0)
2359 {
2360 if (!commands)
2361 {
2362 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2363 return false;
2364 }
2365 }
2366
2367 if (numCoords < 0)
2368 {
2369 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2370 return false;
2371 }
2372 else if (numCoords > 0)
2373 {
2374 if (!coords)
2375 {
2376 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2377 return false;
2378 }
2379 }
2380
2381 std::uint32_t coordTypeSize = 0;
2382 switch (coordType)
2383 {
2384 case GL_BYTE:
2385 coordTypeSize = sizeof(GLbyte);
2386 break;
2387
2388 case GL_UNSIGNED_BYTE:
2389 coordTypeSize = sizeof(GLubyte);
2390 break;
2391
2392 case GL_SHORT:
2393 coordTypeSize = sizeof(GLshort);
2394 break;
2395
2396 case GL_UNSIGNED_SHORT:
2397 coordTypeSize = sizeof(GLushort);
2398 break;
2399
2400 case GL_FLOAT:
2401 coordTypeSize = sizeof(GLfloat);
2402 break;
2403
2404 default:
2405 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2406 return false;
2407 }
2408
2409 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2410 checkedSize += (coordTypeSize * numCoords);
2411 if (!checkedSize.IsValid())
2412 {
2413 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2414 return false;
2415 }
2416
2417 // early return skips command data validation when it doesn't exist.
2418 if (!commands)
2419 return true;
2420
2421 GLsizei expectedNumCoords = 0;
2422 for (GLsizei i = 0; i < numCommands; ++i)
2423 {
2424 switch (commands[i])
2425 {
2426 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2427 break;
2428 case GL_MOVE_TO_CHROMIUM:
2429 case GL_LINE_TO_CHROMIUM:
2430 expectedNumCoords += 2;
2431 break;
2432 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2433 expectedNumCoords += 4;
2434 break;
2435 case GL_CUBIC_CURVE_TO_CHROMIUM:
2436 expectedNumCoords += 6;
2437 break;
2438 case GL_CONIC_CURVE_TO_CHROMIUM:
2439 expectedNumCoords += 5;
2440 break;
2441 default:
2442 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2443 return false;
2444 }
2445 }
2446 if (expectedNumCoords != numCoords)
2447 {
2448 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2449 return false;
2450 }
2451
2452 return true;
2453}
2454
2455bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2456{
2457 if (!context->getExtensions().pathRendering)
2458 {
2459 context->handleError(
2460 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2461 return false;
2462 }
2463 if (!context->hasPath(path))
2464 {
2465 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2466 return false;
2467 }
2468
2469 switch (pname)
2470 {
2471 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2472 if (value < 0.0f)
2473 {
2474 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2475 return false;
2476 }
2477 break;
2478 case GL_PATH_END_CAPS_CHROMIUM:
2479 switch (static_cast<GLenum>(value))
2480 {
2481 case GL_FLAT_CHROMIUM:
2482 case GL_SQUARE_CHROMIUM:
2483 case GL_ROUND_CHROMIUM:
2484 break;
2485 default:
2486 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2487 return false;
2488 }
2489 break;
2490 case GL_PATH_JOIN_STYLE_CHROMIUM:
2491 switch (static_cast<GLenum>(value))
2492 {
2493 case GL_MITER_REVERT_CHROMIUM:
2494 case GL_BEVEL_CHROMIUM:
2495 case GL_ROUND_CHROMIUM:
2496 break;
2497 default:
2498 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2499 return false;
2500 }
2501 case GL_PATH_MITER_LIMIT_CHROMIUM:
2502 if (value < 0.0f)
2503 {
2504 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2505 return false;
2506 }
2507 break;
2508
2509 case GL_PATH_STROKE_BOUND_CHROMIUM:
2510 // no errors, only clamping.
2511 break;
2512
2513 default:
2514 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2515 return false;
2516 }
2517 return true;
2518}
2519
2520bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2521{
2522 if (!context->getExtensions().pathRendering)
2523 {
2524 context->handleError(
2525 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2526 return false;
2527 }
2528
2529 if (!context->hasPath(path))
2530 {
2531 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2532 return false;
2533 }
2534 if (!value)
2535 {
2536 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2537 return false;
2538 }
2539
2540 switch (pname)
2541 {
2542 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2543 case GL_PATH_END_CAPS_CHROMIUM:
2544 case GL_PATH_JOIN_STYLE_CHROMIUM:
2545 case GL_PATH_MITER_LIMIT_CHROMIUM:
2546 case GL_PATH_STROKE_BOUND_CHROMIUM:
2547 break;
2548
2549 default:
2550 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2551 return false;
2552 }
2553
2554 return true;
2555}
2556
2557bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2558{
2559 if (!context->getExtensions().pathRendering)
2560 {
2561 context->handleError(
2562 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2563 return false;
2564 }
2565
2566 switch (func)
2567 {
2568 case GL_NEVER:
2569 case GL_ALWAYS:
2570 case GL_LESS:
2571 case GL_LEQUAL:
2572 case GL_EQUAL:
2573 case GL_GEQUAL:
2574 case GL_GREATER:
2575 case GL_NOTEQUAL:
2576 break;
2577 default:
2578 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2579 return false;
2580 }
2581
2582 return true;
2583}
2584
2585// Note that the spec specifies that for the path drawing commands
2586// if the path object is not an existing path object the command
2587// does nothing and no error is generated.
2588// However if the path object exists but has not been specified any
2589// commands then an error is generated.
2590
2591bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2592{
2593 if (!context->getExtensions().pathRendering)
2594 {
2595 context->handleError(
2596 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2597 return false;
2598 }
2599 if (context->hasPath(path) && !context->hasPathData(path))
2600 {
2601 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2602 return false;
2603 }
2604
2605 switch (fillMode)
2606 {
2607 case GL_COUNT_UP_CHROMIUM:
2608 case GL_COUNT_DOWN_CHROMIUM:
2609 break;
2610 default:
2611 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2612 return false;
2613 }
2614
2615 if (!isPow2(mask + 1))
2616 {
2617 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2618 return false;
2619 }
2620
2621 return true;
2622}
2623
2624bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2625{
2626 if (!context->getExtensions().pathRendering)
2627 {
2628 context->handleError(
2629 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2630 return false;
2631 }
2632 if (context->hasPath(path) && !context->hasPathData(path))
2633 {
2634 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2635 return false;
2636 }
2637
2638 return true;
2639}
2640
2641bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2642{
2643 if (!context->getExtensions().pathRendering)
2644 {
2645 context->handleError(
2646 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2647 return false;
2648 }
2649 if (context->hasPath(path) && !context->hasPathData(path))
2650 {
2651 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2652 return false;
2653 }
2654
2655 switch (coverMode)
2656 {
2657 case GL_CONVEX_HULL_CHROMIUM:
2658 case GL_BOUNDING_BOX_CHROMIUM:
2659 break;
2660 default:
2661 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2662 return false;
2663 }
2664 return true;
2665}
2666
2667bool ValidateStencilThenCoverFillPath(Context *context,
2668 GLuint path,
2669 GLenum fillMode,
2670 GLuint mask,
2671 GLenum coverMode)
2672{
2673 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2674 ValidateCoverPath(context, path, coverMode);
2675}
2676
2677bool ValidateStencilThenCoverStrokePath(Context *context,
2678 GLuint path,
2679 GLint reference,
2680 GLuint mask,
2681 GLenum coverMode)
2682{
2683 return ValidateStencilStrokePath(context, path, reference, mask) &&
2684 ValidateCoverPath(context, path, coverMode);
2685}
2686
2687bool ValidateIsPath(Context *context)
2688{
2689 if (!context->getExtensions().pathRendering)
2690 {
2691 context->handleError(
2692 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2693 return false;
2694 }
2695 return true;
2696}
2697
Sami Väisänend59ca052016-06-21 16:10:00 +03002698bool ValidateCoverFillPathInstanced(Context *context,
2699 GLsizei numPaths,
2700 GLenum pathNameType,
2701 const void *paths,
2702 GLuint pathBase,
2703 GLenum coverMode,
2704 GLenum transformType,
2705 const GLfloat *transformValues)
2706{
2707 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2708 transformType, transformValues))
2709 return false;
2710
2711 switch (coverMode)
2712 {
2713 case GL_CONVEX_HULL_CHROMIUM:
2714 case GL_BOUNDING_BOX_CHROMIUM:
2715 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2716 break;
2717 default:
2718 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2719 return false;
2720 }
2721
2722 return true;
2723}
2724
2725bool ValidateCoverStrokePathInstanced(Context *context,
2726 GLsizei numPaths,
2727 GLenum pathNameType,
2728 const void *paths,
2729 GLuint pathBase,
2730 GLenum coverMode,
2731 GLenum transformType,
2732 const GLfloat *transformValues)
2733{
2734 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2735 transformType, transformValues))
2736 return false;
2737
2738 switch (coverMode)
2739 {
2740 case GL_CONVEX_HULL_CHROMIUM:
2741 case GL_BOUNDING_BOX_CHROMIUM:
2742 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2743 break;
2744 default:
2745 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2746 return false;
2747 }
2748
2749 return true;
2750}
2751
2752bool ValidateStencilFillPathInstanced(Context *context,
2753 GLsizei numPaths,
2754 GLenum pathNameType,
2755 const void *paths,
2756 GLuint pathBase,
2757 GLenum fillMode,
2758 GLuint mask,
2759 GLenum transformType,
2760 const GLfloat *transformValues)
2761{
2762
2763 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2764 transformType, transformValues))
2765 return false;
2766
2767 switch (fillMode)
2768 {
2769 case GL_COUNT_UP_CHROMIUM:
2770 case GL_COUNT_DOWN_CHROMIUM:
2771 break;
2772 default:
2773 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2774 return false;
2775 }
2776 if (!isPow2(mask + 1))
2777 {
2778 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2779 return false;
2780 }
2781 return true;
2782}
2783
2784bool ValidateStencilStrokePathInstanced(Context *context,
2785 GLsizei numPaths,
2786 GLenum pathNameType,
2787 const void *paths,
2788 GLuint pathBase,
2789 GLint reference,
2790 GLuint mask,
2791 GLenum transformType,
2792 const GLfloat *transformValues)
2793{
2794 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2795 transformType, transformValues))
2796 return false;
2797
2798 // no more validation here.
2799
2800 return true;
2801}
2802
2803bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2804 GLsizei numPaths,
2805 GLenum pathNameType,
2806 const void *paths,
2807 GLuint pathBase,
2808 GLenum fillMode,
2809 GLuint mask,
2810 GLenum coverMode,
2811 GLenum transformType,
2812 const GLfloat *transformValues)
2813{
2814 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2815 transformType, transformValues))
2816 return false;
2817
2818 switch (coverMode)
2819 {
2820 case GL_CONVEX_HULL_CHROMIUM:
2821 case GL_BOUNDING_BOX_CHROMIUM:
2822 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2823 break;
2824 default:
2825 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2826 return false;
2827 }
2828
2829 switch (fillMode)
2830 {
2831 case GL_COUNT_UP_CHROMIUM:
2832 case GL_COUNT_DOWN_CHROMIUM:
2833 break;
2834 default:
2835 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2836 return false;
2837 }
2838 if (!isPow2(mask + 1))
2839 {
2840 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2841 return false;
2842 }
2843
2844 return true;
2845}
2846
2847bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2848 GLsizei numPaths,
2849 GLenum pathNameType,
2850 const void *paths,
2851 GLuint pathBase,
2852 GLint reference,
2853 GLuint mask,
2854 GLenum coverMode,
2855 GLenum transformType,
2856 const GLfloat *transformValues)
2857{
2858 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2859 transformType, transformValues))
2860 return false;
2861
2862 switch (coverMode)
2863 {
2864 case GL_CONVEX_HULL_CHROMIUM:
2865 case GL_BOUNDING_BOX_CHROMIUM:
2866 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2867 break;
2868 default:
2869 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2870 return false;
2871 }
2872
2873 return true;
2874}
2875
Sami Väisänen46eaa942016-06-29 10:26:37 +03002876bool ValidateBindFragmentInputLocation(Context *context,
2877 GLuint program,
2878 GLint location,
2879 const GLchar *name)
2880{
2881 if (!context->getExtensions().pathRendering)
2882 {
2883 context->handleError(
2884 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2885 return false;
2886 }
2887
2888 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2889 if (location >= MaxLocation)
2890 {
2891 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2892 return false;
2893 }
2894
2895 const auto *programObject = context->getProgram(program);
2896 if (!programObject)
2897 {
2898 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2899 return false;
2900 }
2901
2902 if (!name)
2903 {
2904 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2905 return false;
2906 }
2907
2908 if (angle::BeginsWith(name, "gl_"))
2909 {
2910 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2911 return false;
2912 }
2913
2914 return true;
2915}
2916
2917bool ValidateProgramPathFragmentInputGen(Context *context,
2918 GLuint program,
2919 GLint location,
2920 GLenum genMode,
2921 GLint components,
2922 const GLfloat *coeffs)
2923{
2924 if (!context->getExtensions().pathRendering)
2925 {
2926 context->handleError(
2927 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2928 return false;
2929 }
2930
2931 const auto *programObject = context->getProgram(program);
2932 if (!programObject || programObject->isFlaggedForDeletion())
2933 {
2934 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2935 return false;
2936 }
2937
2938 if (!programObject->isLinked())
2939 {
2940 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2941 return false;
2942 }
2943
2944 switch (genMode)
2945 {
2946 case GL_NONE:
2947 if (components != 0)
2948 {
2949 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2950 return false;
2951 }
2952 break;
2953
2954 case GL_OBJECT_LINEAR_CHROMIUM:
2955 case GL_EYE_LINEAR_CHROMIUM:
2956 case GL_CONSTANT_CHROMIUM:
2957 if (components < 1 || components > 4)
2958 {
2959 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2960 return false;
2961 }
2962 if (!coeffs)
2963 {
2964 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2965 return false;
2966 }
2967 break;
2968
2969 default:
2970 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2971 return false;
2972 }
2973
2974 // If the location is -1 then the command is silently ignored
2975 // and no further validation is needed.
2976 if (location == -1)
2977 return true;
2978
2979 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2980
2981 if (!binding.valid)
2982 {
2983 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
2984 return false;
2985 }
2986
2987 if (binding.type != GL_NONE)
2988 {
2989 GLint expectedComponents = 0;
2990 switch (binding.type)
2991 {
2992 case GL_FLOAT:
2993 expectedComponents = 1;
2994 break;
2995 case GL_FLOAT_VEC2:
2996 expectedComponents = 2;
2997 break;
2998 case GL_FLOAT_VEC3:
2999 expectedComponents = 3;
3000 break;
3001 case GL_FLOAT_VEC4:
3002 expectedComponents = 4;
3003 break;
3004 default:
3005 context->handleError(Error(GL_INVALID_OPERATION,
3006 "Fragment input type is not a floating point scalar or vector."));
3007 return false;
3008 }
3009 if (expectedComponents != components && genMode != GL_NONE)
3010 {
3011 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3012 return false;
3013 }
3014 }
3015 return true;
3016}
3017
Jamie Madillc29968b2016-01-20 11:17:23 -05003018} // namespace gl