blob: 9d7129b8d002aea8133ae860cafc3baface9ae65 [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
Martin Radev9d901792016-07-15 15:58:58 +03001604static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1605{
1606 size_t labelLength = 0;
1607
1608 if (length < 0)
1609 {
1610 if (label != nullptr)
1611 {
1612 labelLength = strlen(label);
1613 }
1614 }
1615 else
1616 {
1617 labelLength = static_cast<size_t>(length);
1618 }
1619
1620 if (labelLength > context->getExtensions().maxLabelLength)
1621 {
1622 context->handleError(
1623 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1624 return false;
1625 }
1626
1627 return true;
1628}
1629
Geoff Lange102fee2015-12-10 11:23:30 -05001630bool ValidateObjectLabelKHR(Context *context,
1631 GLenum identifier,
1632 GLuint name,
1633 GLsizei length,
1634 const GLchar *label)
1635{
1636 if (!context->getExtensions().debug)
1637 {
Jamie Madill437fa652016-05-03 15:13:24 -04001638 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001639 return false;
1640 }
1641
Geoff Lang70d0f492015-12-10 17:45:46 -05001642 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1643 {
1644 return false;
1645 }
1646
Martin Radev9d901792016-07-15 15:58:58 +03001647 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001648 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 return false;
1650 }
1651
Geoff Lange102fee2015-12-10 11:23:30 -05001652 return true;
1653}
1654
1655bool ValidateGetObjectLabelKHR(Context *context,
1656 GLenum identifier,
1657 GLuint name,
1658 GLsizei bufSize,
1659 GLsizei *length,
1660 GLchar *label)
1661{
1662 if (!context->getExtensions().debug)
1663 {
Jamie Madill437fa652016-05-03 15:13:24 -04001664 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001665 return false;
1666 }
1667
Geoff Lang70d0f492015-12-10 17:45:46 -05001668 if (bufSize < 0)
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001671 return false;
1672 }
1673
1674 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1675 {
1676 return false;
1677 }
1678
Martin Radev9d901792016-07-15 15:58:58 +03001679 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001680}
1681
1682static bool ValidateObjectPtrName(Context *context, const void *ptr)
1683{
1684 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1685 {
Jamie Madill437fa652016-05-03 15:13:24 -04001686 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001687 return false;
1688 }
1689
Geoff Lange102fee2015-12-10 11:23:30 -05001690 return true;
1691}
1692
1693bool ValidateObjectPtrLabelKHR(Context *context,
1694 const void *ptr,
1695 GLsizei length,
1696 const GLchar *label)
1697{
1698 if (!context->getExtensions().debug)
1699 {
Jamie Madill437fa652016-05-03 15:13:24 -04001700 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001701 return false;
1702 }
1703
Geoff Lang70d0f492015-12-10 17:45:46 -05001704 if (!ValidateObjectPtrName(context, ptr))
1705 {
1706 return false;
1707 }
1708
Martin Radev9d901792016-07-15 15:58:58 +03001709 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001710 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001711 return false;
1712 }
1713
Geoff Lange102fee2015-12-10 11:23:30 -05001714 return true;
1715}
1716
1717bool ValidateGetObjectPtrLabelKHR(Context *context,
1718 const void *ptr,
1719 GLsizei bufSize,
1720 GLsizei *length,
1721 GLchar *label)
1722{
1723 if (!context->getExtensions().debug)
1724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001726 return false;
1727 }
1728
Geoff Lang70d0f492015-12-10 17:45:46 -05001729 if (bufSize < 0)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001732 return false;
1733 }
1734
1735 if (!ValidateObjectPtrName(context, ptr))
1736 {
1737 return false;
1738 }
1739
Martin Radev9d901792016-07-15 15:58:58 +03001740 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001741}
1742
1743bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1744{
1745 if (!context->getExtensions().debug)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001748 return false;
1749 }
1750
Geoff Lang70d0f492015-12-10 17:45:46 -05001751 // TODO: represent this in Context::getQueryParameterInfo.
1752 switch (pname)
1753 {
1754 case GL_DEBUG_CALLBACK_FUNCTION:
1755 case GL_DEBUG_CALLBACK_USER_PARAM:
1756 break;
1757
1758 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001760 return false;
1761 }
1762
Geoff Lange102fee2015-12-10 11:23:30 -05001763 return true;
1764}
Jamie Madillc29968b2016-01-20 11:17:23 -05001765
1766bool ValidateBlitFramebufferANGLE(Context *context,
1767 GLint srcX0,
1768 GLint srcY0,
1769 GLint srcX1,
1770 GLint srcY1,
1771 GLint dstX0,
1772 GLint dstY0,
1773 GLint dstX1,
1774 GLint dstY1,
1775 GLbitfield mask,
1776 GLenum filter)
1777{
1778 if (!context->getExtensions().framebufferBlit)
1779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
1784 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1785 {
1786 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001787 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001788 GL_INVALID_OPERATION,
1789 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1790 return false;
1791 }
1792
1793 if (filter == GL_LINEAR)
1794 {
Jamie Madill437fa652016-05-03 15:13:24 -04001795 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001796 return false;
1797 }
1798
Jamie Madill51f40ec2016-06-15 14:06:00 -04001799 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1800 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001801
1802 if (mask & GL_COLOR_BUFFER_BIT)
1803 {
1804 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1805 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1806
1807 if (readColorAttachment && drawColorAttachment)
1808 {
1809 if (!(readColorAttachment->type() == GL_TEXTURE &&
1810 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1811 readColorAttachment->type() != GL_RENDERBUFFER &&
1812 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1813 {
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001815 return false;
1816 }
1817
Geoff Langa15472a2015-08-11 11:48:03 -04001818 for (size_t drawbufferIdx = 0;
1819 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001820 {
Geoff Langa15472a2015-08-11 11:48:03 -04001821 const FramebufferAttachment *attachment =
1822 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1823 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001824 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001825 if (!(attachment->type() == GL_TEXTURE &&
1826 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1827 attachment->type() != GL_RENDERBUFFER &&
1828 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1829 {
Jamie Madill437fa652016-05-03 15:13:24 -04001830 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001831 return false;
1832 }
1833
1834 // Return an error if the destination formats do not match
1835 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001838 return false;
1839 }
1840 }
1841 }
1842
Jamie Madill51f40ec2016-06-15 14:06:00 -04001843 if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05001844 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1845 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1846 {
Jamie Madill437fa652016-05-03 15:13:24 -04001847 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001848 return false;
1849 }
1850 }
1851 }
1852
1853 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1854 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1855 for (size_t i = 0; i < 2; i++)
1856 {
1857 if (mask & masks[i])
1858 {
1859 const FramebufferAttachment *readBuffer =
1860 readFramebuffer->getAttachment(attachments[i]);
1861 const FramebufferAttachment *drawBuffer =
1862 drawFramebuffer->getAttachment(attachments[i]);
1863
1864 if (readBuffer && drawBuffer)
1865 {
1866 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1867 dstX0, dstY0, dstX1, dstY1))
1868 {
1869 // only whole-buffer copies are permitted
1870 ERR(
1871 "Only whole-buffer depth and stencil blits are supported by this "
1872 "implementation.");
Jamie Madill437fa652016-05-03 15:13:24 -04001873 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001874 return false;
1875 }
1876
1877 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882 }
1883 }
1884 }
1885
1886 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1887 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001888}
Jamie Madillc29968b2016-01-20 11:17:23 -05001889
1890bool ValidateClear(ValidationContext *context, GLbitfield mask)
1891{
Jamie Madill51f40ec2016-06-15 14:06:00 -04001892 auto fbo = context->getGLState().getDrawFramebuffer();
1893 if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05001894 {
Jamie Madill437fa652016-05-03 15:13:24 -04001895 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05001896 return false;
1897 }
1898
1899 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1900 {
Jamie Madill437fa652016-05-03 15:13:24 -04001901 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05001902 return false;
1903 }
1904
1905 return true;
1906}
1907
1908bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1909{
1910 if (!context->getExtensions().drawBuffers)
1911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001913 return false;
1914 }
1915
1916 return ValidateDrawBuffersBase(context, n, bufs);
1917}
1918
Jamie Madill73a84962016-02-12 09:27:23 -05001919bool ValidateTexImage2D(Context *context,
1920 GLenum target,
1921 GLint level,
1922 GLint internalformat,
1923 GLsizei width,
1924 GLsizei height,
1925 GLint border,
1926 GLenum format,
1927 GLenum type,
1928 const GLvoid *pixels)
1929{
1930 if (context->getClientVersion() < 3)
1931 {
1932 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1933 0, 0, width, height, border, format, type, pixels);
1934 }
1935
1936 ASSERT(context->getClientVersion() >= 3);
1937 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1938 0, 0, width, height, 1, border, format, type, pixels);
1939}
1940
1941bool ValidateTexSubImage2D(Context *context,
1942 GLenum target,
1943 GLint level,
1944 GLint xoffset,
1945 GLint yoffset,
1946 GLsizei width,
1947 GLsizei height,
1948 GLenum format,
1949 GLenum type,
1950 const GLvoid *pixels)
1951{
1952
1953 if (context->getClientVersion() < 3)
1954 {
1955 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1956 yoffset, width, height, 0, format, type, pixels);
1957 }
1958
1959 ASSERT(context->getClientVersion() >= 3);
1960 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1961 yoffset, 0, width, height, 1, 0, format, type, pixels);
1962}
1963
1964bool ValidateCompressedTexImage2D(Context *context,
1965 GLenum target,
1966 GLint level,
1967 GLenum internalformat,
1968 GLsizei width,
1969 GLsizei height,
1970 GLint border,
1971 GLsizei imageSize,
1972 const GLvoid *data)
1973{
1974 if (context->getClientVersion() < 3)
1975 {
1976 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1977 0, width, height, border, GL_NONE, GL_NONE, data))
1978 {
1979 return false;
1980 }
1981 }
1982 else
1983 {
1984 ASSERT(context->getClientVersion() >= 3);
1985 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1986 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1987 data))
1988 {
1989 return false;
1990 }
1991 }
1992
1993 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04001994 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001995 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04001996 if (blockSizeOrErr.isError())
1997 {
1998 context->handleError(blockSizeOrErr.getError());
1999 return false;
2000 }
2001
2002 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002003 {
Jamie Madill437fa652016-05-03 15:13:24 -04002004 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002005 return false;
2006 }
2007
2008 return true;
2009}
2010
2011bool ValidateCompressedTexSubImage2D(Context *context,
2012 GLenum target,
2013 GLint level,
2014 GLint xoffset,
2015 GLint yoffset,
2016 GLsizei width,
2017 GLsizei height,
2018 GLenum format,
2019 GLsizei imageSize,
2020 const GLvoid *data)
2021{
2022 if (context->getClientVersion() < 3)
2023 {
2024 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2025 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
2026 {
2027 return false;
2028 }
2029 }
2030 else
2031 {
2032 ASSERT(context->getClientVersion() >= 3);
2033 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2034 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
2035 data))
2036 {
2037 return false;
2038 }
2039 }
2040
2041 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002042 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002043 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002044 if (blockSizeOrErr.isError())
2045 {
2046 context->handleError(blockSizeOrErr.getError());
2047 return false;
2048 }
2049
2050 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002053 return false;
2054 }
2055
2056 return true;
2057}
2058
Olli Etuaho4f667482016-03-30 15:56:35 +03002059bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2060{
2061 if (!context->getExtensions().mapBuffer)
2062 {
Jamie Madill437fa652016-05-03 15:13:24 -04002063 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002064 return false;
2065 }
2066
2067 return ValidateGetBufferPointervBase(context, target, pname, params);
2068}
2069
2070bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2071{
2072 if (!context->getExtensions().mapBuffer)
2073 {
Jamie Madill437fa652016-05-03 15:13:24 -04002074 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002075 return false;
2076 }
2077
2078 if (!ValidBufferTarget(context, target))
2079 {
Jamie Madill437fa652016-05-03 15:13:24 -04002080 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002081 return false;
2082 }
2083
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002084 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002085
2086 if (buffer == nullptr)
2087 {
Jamie Madill437fa652016-05-03 15:13:24 -04002088 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002089 return false;
2090 }
2091
2092 if (access != GL_WRITE_ONLY_OES)
2093 {
Jamie Madill437fa652016-05-03 15:13:24 -04002094 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002095 return false;
2096 }
2097
2098 if (buffer->isMapped())
2099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002101 return false;
2102 }
2103
2104 return true;
2105}
2106
2107bool ValidateUnmapBufferOES(Context *context, GLenum target)
2108{
2109 if (!context->getExtensions().mapBuffer)
2110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002112 return false;
2113 }
2114
2115 return ValidateUnmapBufferBase(context, target);
2116}
2117
2118bool ValidateMapBufferRangeEXT(Context *context,
2119 GLenum target,
2120 GLintptr offset,
2121 GLsizeiptr length,
2122 GLbitfield access)
2123{
2124 if (!context->getExtensions().mapBufferRange)
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002127 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2128 return false;
2129 }
2130
2131 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2132}
2133
2134bool ValidateFlushMappedBufferRangeEXT(Context *context,
2135 GLenum target,
2136 GLintptr offset,
2137 GLsizeiptr length)
2138{
2139 if (!context->getExtensions().mapBufferRange)
2140 {
Jamie Madill437fa652016-05-03 15:13:24 -04002141 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002142 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2143 return false;
2144 }
2145
2146 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2147}
2148
Ian Ewell54f87462016-03-10 13:47:21 -05002149bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2150{
2151 Texture *textureObject = context->getTexture(texture);
2152 if (textureObject && textureObject->getTarget() != target && texture != 0)
2153 {
Jamie Madill437fa652016-05-03 15:13:24 -04002154 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002155 return false;
2156 }
2157
2158 switch (target)
2159 {
2160 case GL_TEXTURE_2D:
2161 case GL_TEXTURE_CUBE_MAP:
2162 break;
2163
2164 case GL_TEXTURE_3D:
2165 case GL_TEXTURE_2D_ARRAY:
2166 if (context->getClientVersion() < 3)
2167 {
Jamie Madill437fa652016-05-03 15:13:24 -04002168 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002169 return false;
2170 }
2171 break;
2172 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002173 if (!context->getExtensions().eglImageExternal &&
2174 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002175 {
Jamie Madill437fa652016-05-03 15:13:24 -04002176 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002177 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2178 return false;
2179 }
2180 break;
2181 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002183 return false;
2184 }
2185
2186 return true;
2187}
2188
Geoff Langd8605522016-04-13 10:19:12 -04002189bool ValidateBindUniformLocationCHROMIUM(Context *context,
2190 GLuint program,
2191 GLint location,
2192 const GLchar *name)
2193{
2194 if (!context->getExtensions().bindUniformLocation)
2195 {
Jamie Madill437fa652016-05-03 15:13:24 -04002196 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002197 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2198 return false;
2199 }
2200
2201 Program *programObject = GetValidProgram(context, program);
2202 if (!programObject)
2203 {
2204 return false;
2205 }
2206
2207 if (location < 0)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002210 return false;
2211 }
2212
2213 const Caps &caps = context->getCaps();
2214 if (static_cast<size_t>(location) >=
2215 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002218 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2219 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2220 return false;
2221 }
2222
2223 if (strncmp(name, "gl_", 3) == 0)
2224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002226 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2227 return false;
2228 }
2229
2230 return true;
2231}
2232
Jamie Madille2e406c2016-06-02 13:04:10 -04002233bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002234{
2235 if (!context->getExtensions().framebufferMixedSamples)
2236 {
2237 context->handleError(
2238 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2239 return false;
2240 }
2241 switch (components)
2242 {
2243 case GL_RGB:
2244 case GL_RGBA:
2245 case GL_ALPHA:
2246 case GL_NONE:
2247 break;
2248 default:
2249 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002250 Error(GL_INVALID_ENUM,
2251 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002252 return false;
2253 }
2254
2255 return true;
2256}
2257
Sami Väisänene45e53b2016-05-25 10:36:04 +03002258// CHROMIUM_path_rendering
2259
2260bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2261{
2262 if (!context->getExtensions().pathRendering)
2263 {
2264 context->handleError(
2265 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2266 return false;
2267 }
2268 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2269 {
2270 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2271 return false;
2272 }
2273 if (matrix == nullptr)
2274 {
2275 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2276 return false;
2277 }
2278 return true;
2279}
2280
2281bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2282{
2283 if (!context->getExtensions().pathRendering)
2284 {
2285 context->handleError(
2286 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2287 return false;
2288 }
2289 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2290 {
2291 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2292 return false;
2293 }
2294 return true;
2295}
2296
2297bool ValidateGenPaths(Context *context, GLsizei range)
2298{
2299 if (!context->getExtensions().pathRendering)
2300 {
2301 context->handleError(
2302 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2303 return false;
2304 }
2305
2306 // range = 0 is undefined in NV_path_rendering.
2307 // we add stricter semantic check here and require a non zero positive range.
2308 if (range <= 0)
2309 {
2310 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2311 return false;
2312 }
2313
2314 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2315 {
2316 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2317 return false;
2318 }
2319
2320 return true;
2321}
2322
2323bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2324{
2325 if (!context->getExtensions().pathRendering)
2326 {
2327 context->handleError(
2328 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2329 return false;
2330 }
2331
2332 // range = 0 is undefined in NV_path_rendering.
2333 // we add stricter semantic check here and require a non zero positive range.
2334 if (range <= 0)
2335 {
2336 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2337 return false;
2338 }
2339
2340 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2341 checkedRange += range;
2342
2343 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2344 {
2345 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2346 return false;
2347 }
2348 return true;
2349}
2350
2351bool ValidatePathCommands(Context *context,
2352 GLuint path,
2353 GLsizei numCommands,
2354 const GLubyte *commands,
2355 GLsizei numCoords,
2356 GLenum coordType,
2357 const void *coords)
2358{
2359 if (!context->getExtensions().pathRendering)
2360 {
2361 context->handleError(
2362 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2363 return false;
2364 }
2365 if (!context->hasPath(path))
2366 {
2367 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2368 return false;
2369 }
2370
2371 if (numCommands < 0)
2372 {
2373 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2374 return false;
2375 }
2376 else if (numCommands > 0)
2377 {
2378 if (!commands)
2379 {
2380 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2381 return false;
2382 }
2383 }
2384
2385 if (numCoords < 0)
2386 {
2387 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2388 return false;
2389 }
2390 else if (numCoords > 0)
2391 {
2392 if (!coords)
2393 {
2394 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2395 return false;
2396 }
2397 }
2398
2399 std::uint32_t coordTypeSize = 0;
2400 switch (coordType)
2401 {
2402 case GL_BYTE:
2403 coordTypeSize = sizeof(GLbyte);
2404 break;
2405
2406 case GL_UNSIGNED_BYTE:
2407 coordTypeSize = sizeof(GLubyte);
2408 break;
2409
2410 case GL_SHORT:
2411 coordTypeSize = sizeof(GLshort);
2412 break;
2413
2414 case GL_UNSIGNED_SHORT:
2415 coordTypeSize = sizeof(GLushort);
2416 break;
2417
2418 case GL_FLOAT:
2419 coordTypeSize = sizeof(GLfloat);
2420 break;
2421
2422 default:
2423 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2424 return false;
2425 }
2426
2427 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2428 checkedSize += (coordTypeSize * numCoords);
2429 if (!checkedSize.IsValid())
2430 {
2431 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2432 return false;
2433 }
2434
2435 // early return skips command data validation when it doesn't exist.
2436 if (!commands)
2437 return true;
2438
2439 GLsizei expectedNumCoords = 0;
2440 for (GLsizei i = 0; i < numCommands; ++i)
2441 {
2442 switch (commands[i])
2443 {
2444 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2445 break;
2446 case GL_MOVE_TO_CHROMIUM:
2447 case GL_LINE_TO_CHROMIUM:
2448 expectedNumCoords += 2;
2449 break;
2450 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2451 expectedNumCoords += 4;
2452 break;
2453 case GL_CUBIC_CURVE_TO_CHROMIUM:
2454 expectedNumCoords += 6;
2455 break;
2456 case GL_CONIC_CURVE_TO_CHROMIUM:
2457 expectedNumCoords += 5;
2458 break;
2459 default:
2460 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2461 return false;
2462 }
2463 }
2464 if (expectedNumCoords != numCoords)
2465 {
2466 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2467 return false;
2468 }
2469
2470 return true;
2471}
2472
2473bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2474{
2475 if (!context->getExtensions().pathRendering)
2476 {
2477 context->handleError(
2478 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2479 return false;
2480 }
2481 if (!context->hasPath(path))
2482 {
2483 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2484 return false;
2485 }
2486
2487 switch (pname)
2488 {
2489 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2490 if (value < 0.0f)
2491 {
2492 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2493 return false;
2494 }
2495 break;
2496 case GL_PATH_END_CAPS_CHROMIUM:
2497 switch (static_cast<GLenum>(value))
2498 {
2499 case GL_FLAT_CHROMIUM:
2500 case GL_SQUARE_CHROMIUM:
2501 case GL_ROUND_CHROMIUM:
2502 break;
2503 default:
2504 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2505 return false;
2506 }
2507 break;
2508 case GL_PATH_JOIN_STYLE_CHROMIUM:
2509 switch (static_cast<GLenum>(value))
2510 {
2511 case GL_MITER_REVERT_CHROMIUM:
2512 case GL_BEVEL_CHROMIUM:
2513 case GL_ROUND_CHROMIUM:
2514 break;
2515 default:
2516 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2517 return false;
2518 }
2519 case GL_PATH_MITER_LIMIT_CHROMIUM:
2520 if (value < 0.0f)
2521 {
2522 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2523 return false;
2524 }
2525 break;
2526
2527 case GL_PATH_STROKE_BOUND_CHROMIUM:
2528 // no errors, only clamping.
2529 break;
2530
2531 default:
2532 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2533 return false;
2534 }
2535 return true;
2536}
2537
2538bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2539{
2540 if (!context->getExtensions().pathRendering)
2541 {
2542 context->handleError(
2543 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2544 return false;
2545 }
2546
2547 if (!context->hasPath(path))
2548 {
2549 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2550 return false;
2551 }
2552 if (!value)
2553 {
2554 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2555 return false;
2556 }
2557
2558 switch (pname)
2559 {
2560 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2561 case GL_PATH_END_CAPS_CHROMIUM:
2562 case GL_PATH_JOIN_STYLE_CHROMIUM:
2563 case GL_PATH_MITER_LIMIT_CHROMIUM:
2564 case GL_PATH_STROKE_BOUND_CHROMIUM:
2565 break;
2566
2567 default:
2568 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2569 return false;
2570 }
2571
2572 return true;
2573}
2574
2575bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2576{
2577 if (!context->getExtensions().pathRendering)
2578 {
2579 context->handleError(
2580 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2581 return false;
2582 }
2583
2584 switch (func)
2585 {
2586 case GL_NEVER:
2587 case GL_ALWAYS:
2588 case GL_LESS:
2589 case GL_LEQUAL:
2590 case GL_EQUAL:
2591 case GL_GEQUAL:
2592 case GL_GREATER:
2593 case GL_NOTEQUAL:
2594 break;
2595 default:
2596 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2597 return false;
2598 }
2599
2600 return true;
2601}
2602
2603// Note that the spec specifies that for the path drawing commands
2604// if the path object is not an existing path object the command
2605// does nothing and no error is generated.
2606// However if the path object exists but has not been specified any
2607// commands then an error is generated.
2608
2609bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2610{
2611 if (!context->getExtensions().pathRendering)
2612 {
2613 context->handleError(
2614 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2615 return false;
2616 }
2617 if (context->hasPath(path) && !context->hasPathData(path))
2618 {
2619 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2620 return false;
2621 }
2622
2623 switch (fillMode)
2624 {
2625 case GL_COUNT_UP_CHROMIUM:
2626 case GL_COUNT_DOWN_CHROMIUM:
2627 break;
2628 default:
2629 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2630 return false;
2631 }
2632
2633 if (!isPow2(mask + 1))
2634 {
2635 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2636 return false;
2637 }
2638
2639 return true;
2640}
2641
2642bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2643{
2644 if (!context->getExtensions().pathRendering)
2645 {
2646 context->handleError(
2647 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2648 return false;
2649 }
2650 if (context->hasPath(path) && !context->hasPathData(path))
2651 {
2652 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2653 return false;
2654 }
2655
2656 return true;
2657}
2658
2659bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2660{
2661 if (!context->getExtensions().pathRendering)
2662 {
2663 context->handleError(
2664 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2665 return false;
2666 }
2667 if (context->hasPath(path) && !context->hasPathData(path))
2668 {
2669 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2670 return false;
2671 }
2672
2673 switch (coverMode)
2674 {
2675 case GL_CONVEX_HULL_CHROMIUM:
2676 case GL_BOUNDING_BOX_CHROMIUM:
2677 break;
2678 default:
2679 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2680 return false;
2681 }
2682 return true;
2683}
2684
2685bool ValidateStencilThenCoverFillPath(Context *context,
2686 GLuint path,
2687 GLenum fillMode,
2688 GLuint mask,
2689 GLenum coverMode)
2690{
2691 return ValidateStencilFillPath(context, path, fillMode, mask) &&
2692 ValidateCoverPath(context, path, coverMode);
2693}
2694
2695bool ValidateStencilThenCoverStrokePath(Context *context,
2696 GLuint path,
2697 GLint reference,
2698 GLuint mask,
2699 GLenum coverMode)
2700{
2701 return ValidateStencilStrokePath(context, path, reference, mask) &&
2702 ValidateCoverPath(context, path, coverMode);
2703}
2704
2705bool ValidateIsPath(Context *context)
2706{
2707 if (!context->getExtensions().pathRendering)
2708 {
2709 context->handleError(
2710 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2711 return false;
2712 }
2713 return true;
2714}
2715
Sami Väisänend59ca052016-06-21 16:10:00 +03002716bool ValidateCoverFillPathInstanced(Context *context,
2717 GLsizei numPaths,
2718 GLenum pathNameType,
2719 const void *paths,
2720 GLuint pathBase,
2721 GLenum coverMode,
2722 GLenum transformType,
2723 const GLfloat *transformValues)
2724{
2725 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2726 transformType, transformValues))
2727 return false;
2728
2729 switch (coverMode)
2730 {
2731 case GL_CONVEX_HULL_CHROMIUM:
2732 case GL_BOUNDING_BOX_CHROMIUM:
2733 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2734 break;
2735 default:
2736 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2737 return false;
2738 }
2739
2740 return true;
2741}
2742
2743bool ValidateCoverStrokePathInstanced(Context *context,
2744 GLsizei numPaths,
2745 GLenum pathNameType,
2746 const void *paths,
2747 GLuint pathBase,
2748 GLenum coverMode,
2749 GLenum transformType,
2750 const GLfloat *transformValues)
2751{
2752 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2753 transformType, transformValues))
2754 return false;
2755
2756 switch (coverMode)
2757 {
2758 case GL_CONVEX_HULL_CHROMIUM:
2759 case GL_BOUNDING_BOX_CHROMIUM:
2760 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2761 break;
2762 default:
2763 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2764 return false;
2765 }
2766
2767 return true;
2768}
2769
2770bool ValidateStencilFillPathInstanced(Context *context,
2771 GLsizei numPaths,
2772 GLenum pathNameType,
2773 const void *paths,
2774 GLuint pathBase,
2775 GLenum fillMode,
2776 GLuint mask,
2777 GLenum transformType,
2778 const GLfloat *transformValues)
2779{
2780
2781 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2782 transformType, transformValues))
2783 return false;
2784
2785 switch (fillMode)
2786 {
2787 case GL_COUNT_UP_CHROMIUM:
2788 case GL_COUNT_DOWN_CHROMIUM:
2789 break;
2790 default:
2791 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2792 return false;
2793 }
2794 if (!isPow2(mask + 1))
2795 {
2796 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2797 return false;
2798 }
2799 return true;
2800}
2801
2802bool ValidateStencilStrokePathInstanced(Context *context,
2803 GLsizei numPaths,
2804 GLenum pathNameType,
2805 const void *paths,
2806 GLuint pathBase,
2807 GLint reference,
2808 GLuint mask,
2809 GLenum transformType,
2810 const GLfloat *transformValues)
2811{
2812 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2813 transformType, transformValues))
2814 return false;
2815
2816 // no more validation here.
2817
2818 return true;
2819}
2820
2821bool ValidateStencilThenCoverFillPathInstanced(Context *context,
2822 GLsizei numPaths,
2823 GLenum pathNameType,
2824 const void *paths,
2825 GLuint pathBase,
2826 GLenum fillMode,
2827 GLuint mask,
2828 GLenum coverMode,
2829 GLenum transformType,
2830 const GLfloat *transformValues)
2831{
2832 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2833 transformType, transformValues))
2834 return false;
2835
2836 switch (coverMode)
2837 {
2838 case GL_CONVEX_HULL_CHROMIUM:
2839 case GL_BOUNDING_BOX_CHROMIUM:
2840 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2841 break;
2842 default:
2843 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2844 return false;
2845 }
2846
2847 switch (fillMode)
2848 {
2849 case GL_COUNT_UP_CHROMIUM:
2850 case GL_COUNT_DOWN_CHROMIUM:
2851 break;
2852 default:
2853 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2854 return false;
2855 }
2856 if (!isPow2(mask + 1))
2857 {
2858 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2859 return false;
2860 }
2861
2862 return true;
2863}
2864
2865bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
2866 GLsizei numPaths,
2867 GLenum pathNameType,
2868 const void *paths,
2869 GLuint pathBase,
2870 GLint reference,
2871 GLuint mask,
2872 GLenum coverMode,
2873 GLenum transformType,
2874 const GLfloat *transformValues)
2875{
2876 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
2877 transformType, transformValues))
2878 return false;
2879
2880 switch (coverMode)
2881 {
2882 case GL_CONVEX_HULL_CHROMIUM:
2883 case GL_BOUNDING_BOX_CHROMIUM:
2884 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
2885 break;
2886 default:
2887 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2888 return false;
2889 }
2890
2891 return true;
2892}
2893
Sami Väisänen46eaa942016-06-29 10:26:37 +03002894bool ValidateBindFragmentInputLocation(Context *context,
2895 GLuint program,
2896 GLint location,
2897 const GLchar *name)
2898{
2899 if (!context->getExtensions().pathRendering)
2900 {
2901 context->handleError(
2902 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2903 return false;
2904 }
2905
2906 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
2907 if (location >= MaxLocation)
2908 {
2909 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
2910 return false;
2911 }
2912
2913 const auto *programObject = context->getProgram(program);
2914 if (!programObject)
2915 {
2916 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2917 return false;
2918 }
2919
2920 if (!name)
2921 {
2922 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
2923 return false;
2924 }
2925
2926 if (angle::BeginsWith(name, "gl_"))
2927 {
2928 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
2929 return false;
2930 }
2931
2932 return true;
2933}
2934
2935bool ValidateProgramPathFragmentInputGen(Context *context,
2936 GLuint program,
2937 GLint location,
2938 GLenum genMode,
2939 GLint components,
2940 const GLfloat *coeffs)
2941{
2942 if (!context->getExtensions().pathRendering)
2943 {
2944 context->handleError(
2945 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2946 return false;
2947 }
2948
2949 const auto *programObject = context->getProgram(program);
2950 if (!programObject || programObject->isFlaggedForDeletion())
2951 {
2952 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
2953 return false;
2954 }
2955
2956 if (!programObject->isLinked())
2957 {
2958 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2959 return false;
2960 }
2961
2962 switch (genMode)
2963 {
2964 case GL_NONE:
2965 if (components != 0)
2966 {
2967 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2968 return false;
2969 }
2970 break;
2971
2972 case GL_OBJECT_LINEAR_CHROMIUM:
2973 case GL_EYE_LINEAR_CHROMIUM:
2974 case GL_CONSTANT_CHROMIUM:
2975 if (components < 1 || components > 4)
2976 {
2977 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
2978 return false;
2979 }
2980 if (!coeffs)
2981 {
2982 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
2983 return false;
2984 }
2985 break;
2986
2987 default:
2988 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
2989 return false;
2990 }
2991
2992 // If the location is -1 then the command is silently ignored
2993 // and no further validation is needed.
2994 if (location == -1)
2995 return true;
2996
2997 const auto &binding = programObject->getFragmentInputBindingInfo(location);
2998
2999 if (!binding.valid)
3000 {
3001 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3002 return false;
3003 }
3004
3005 if (binding.type != GL_NONE)
3006 {
3007 GLint expectedComponents = 0;
3008 switch (binding.type)
3009 {
3010 case GL_FLOAT:
3011 expectedComponents = 1;
3012 break;
3013 case GL_FLOAT_VEC2:
3014 expectedComponents = 2;
3015 break;
3016 case GL_FLOAT_VEC3:
3017 expectedComponents = 3;
3018 break;
3019 case GL_FLOAT_VEC4:
3020 expectedComponents = 4;
3021 break;
3022 default:
3023 context->handleError(Error(GL_INVALID_OPERATION,
3024 "Fragment input type is not a floating point scalar or vector."));
3025 return false;
3026 }
3027 if (expectedComponents != components && genMode != GL_NONE)
3028 {
3029 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3030 return false;
3031 }
3032 }
3033 return true;
3034}
3035
Jamie Madillc29968b2016-01-20 11:17:23 -05003036} // namespace gl